# 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//providers/.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` host:ubuntu@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 600,root 持有) 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` 访问入口(公网): - 用户 portal:https://sub.tksea.top/portal/ - 管理 portal:https://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`(无 auth,Prometheus 格式)→ 200,含 `active_hosts` `active_providers` `db_connections_active` + Go runtime metrics - `GET /api/packs`(无 auth)→ 401,auth 拦截正常 - 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 - 完整审计日志面板 这些能力若为上线要求,需要单独实现后再升级部署结论。