phamnazage-jpg 35447be934
Some checks failed
CI / Build & Test (push) Has been cancelled
CI / Lint (push) Has been cancelled
CI / Security Scan (push) Has been cancelled
CI / Docker Build (push) Has been cancelled
CI / Release (push) Has been cancelled
feat(deploy): add CRM-only online deployment to remote43
- scripts/deploy/deploy_crm_only.sh: 单进程部署 sub2api-cn-relay-manager
  CRM 控制面到 remote43,不依赖 sub2api host / PG / Redis 容器。
  复用 scripts/deploy/remote43_patched_stack_lib.sh 的 env 渲染
  (render_remote43_crm_env),render_crm_only_bootstrap 用 $\{VAR\} 占位符 +
  sed 注入避开 set -u + unquoted-heredoc 边缘问题。
  部署前先 kill 老进程 (再 scp 二进制) 避免 ELF overwrite 失败。

- docs/DEPLOYMENT.md: 加 '在线部署节点' 段,记录 stack / 端口 / 入口 / 验证。
- docs/EXECUTION_BOARD.md: 顶部加 'Latest Online Stack' 段。
- artifacts/online-deploy-20260602/: 本次真实部署的证据
  - 01-local-build.txt: 本地 server 二进制 md5 + git head
  - 02-remote-inspect.txt: 远端 process / port / db tables
  - 03-crm-api-checks.txt: /healthz /api/packs /api/hosts /metrics 真实响应
  - 04-portal-public.txt: sub.tksea.top 公共入口
  - 05-quality-gates.txt: gofmt / vet / test -race / integration
  - manifest.json: 结构化汇总

验证(2026-06-02 21:32-21:43):
- /healthz: HTTP 200 'ok'
- /api/packs (Bearer): HTTP 200 '{"packs":[]}'
- /api/hosts (Bearer): HTTP 200 '{"hosts":[]}'
- /api/packs (no auth): HTTP 401
- /metrics (Prometheus): HTTP 200,含 active_hosts/active_providers/
  db_connections_active + Go runtime
- sub.tksea.top/portal/: HTTP 200
- sub.tksea.top/portal-admin-api/healthz: HTTP 200 'ok'(反代到 CRM)
- go test -race ./internal/... ./tests/integration/...: PASS
- gofmt / go vet: 干净
2026-06-02 21:46:39 +08:00
2026-05-12 21:46:19 +08:00

sub2api-cn-relay-manager

sub2api-cn-relay-manager 是一个独立于 sub2api 宿主仓库的外部伴生安装器 / 控制面项目。

目标不是修改 sub2api,也不是把国产模型能力硬塞进宿主源码,而是通过 sub2api 已有的管理 API把“国产模型 OpenAI 兼容中转能力”以独立交付物的形式安装到任意一台已部署的 sub2api 实例上。

项目定位

  • 宿主:第三方开源系统 sub2api
  • 约束:不修改宿主代码,不 fork 宿主,不要求宿主内置原生插件运行时
  • 交付:一个独立控制面项目 + 一个或多个 model_pack
  • 结果:管理员可一键导入多个国产模型 key普通用户继续只用 sub2api 标准 API

这个项目解决的问题

  • 不同机器部署了 sub2api 后,如何用同一套交付物补齐国产模型中转能力
  • 如何把多个国产模型 key 批量导入为可用的宿主资源
  • 如何在不改宿主的前提下实现热生效、探测、对账和漂移发现
  • 如何让普通用户完全无感,继续走 sub2api 标准接口

非目标

  • 不做宿主原生插件系统
  • 不做任意第三方 Go 代码动态加载
  • 不要求宿主识别“插件”概念
  • 不接管宿主网关流量

目录结构

sub2api-cn-relay-manager/
  cmd/                         # CLI / server 入口
  internal/                    # 控制面核心实现
  packs/                       # provider packs / overlay metadata
  deploy/                      # 部署资产portal 静态页、Nginx 模板)
  scripts/                     # deploy / acceptance / test 三层脚本
  docs/                        # 真相入口、执行板、runbook、目录说明
  tests/                       # 集成测试
  artifacts/                   # 真实验收证据与归档
  web/                         # 预留给未来管理端前端

如果你想看更细的目录职责,而不是只看一级树结构,读:

交付模型

本项目最终会拆成两个可独立发布的产物:

  1. sub2api-cn-relay-manager

    • 外部控制面 / 安装器
    • 连接已有 sub2api
    • 安装模型包
    • 调用宿主管理 API 创建资源
    • 做 smoke test、对账和状态展示
  2. model_pack

    • 只包含 provider 定义、默认模板、导入规则和校验信息
    • 不携带宿主执行代码
    • 可以跨机器复用

当前文档

先读这些:

背景/设计文档:

当前 MVP 能力

当前仓库已经具备一个最小可运行闭环:

  • packs/openai-cn-pack/ 提供真实 pack.json + provider + checksums
  • internal/pack 负责 pack 装载、checksum 校验、provider schema 校验
  • internal/provision 负责多 key 导入编排、账号探测和访问闭环判定
  • cmd/cli import-provider 提供一键导入入口

示例:

go run ./cmd/cli import-provider \
  --host-base-url https://sub2api.example.com \
  --host-api-key <admin-api-key> \
  --pack-dir ./packs/openai-cn-pack \
  --provider-id deepseek \
  --keys sk-a,sk-b \
  --access-mode self_service \
  --access-api-key <user-api-key>

运行方式

服务端:

SUB2API_CRM_ADMIN_TOKEN=replace-me go run ./cmd/server

Docker Compose

cp .env.example .env
# 编辑 .env 中的 SUB2API_CRM_ADMIN_TOKEN
scripts/deploy/build_local_image.sh
docker run --rm -p 8080:8080 \
  --env-file .env \
  -v "$(pwd)/data:/data" \
  sub2api-cn-relay-manager:local
curl -fsS http://127.0.0.1:8080/healthz

真实宿主验收:

CRM_BASE_URL=http://127.0.0.1:8080 \
CRM_ADMIN_TOKEN='<crm-admin-token>' \
HOST_NAME=prod-sub2api \
HOST_BASE_URL=https://sub2api.example.com \
HOST_API_KEY='<sub2api-admin-key>' \
PACK_PATH=/app/packs/openai-cn-pack \
PROVIDER_ID=deepseek \
KEYS=sk-live-1 \
ACCESS_MODE=self_service \
ACCESS_API_KEY='<user-gateway-key>' \
DRY_RUN=1 \
scripts/acceptance/real_host_acceptance.sh
Description
No description provided
Readme 57 MiB
Languages
Go 73.9%
HTML 10.8%
Shell 10.6%
CSS 1.9%
PLpgSQL 1%
Other 1.7%