zizi a2953b8a2f
Some checks failed
CI / test (push) Has been cancelled
CI / frontend (push) Has been cancelled
CI / golangci-lint (push) Has been cancelled
Security Scan / backend-security (push) Has been cancelled
Security Scan / frontend-security (push) Has been cancelled
docs(ops): record sub2api 0.1.133 deployment
2026-06-05 17:23:26 +08:00

18 KiB
Raw Blame History

US RackNerd 0526 Sub2API Remote Inventory

最后核对时间2026-06-05 17:22 Asia/Shanghai

远程位置

  • Tabby profile个人-US-racknerd-0526-3c4g
  • Hostnameracknerd-0a1c758
  • 公网 IP216.45.59.243
  • origin 入口:https://origin.proxy.api.lilifamily.com
  • 公开直连主站入口:https://catproxy.lilifamily.com
  • 部署目录:/opt/sub2api
  • Compose projectsub2api
  • 系统Debian GNU/Linux 13 (trixie)

当前状态

  • 已部署并验证。
  • DockerDocker version 29.5.2, build 79eb04c
  • Docker ComposeDocker Compose version v5.1.4
  • nginxnginx/1.26.3
  • DNSorigin.proxy.api.lilifamily.com -> 216.45.59.243catproxy.lilifamily.com -> 216.45.59.243
  • proxy.api.lilifamily.com 已切到 JPpro 151.242.164.723c4g 上旧 proxy.api nginx 站点已禁用。
  • Sub2API 当前版本:0.1.133,当前镜像:sub2api:upstream-0.1.133-ebf4d8c3c3e9
  • Sub2API 只绑定宿主机 127.0.0.1:8080,公网只能经 nginx catproxy 或受限 origin 转发。
  • PostgreSQL、Redis、Mihomo 不映射公网端口。
  • CLIProxyAPI 已部署为同机内网服务,容器加入 sub2api-network,宿主机仅监听 127.0.0.1:8317
  • 从旧机迁移的业务计数已核对:users=1api_keys=3accounts=133

本地留痕

  • 当前远程 Compose 副本:current/docker-compose.yml
  • 旧主域 nginx 配置副本:current/nginx-sub2api.conf,当前远程已禁用,仅作历史/回滚参考
  • 当前 origin 配置副本:current/nginx-origin-sub2api.conf
  • 当前 catproxy 配置副本:current/nginx-catproxy-sub2api.conf
  • 当前默认拒绝配置副本:current/nginx-default-deny.conf
  • 当前 token map 配置副本:current/proxy-ng-token-map.conf,真实 token 已脱敏
  • 当前 CLIProxyAPI Compose 副本:current/cliproxyapi-compose.yml
  • 当前 CLIProxyAPI 配置副本:current/cliproxyapi-config.redacted.yaml,业务调用密钥已脱敏
  • 防火墙与 origin 边界记录:current/firewall-notes.md
  • 迁移包 SHA256 记录:backups/migrate-to-racknerd-0526-20260525-205103.SHA256SUMS
  • 密钥目录说明:secrets/README.md

真实 .env、Mihomo 配置、订阅文件、proxy-ng token、证书私钥和临时备份不得提交。需要本地留存时放入 secrets/backups/,并确认 .gitignore 已排除。

部署架构

Client
  ↓ HTTPS :443 proxy.api.lilifamily.com
JPpro nginx proxy-ng
  ↓ HTTPS + X-Proxy-Ng-Token
3c4g nginx origin.proxy.api.lilifamily.com
  ↓ 127.0.0.1:8080
sub2api container
  ↓
postgres / redis / mihomo containers

Sub2API 调用 CLIProxyAPI 的同机内网路径:

sub2api container
  ↓ Docker DNS: http://cli-proxy-api:8317
cli-proxy-api container
  ↓ OAuth auths / configured upstream API keys
upstream model providers

公开直连主站路径:

Client
  ↓ HTTPS :443 catproxy.lilifamily.com
3c4g nginx
  ↓ 127.0.0.1:8080
Sub2API

部署安全边界:

  • origin.proxy.api.lilifamily.com 只允许 JPpro IP 151.242.164.72 访问,并校验 X-Proxy-Ng-Token
  • catproxy.lilifamily.com 不做 IP 白名单限制,是 3c4g 上可直接访问的主站域名和回滚入口。
  • proxy.api.lilifamily.com 不再解析到 3c4g也不再由 3c4g nginx 站点提供服务。
  • Sub2API 容器端口只绑定 127.0.0.1:8080
  • CLIProxyAPI 不接入 nginx不配置公网域名公网不可直接访问 8317

当前配置要点

  • origin 域名:origin.proxy.api.lilifamily.com
  • catproxy 域名:catproxy.lilifamily.com
  • TLSCertbot 管理 nginx 证书。
  • origin 证书路径:/etc/letsencrypt/live/origin.proxy.api.lilifamily.com/fullchain.pem
  • catproxy 证书路径:/etc/letsencrypt/live/catproxy.lilifamily.com/fullchain.pem
  • token 配置:/etc/nginx/proxy-ng/token.conf,权限 600 root root
  • token map 配置:/etc/nginx/conf.d/proxy-ng-token-map.conf,本地副本已脱敏
  • 远程 .envPUBLIC_DOMAIN=proxy.api.lilifamily.com
  • 远程 .envSUB2API_IMAGE=sub2api:upstream-0.1.133-ebf4d8c3c3e9
  • URL allowlist 当前关闭:SECURITY_URL_ALLOWLIST_ENABLED=false
  • 远程 .envSECURITY_URL_ALLOWLIST_ALLOW_INSECURE_HTTP=true,允许 APIKey 上游 base_url 使用 http://
  • CLIProxyAPI 部署目录:/opt/cliproxyapi
  • CLIProxyAPI 镜像:eceasy/cli-proxy-api:v7.1.39
  • CLIProxyAPI 宿主机监听:127.0.0.1:8317
  • CLIProxyAPI Docker 网络地址:http://cli-proxy-api:8317
  • CLIProxyAPI 业务调用密钥:远程 /opt/cliproxyapi/secrets/generated-credentials.txt,不提交 Git。

DNS state after proxy-ng hardening

Name A records Role
proxy.api.lilifamily.com 151.242.164.72 Public entry
jp.proxy.api.lilifamily.com 151.242.164.72 JPpro proxy-ng node
catproxy.lilifamily.com 216.45.59.243 Public direct main-site and rollback entry
origin.proxy.api.lilifamily.com 216.45.59.243 Proxy-ng origin only

运行检查

cd /opt/sub2api
docker compose ps
curl -sS http://127.0.0.1:8080/health
nginx -t
systemctl is-active nginx
curl --noproxy '*' -i https://origin.proxy.api.lilifamily.com/health
curl --noproxy '*' -i https://catproxy.lilifamily.com/health

CLIProxyAPI 内网检查:

cd /opt/cliproxyapi
docker compose ps
curl --noproxy '*' -sS http://127.0.0.1:8317/healthz
docker exec sub2api sh -lc 'wget -q -S -O - http://cli-proxy-api:8317/healthz 2>&1 | sed -n "1,12p"'

期望结果:

  • sub2apisub2api-postgressub2api-redis 为 healthy。
  • 本机 /health 返回 {"status":"ok"}
  • 非 JPpro 来源访问 origin.proxy.api.lilifamily.com/health 返回 403
  • JPpro 带 X-Proxy-Ng-Token 访问 origin 返回 200
  • 公网访问 catproxy.lilifamily.com/health 返回 200
  • 直连 216.45.59.243:8080 不对公网开放。
  • ss -ltnp 显示 CLIProxyAPI 只监听 127.0.0.1:8317
  • Sub2API 容器内访问 http://cli-proxy-api:8317/healthz 返回 {"status":"ok"}

操作记录

2026-05-26 迁移目标盘点

  • 通过 Tabby profile 个人-US-racknerd-0526-3c4g 只读核对。
  • 确认公网 IP216.45.59.243
  • 确认系统Debian GNU/Linux 13 (trixie)。
  • 确认尚未部署 /opt/sub2api,尚未安装 Docker。

2026-05-26 部署与迁移完成

  • 安装 Docker CE、Docker Compose plugin、nginx、certbot、python3-certbot-nginxrsync
  • 从旧机迁移包恢复 /opt/sub2api,迁移包 SHA256 在新机按 basename 重新校验通过。
  • 使用 pg_restore -U sub2api -d sub2api --clean --if-exists 导入 PostgreSQL dump。
  • 业务数据计数核对通过:users=1api_keys=3accounts=133
  • 启动 Compose 服务,sub2apisub2api-postgressub2api-redis 均为 healthysub2api-mihomo 为 running。
  • 配置 nginx 站点 /etc/nginx/sites-available/sub2api.conf,启用 /etc/nginx/sites-enabled/sub2api.conf
  • Certbot 已为 proxy.api.lilifamily.com 签发并部署 HTTPS 证书。
  • 公网验证通过:https://proxy.api.lilifamily.com/health 返回 {"status":"ok"}
  • API 路由验证通过:未授权 POST https://proxy.api.lilifamily.com/v1/responses 返回 401 API_KEY_REQUIRED
  • 旧机未停止,仍作为短期回滚来源。

2026-05-26 proxy-ng origin hardening backup

  • Backup path: /root/sub2api-hardening-backup-20260526-033010
  • Includes nginx config, docker-compose.yml, .env, and PostgreSQL dump.
  • Secret token exists only on remote root-readable nginx config and is not stored in Git.

2026-05-26 origin/catproxy hardening

  • origin.proxy.api.lilifamily.comcatproxy.lilifamily.com 签发 Let's Encrypt 证书,到期时间均为 2026-08-24
  • 新增 /etc/nginx/sites-available/origin-sub2api.conf,只允许 151.242.164.72 并校验 X-Proxy-Ng-Token
  • 新增 /etc/nginx/sites-available/catproxy-sub2api.conf;初始版本限制管理来源,后续已按当前决策改为公开直连主站入口。
  • 新增 /etc/nginx/sites-available/00-default-deny.conf,未知 Host 默认返回 444
  • 为 nginx 增加 map_hash_bucket_size 128,修复长 hostname map 导致的 nginx -t 失败。
  • proxy.api.lilifamily.com 站点已从 sites-enabled 禁用,备份路径:/root/sub2api-disable-public-proxy-backup-20260526-040529
  • 验证结果:非白名单访问 origin 返回 403JPpro 带 token 访问 origin 返回 200,公网主入口 proxy.api.lilifamily.com 返回 JPpro 节点响应头。
  • 配置 logrotate/etc/logrotate.d/nginx-proxy-ngdry-run 无语法错误。

2026-05-26 catproxy 访问边界调整

  • 按当前决策,catproxy.lilifamily.com 不再限制访问来源,作为 3c4g 公开直连主站域名和回滚入口。
  • 远程备份:/etc/nginx/sites-available/catproxy-sub2api.conf.bak-20260526043650
  • /etc/nginx/sites-available/catproxy-sub2api.conf 删除 allow 106.37.220.142deny all
  • 保留 origin.proxy.api.lilifamily.com 的来源 IP 白名单和 X-Proxy-Ng-Token 校验。
  • 验证结果:nginx -t 成功,systemctl reload nginx 成功,catproxy.lilifamily.com/health 返回 200,非白名单访问 origin.proxy.api.lilifamily.com/health 返回 403

2026-05-26 主站限速核对

  • catproxy.lilifamily.com 当前无 nginx limit_req / limit_conn,主站直连不按 IP 限速。
  • origin.proxy.api.lilifamily.com 当前只做 JPpro IP 白名单和 X-Proxy-Ng-Token 校验,不做 nginx 速率限制。
  • Sub2API 业务请求限速维度是用户、用户+分组、API Key 窗口额度;不是按 IP 限速。
  • 生产库非敏感快照:当前用户全局 rpm_limit=0;部分分组配置 20/30/40/100 RPMAPI Key briqt 配置 5h=3001d=500API Key free 配置 1d=50
  • 本机测速与限速维度详见 docs/memorys/2026-05-26-主站测速与限速核对.md

2026-05-27 自定义菜单安全嵌入部署

  • 目标:用户侧新增一级菜单 购买套餐,站内嵌入 https://pay.ldxp.cn/shop/5HAP5JVN
  • 安全边界:菜单项配置 omit_auth_context=trueiframe URL 不传 tokenuser_idsrc_hostsrc_url
  • 本地构建:前端 build 后交叉编译 linux/amd64 Go 二进制,使用 -tags embed 嵌入前端资源。
  • 远程部署方式:上传 runtime patch tar在远程基于 weishaw/sub2api:latest 替换 /app/sub2api/app/resourcesdocker commit 生成本地镜像。
  • runtime patch/tmp/sub2api-custom-menu-runtime-patch-20260527.tar.gz
  • runtime patch SHA256321b69bcf40470be9f2de10f8f1114ebd6bd7e6e014783b123c7160781ac127d
  • 当前镜像:sub2api:custom-menu-safe-embed-20260527
  • 镜像 IDsha256:356653e0e5a7b688faacb728a0f94d450e102393fd73bb16c705000f359133de
  • 部署前备份:/opt/sub2api/backups/deploy-custom-menu-20260526-222849
  • 菜单配置备份:/opt/sub2api/backups/custom-menu-shop-20260526-224153
  • 线上数据库 settings.custom_menu_items 已写入:
[
  {
    "id": "shop",
    "label": "购买套餐",
    "icon_svg": "",
    "url": "https://pay.ldxp.cn/shop/5HAP5JVN",
    "visibility": "user",
    "sort_order": 0,
    "omit_auth_context": true
  }
]
  • 写入数据库后已重启 sub2api 容器刷新 CSP frame-src 缓存。
  • 验证结果:sub2api healthycatproxy.lilifamily.com/healthproxy.api.lilifamily.com/health 返回 200catproxy.lilifamily.com/custom/shopproxy.api.lilifamily.com/custom/shop 返回 200CSP frame-src 已包含 https://pay.ldxp.cn

2026-05-27 自定义菜单安全嵌入 r2 发布

  • 目标:发布提交 7954492cee99,包含侧边栏隐藏版本号和最终 custom menu 安全契约修正。
  • 本地版本:0.1.131
  • 本地 commit7954492cee99
  • 本地构建:pnpm -C frontend build 后执行 CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -tags embed
  • runtime patch/tmp/sub2api-custom-menu-safe-embed-r2-runtime-patch.tar.gz
  • runtime patch SHA256962de880c5e0917e3c6b351fd1955c3d94c8f7b6fcfae558492535c08faac0d0
  • 部署前备份:/opt/sub2api/backups/deploy-custom-menu-r2-20260527-000642
  • 当前镜像:sub2api:custom-menu-safe-embed-20260527-r2
  • 镜像 IDsha256:ceeea1a913ea8386f24b4296b856295c18febd0b19eeb1e92de4ef9512e3f3a2
  • 远程二进制核对:Sub2API 0.1.131 (commit: 7954492cee99, built: 2026-05-27T07:02:24Z)
  • 远程健康核对:docker inspect sub2api 显示镜像 sub2api:custom-menu-safe-embed-20260527-r2healthy
  • 公网验证:catproxy.lilifamily.com/healthproxy.api.lilifamily.com/health 返回 {"status":"ok"}
  • 菜单验证:proxy.api.lilifamily.com/api/v1/settings/public 返回版本 0.1.131custom_menu_items[0].label=购买套餐omit_auth_context=true
  • iframe CSP 验证:catproxy.lilifamily.com/custom/shopproxy.api.lilifamily.com/custom/shop 返回 200CSP frame-src 包含 https://pay.ldxp.cn

2026-06-02 允许 HTTP APIKey 上游

  • 背景APIKey 账号测试 http:// base URL 时返回 Invalid base URL: invalid url scheme: http
  • 远程配置:/opt/sub2api/.env 第 58 行改为 SECURITY_URL_ALLOWLIST_ALLOW_INSECURE_HTTP=true
  • 生效方式:docker compose up -d --no-deps --force-recreate sub2api,未重建镜像,未重启 PostgreSQL、Redis、Mihomo。
  • 验证结果:sub2api 容器重建后为 healthy;容器内 SECURITY_URL_ALLOWLIST_ALLOW_INSECURE_HTTP=true;本机 http://127.0.0.1:8080/health 返回 {"status":"ok"}
  • 安全注意:该配置允许配置 http:// 上游,公网 HTTP 会明文传输上游 API Key优先只用于可信内网或明确接受风险的上游。

2026-06-02 CLIProxyAPI 内网部署

  • 目标:在 3c4g 上部署 CLIProxyAPI仅供同机 Sub2API 调用,不开放公网入口。
  • 部署目录:/opt/cliproxyapi
  • 镜像:eceasy/cli-proxy-api:v7.1.39
  • 容器:cli-proxy-api
  • Docker 网络:加入现有 sub2api-network,网络别名 cli-proxy-api
  • 监听边界:宿主机只绑定 127.0.0.1:8317,未配置 nginx 站点,未新增公网域名。
  • 远程密钥:/opt/cliproxyapi/secrets/cliproxyapi.env 保存 MANAGEMENT_PASSWORD/opt/cliproxyapi/secrets/generated-credentials.txt 保存 Sub2API 业务调用 key。
  • 脱敏配置副本:current/cliproxyapi-compose.ymlcurrent/cliproxyapi-config.redacted.yaml
  • 验证结果:curl http://127.0.0.1:8317/healthz 返回 200;无业务 key 请求 /v1/models 返回 401 Missing API key;带业务 key 请求 /v1/models 返回 200 {"data":[],"object":"list"}docker exec sub2api 内访问 http://cli-proxy-api:8317/healthz 返回 200
  • 当前限制:尚未导入 OAuth auth 文件或上游 API key因此 /v1/models 返回空列表;后续需要为 CLIProxyAPI 配置具体 provider 后Sub2API 才能通过该内网地址调用上游模型。

2026-06-05 Sub2API 0.1.133 上游合并发布

  • 目标:从上游 origin/main 合并到 feature/proxy-ng 后发布,跟进开源版本升级,同时保留本地 proxy-ng、ops 留痕和自定义菜单安全嵌入能力。
  • 上游合并来源:origin/main d895d765
  • 本地发布提交:ebf4d8c3c3e9
  • 发布版本:0.1.133
  • 部署方式:本地构建 linux/amd64 Go 二进制并嵌入前端,上传 runtime patch tar 到远程,在远程基于当前运行镜像替换 /app/sub2api/app/resourcesdocker commit 生成本地镜像。
  • runtime patch/tmp/sub2api-0.1.133-ebf4d8c3c3e9-runtime-patch.tar.gz
  • runtime patch SHA2562709409c4bd3cd3cc7622dcdb9e8eea264f9cc595cb60d845a528fc0d676fcc6
  • 部署前备份:/opt/sub2api/backups/deploy-upstream-0.1.133-20260605-021731
  • 当前镜像:sub2api:upstream-0.1.133-ebf4d8c3c3e9
  • 镜像 IDsha256:01bc4c4df84c2ed9cc5ec0934203b3a17538b0854d0704d91dbc2b9b878e834a
  • 生效方式:更新远程 /opt/sub2api/.envSUB2API_IMAGE,执行 docker compose up -d --no-deps --force-recreate sub2apiPostgreSQL、Redis、Mihomo、CLIProxyAPI 未重启。
  • 远程版本核对:/app/sub2api --version 返回 Sub2API 0.1.133 (commit: ebf4d8c3c3e9, built: 2026-06-05T09:13:49Z)
  • 远程健康核对:docker compose ps sub2api 显示 healthy;本机 http://127.0.0.1:8080/health 返回 {"status":"ok"}
  • CLIProxyAPI 边界核对:宿主机 http://127.0.0.1:8317/healthz 和 Sub2API 容器内 http://cli-proxy-api:8317/healthz 均返回 {"status":"ok"}
  • nginx 核对:nginx -t 成功,systemctl is-active nginx 返回 active
  • 端口边界核对Sub2API 仅监听 127.0.0.1:8080CLIProxyAPI 仅监听 127.0.0.1:8317,公网仅开放 nginx 80/443
  • 公网健康核对:https://catproxy.lilifamily.com/healthhttps://proxy.api.lilifamily.com/health 均返回 {"status":"ok"}
  • 公网设置核对:https://catproxy.lilifamily.com/api/v1/settings/public 返回 version=0.1.133,并保留 购买套餐 菜单和 omit_auth_context=true
  • 自定义页面核对:https://catproxy.lilifamily.com/custom/shop 返回 200,页面配置仍包含 https://pay.ldxp.cn
  • origin 边界核对:本地非白名单来源访问 https://origin.proxy.api.lilifamily.com/health 返回 403,符合预期。
  • 注意:本地镜像通过 docker commit 生成OCI label 仍可能继承旧 runtime patch 元数据;运行版本以远程二进制 --version.envSUB2API_IMAGE 和 Compose 实际镜像为准。
  • 回滚方式:把 /opt/sub2api/.envSUB2API_IMAGE 回退到上一版 sub2api:custom-menu-safe-embed-20260527-r2,再执行 cd /opt/sub2api && docker compose up -d --no-deps --force-recreate sub2api;必要时使用备份目录 /opt/sub2api/backups/deploy-upstream-0.1.133-20260605-021731 取回部署前文件。