# doc79 同机拉取式部署配置（1Panel 原生方式，一次性）

> 安全原则：CI 只构建、不部署；任何 AI 与流水线都不允许 SSH 到服务器执行命令。
> 部署由服务器本地定时任务监听 CI 产物目录自动完成。
> 本文档所有操作均通过 **1Panel 网页界面**或管理员本人的终端完成，不依赖 AI 远程执行。

## 架构

```
push main → Gitea Actions（hk runner 构建）→ 部署包发布为 Gitea Release 附件
                                        ↓
1Panel 计划任务（每分钟）运行 deploy-watch.sh → 发现新 release → HTTPS 拉取 deploy.tar.gz
                                        ↓
deploy.sh 原子切换 + 重启容器 + 健康检查（失败自动回滚）
                                        ↓
EdgeOne CDN (HTTPS 终结) → doc79:80 → 1Panel OpenResty 反代 → 127.0.0.1:8080 lunar-server 容器
```

> 产物通过 Gitea Release 分发，与 runner 位置解耦（hk/bt 均可构建）；
> 服务器侧只出站 HTTPS 拉取，无任何入站 SSH。

## 一次性安装步骤（按序执行）

### 1. EdgeOne 回源配置（控制台）

- 回源协议改为 **HTTP**（HTTPS 由 EdgeOne 终结，源站无需证书，消除 525）；
- 回源地址：doc79 公网 IP，端口 80；回源 Host：`lunar.neatcn.com`。

### 2. 1Panel 创建反向代理网站

1Panel → **网站** → 创建网站 → **反向代理**：

- 主域名：`lunar.neatcn.com`
- 代理地址：`http://127.0.0.1:8080`

创建后如需补充请求头，可在站点「配置文件」中加入：

```nginx
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto https;
```

（1Panel 的 OpenResty 默认已带 Host 头转发，以上为可选项。）

### 3. 生产环境变量（切勿写入仓库）

1Panel → **文件** → 进入 `/opt/lunar/production/`（不存在先创建），新建 `.env`：

```ini
SERVER_ENV=production
SERVER_PORT=8080
DB_HOST=<数据库地址>
DB_PORT=3306
DB_USER=<用户名>
DB_PASSWORD=<密码>
DB_NAME=lunar
JWT_SECRET=<强随机值，至少32位>
MINI_APP_ID=<小程序AppID>
MINI_APP_SECRET=<小程序AppSecret>
WECHAT_PAY_APIKEY=<支付API密钥>
WECHAT_PAY_MCHID=<商户号>
ADMIN_PASSWORD=<后台登录密码>
# 注意：不要配置 CORS_ORIGINS 白名单。小程序请求 Origin 为 servicewechat.com，
# 配置白名单会导致跨域头缺失；保持默认（*）即可，鉴权由 JWT/Cookie 保证。
```

文件权限设为 `600`（1Panel 文件管理器右键可改）。

### 4. 1Panel Compose 编排创建容器

1Panel → **容器** → **Compose** → 创建编排，名称 `lunar`，粘贴仓库
[.gitea/deploy/docker-compose.yml](../deploy/docker-compose.yml) 的完整内容后部署。

> 首次部署时 `/opt/lunar/production/current` 尚不存在，容器会启动失败——正常现象。
> 待第 6 步首次部署落盘后，在 1Panel 里重启该容器即可恢复。

### 5. 上传部署脚本

1Panel → **文件** → 进入 `/opt/lunar/scripts/`（不存在先创建），从仓库
`.gitea/scripts/` 上传两个文件并赋予可执行权限（右键 → 权限 755）：

- `deploy.sh`（原子切换 + 健康检查 + 失败回滚）
- `deploy-watch.sh`（产物指纹轮询）

### 6. 1Panel 计划任务触发部署

1Panel → **计划任务** → 创建任务：

- 任务类型：**Shell 脚本**
- 执行周期：固定间隔 1 分钟（或 cron `*/1 * * * *`）
- 脚本内容：

```bash
# 可选：若仓库私有或需要令牌拉取，在 .env 中配置 GITEA_DEPLOY_TOKEN
[ -f /opt/lunar/production/.env ] && set -a && . /opt/lunar/production/.env && set +a
bash /opt/lunar/scripts/deploy-watch.sh
```

保存后可先点「执行」手动跑一次验证（日志在任务详情里查看）。

### 7. 微信公众平台

开发管理 → 服务器域名：将 `https://lunar.neatcn.com` 加入 **request 合法域名**。

## 验证

```bash
curl -s https://lunar.neatcn.com/api/version   # 应返回含 commitSha 的版本 JSON
```

- CI 侧：push 后 Gitea Actions 日志显示"后端构建成功"，Telegram/Discord 收到通知；
- 服务器侧：1Panel 计划任务日志出现"部署成功"；容器日志可见 `lunar-server 1.0.x` 启动行。

## 回滚

- 自动：deploy.sh 健康检查失败会自动恢复 `current.old` 并重启容器；
- 手工：用 `/opt/lunar/backups/` 下的备份包重新执行 `bash /opt/lunar/scripts/deploy.sh <备份包>`；
- 紧急：在 1Panel 容器页直接重启/回退。

## 为什么不用 systemd timer / 裸 nginx / 裸 docker-compose？

doc79 由 1Panel 统一管理：Web 服务是其内置 OpenResty（非系统 nginx）、容器与定时任务
有对应的可视化模块。全部落在 1Panel 能力内，日志、重启、证书都在一个面板里可见可控，
避免绕过平台管理造成"幽灵配置"。
