Files
sub2api-cn-relay-manager/docs/DEPLOYMENT.md
2026-06-04 20:00:03 +08:00

232 lines
9.0 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Sub2API CN Relay Manager 部署指南
## 概览
Sub2API CN Relay Manager 是一个 Go 控制面服务,用于:
- 注册并探测 sub2api 宿主
- 安装 pack / 导入 provider
- 记录 import batch / managed resources / access closure / reconcile 结果
- 执行基于已记录资源集的回滚
当前内置运行面能力以最小生产闭环为主:
- 已内置:`/healthz`、SQLite 状态库、宿主注册与探测、导入/回滚/对账 API
- 未内置:`/metrics`、限流、配额治理、Prometheus/Grafana 集成
## 前置条件
| 组件 | 版本 | 说明 |
|---|---|---|
| Go | 1.22+ | 构建与本地运行 |
| SQLite | 3.40+ | 内嵌状态库,需持久化挂载 |
| Docker / Podman | 4.x+ | 本地容器验收可选 |
| 控制面 Admin Token | - | 调用控制面 API |
| 宿主 Admin 凭据 | - | 注册 host 时写入控制面,用于后续 import / reconcile / rollback |
## 快速启动
```bash
cp .env.example .env
# 至少设置 SUB2API_CRM_ADMIN_TOKEN
docker compose up --build -d
curl -fsS http://127.0.0.1:18081/healthz
```
或本地直接运行:
```bash
SUB2API_CRM_ADMIN_TOKEN=change-me-before-production SUB2API_CRM_LISTEN_ADDR=127.0.0.1:18081 SUB2API_CRM_SQLITE_DSN='file:/tmp/sub2api-cn-relay-manager.db?_foreign_keys=on&_busy_timeout=5000' go run ./cmd/server
```
## 关键配置
| 变量 | 说明 | 示例 |
|---|---|---|
| `SUB2API_CRM_ADMIN_TOKEN` | 控制面 Bearer token | `crm-admin-token` |
| `SUB2API_CRM_LISTEN_ADDR` | 监听地址 | `:18081` |
| `SUB2API_CRM_SQLITE_DSN` | SQLite DSN | `file:/tmp/sub2api-cn-relay-manager.db?_foreign_keys=on&_busy_timeout=5000` |
| `SUB2API_CRM_REPO_ROOT` | provider 草稿发布到 pack/provider 文件时使用的仓库根目录 | `/home/ubuntu/sub2api-cn-relay-manager-git-current` |
## 公网 Portal 资产
如果你还需要同时维护 `sub.tksea.top` 上的用户态 portal不要再把静态页或 Nginx 规则只放在 `/tmp`
- 静态页源码:`deploy/tksea-portal/index.html`
- Nginx 示例:`deploy/tksea-portal/nginx.sub.tksea.top.conf.example`
- 部署脚本:`scripts/deploy/deploy_tksea_portal.sh`
- 资产回归:`scripts/test/test_tksea_portal_assets.sh`
- 浏览器级 smoke`scripts/test/verify_frontend_smoke.sh`
- 前端统一矩阵:`scripts/acceptance/verify_frontend_acceptance_matrix.sh`
- Provider Admin 页面验收:`scripts/acceptance/verify_provider_admin_actions.sh`
当前正式入口:
- `https://sub.tksea.top/portal/`
- `https://sub.tksea.top/portal/admin/`
- 管理首页
- 统一提供“新增模型 / 供应商目录”和“导入供应商帐号”入口
- 当前已支持管理员用户名 / 密码登录;登录成功后浏览器会持有同域 HttpOnly session cookie
- `https://sub.tksea.top/portal/admin/providers.html`
- provider 目录与 preview/import 管理页
- 当前已支持通过 `provider_drafts` API 把 provider manifest 草稿持久化到 CRM SQLite并直接更新 / 删除 / 发布到 pack 仓库
- `https://sub.tksea.top/portal/admin/batch-import.html`
- 结构化 batch-import 入口,当前跳到 legacy 最小管理页
- `https://sub.tksea.top/portal/admin-batch-import.html`
- 最小管理页
- 直接消费 `POST /api/batch-import/runs`
- 直接消费 `GET /api/batch-import/runs/{run_id}`
- 直接消费 `GET /api/batch-import/runs/{run_id}/items`
管理态同域代理:
- `https://sub.tksea.top/portal-admin-api/`
- 反代到 CRM
- 浏览器侧优先走管理员 session同时保留 Bearer admin token 兼容脚本与紧急兜底
- 作用是让静态 admin 页面不必直接访问 remote43 的内网 `18190`
生产稳定基线:
- 当前生产数据面固定为 `https://sub.tksea.top/v1` -> `127.0.0.1:8080`
- 当前生产控制面固定为 `https://sub.tksea.top/portal-admin-api/` -> `127.0.0.1:18190`
- `18169``18173``18191``18192``18193` 只能作为历史/验收栈端口,不得作为公网生产入口
- remote43 只应长期保留一套生产宿主;临时宿主用于验收后必须停止或清理
- 详细规则见 `docs/PRODUCTION_STABILITY_BASELINE.md`
管理员登录配置:
- `SUB2API_CRM_ADMIN_TOKEN`
- 必填
- 继续作为服务端管理 API 的 Bearer token同时也是 session cookie 的签名密钥
- `SUB2API_CRM_ADMIN_USERNAME`
- 可选,默认 `admin`
- `SUB2API_CRM_ADMIN_PASSWORD`
- 可选
- 若未配置,当前实现会回退为“使用 `SUB2API_CRM_ADMIN_TOKEN` 作为登录密码”
- `SUB2API_CRM_ADMIN_SESSION_TTL`
- 可选,默认 `12h`
- 控制浏览器管理态 session 的有效期
当前 provider 草稿发布相关 API
- `POST /api/provider-drafts`
- `GET /api/provider-drafts`
- `GET /api/provider-drafts/{draft_id}`
- `PUT /api/provider-drafts/{draft_id}`
- `DELETE /api/provider-drafts/{draft_id}`
- `POST /api/provider-drafts/{draft_id}/publish`
`providers.html` 页面内显式动作当前推荐独立验收:
- `GET /api/packs`
- `GET /api/hosts`
- `GET /api/packs/{pack_id}/providers`
- `POST /api/providers/{provider_id}/preview-import`
- `POST /api/providers/{provider_id}/import`
- `POST /api/provider-drafts`
- `PUT /api/provider-drafts/{draft_id}`
- `DELETE /api/provider-drafts/{draft_id}`
- `POST /api/provider-drafts/{draft_id}/publish`
对应脚本:
```bash
bash ./scripts/acceptance/verify_provider_admin_actions.sh
```
最小前端门禁:
```bash
bash ./scripts/test/test_tksea_portal_assets.sh
bash ./scripts/test/verify_frontend_smoke.sh
```
`publish` 的运行前提:
- CRM 进程必须配置 `SUB2API_CRM_REPO_ROOT`
- 该目录必须是真实 Git 仓库,而不是普通文件夹
- remote43 当前推荐固定路径:`/home/ubuntu/sub2api-cn-relay-manager-git-current`
- 推荐由 `scripts/deploy/setup_remote43_patched_stack.sh` 统一准备,不要再手工生成带日期后缀的临时 repo 根目录
- 当前实现会原子完成:
- 生成或更新 `packs/<pack_id>/providers/<provider_id>.json`
- bump `pack.json` patch 版本
- 更新 `checksums.txt`
- 校验整个 pack
- `git add` + `git commit`
兼容入口:
- `https://sub.tksea.top/kimi-portal/`
- 当前应保持跳转到 `/portal/`
## 上线前验证
```bash
gofmt -l .
bash ./scripts/test/test_tksea_portal_assets.sh
bash ./scripts/test/verify_frontend_smoke.sh
go vet ./...
go test ./...
go test -race ./...
go test ./tests/integration/... -count=1
go test -cover ./internal/...
```
## 在线部署节点latest online stack
日期2026-06-02
stack`crm-only-20260602_18190`
hostubuntu@43.155.133.187
CRM 端口18190仅 127.0.0.1 监听,不直接对外暴露)
CRM 二进制:`/home/ubuntu/crm-only-20260602_18190/sub2api-cn-relay-manager-server`
CRM env`/home/ubuntu/crm-only-20260602_18190/.env.crm`chmod 600root 持有)
CRM 日志:`/home/ubuntu/crm-only-20260602_18190/crm.log`
CRM 数据库:`/home/ubuntu/crm-only-20260602_18190/sub2api-cn-relay-manager.db`
publish 仓库:`/home/ubuntu/sub2api-cn-relay-manager-git-current`main @ 4ec9dad4
运维 env`/tmp/crm-only-20260602.env`本地chmod 600
部署脚本:`scripts/deploy/deploy_crm_only.sh`
真实验收:见 `artifacts/online-deploy-20260602/manifest.json`
访问入口(公网):
- 用户 portalhttps://sub.tksea.top/portal/
- 管理 portalhttps://sub.tksea.top/portal/admin/
- 管理态同域反代https://sub.tksea.top/portal-admin-api/ → http://127.0.0.1:18190/
- 直接 CRM 访问:必须先开 SSH 隧道跑 `bash /tmp/crm-only-20260602.tunnel.sh`
然后 `set -a; source /tmp/crm-only-20260602.env; set +a`
当前已验证2026-06-02
- `GET /healthz` → 200 `ok`
- `GET /api/packs`Bearer→ 200 `{"packs":[]}`
- `GET /api/hosts`Bearer→ 200 `{"hosts":[]}`
- `GET /metrics`(无 authPrometheus 格式)→ 200`active_hosts` `active_providers` `db_connections_active` + Go runtime metrics
- `GET /api/packs`(无 auth→ 401auth 拦截正常
- SQLite 库初始化出 22 张表schema_migrations 存在
部署步骤(后续重启 / 滚动更新时):
```bash
cd /home/long/project/sub2api-cn-relay-manager
go build -trimpath -ldflags='-s -w' -o server ./cmd/server
STACK_NAME=crm-only-20260602 bash scripts/deploy/deploy_crm_only.sh
# 然后在新终端开隧道
bash /tmp/crm-only-20260602.tunnel.sh
```
## 生产注意事项
- host 注册后,后续 `preview-import / import / reconcile / access / rollback-provider / status / resources / import-batches` 应统一使用 `host_id``host_id` 查询参数,不再依赖临时 `host_base_url` 作为运行时主键。
- 状态库会持久化宿主认证信息;部署时必须把 SQLite 文件放到受限目录并纳入备份/权限管理。
- `rollback-provider` 现在只按已记录的 managed resources 回滚;若缺少批次资源记录,会拒绝危险删除。
- capability probe 已改为无副作用探测,但仍建议先在预生产宿主验证后再接入生产宿主。
## 真实能力边界
当前文档不应宣称以下能力已经内置:
- `/metrics`
- Prometheus / Grafana 接入
- 限流 / quota enforcement
- 完整审计日志面板
这些能力若为上线要求,需要单独实现后再升级部署结论。