# AGENTS.md — Sub2API 部署与发版 ## 项目概述 Sub2API — AI API 网关平台,Go + Vue 3 前后端一体,Ent ORM,支持多账户管理、API 密钥分发、Token 级计费、智能调度、支付集成。 - 上游: `https://github.com/Wei-Shaw/sub2api` - 本地: `/Users/qingse/Sync/local-git/sub2api` - 当前稳定版: `v0.1.133` - 许可证: LGPL v3 ## 部署留痕规则 所有远程部署、迁移、域名切换、证书、反代、Compose、数据库、Redis、Mihomo 或代理配置变化,都必须在当前仓库留痕。 - 根级 `AGENTS.md` 只记录规则、索引和通用流程。 - 每台服务器必须在 `ops/remote/` 下单独一个子目录。 - 服务器目录必须记录域名、IP、服务器名、Tabby profile、部署方式、部署架构、运行检查和操作记录。 - 当前实际生效配置副本必须放在对应服务器目录的 `current/` 下,例如 `docker-compose.yml`、`nginx-sub2api.conf` 或 `Caddyfile`。 - 计划但尚未部署的配置放在 `planned/` 下,不能写成当前事实。 - `.env`、数据库密码、JWT/TOTP 密钥、Mihomo 订阅和真实代理配置只允许放在被 `.gitignore` 排除的 `secrets/` 或 `backups/` 中,禁止提交。 - 通过 Tabby 操作远程后,必须同步更新对应服务器目录,避免远程真实状态和项目记录漂移。 当前远程部署索引见 `ops/remote/README.md`。每个服务器目录至少包含: ```text ops/remote/-sub2api/ ├── README.md # 服务器级部署记录 ├── current/ # 当前远程生效配置副本 ├── planned/ # 计划配置,未部署时使用 ├── secrets/README.md # 敏感配置保存说明,真实文件不提交 ├── backups/.gitkeep # 远程备份说明或占位,真实备份不提交 └── .gitignore # 排除密钥、订阅和备份 ``` ## 远程部署索引 | 目录 | Tabby 连接 | 公网入口 | 状态 | |------|------------|----------|------| | `ops/remote/jppro-sub2api/` | `个人-JPpro-akile-0504-1c1g` | `https://proxy.api.lilifamily.com` / `https://jp.proxy.api.lilifamily.com` | proxy-ng 公开入口节点,回源到 3c4g origin | | `ops/remote/us-racknerd-0425-sub2api/` | `个人-US-racknerd-0425-1c1g` | `https://pai.cyan2000.uk` | 旧机,迁移来源和回滚来源 | | `ops/remote/us-racknerd-0526-sub2api/` | `个人-US-racknerd-0526-3c4g` | `https://origin.proxy.api.lilifamily.com` / `https://catproxy.lilifamily.com` | Sub2API 受限 origin 和公开直连主站入口 | ## JPpro 当前 proxy-ng 记录 | 项目 | 详情 | |------|------| | 服务器 | JP Pro VPS `151.242.164.72`,Debian Trixie 1C1G20G | | 域名 | `proxy.api.lilifamily.com`、`jp.proxy.api.lilifamily.com` | | Tabby 连接 | `个人-JPpro-akile-0504-1c1g` | | 部署方式 | apt 安装 nginx + Certbot,作为 proxy-ng 入口中转 | | 回源目标 | `https://origin.proxy.api.lilifamily.com` | | 访问 | `https://proxy.api.lilifamily.com/`、`https://jp.proxy.api.lilifamily.com/` | | 详细记录 | `ops/remote/jppro-sub2api/` | 当前 JPpro 不运行 Sub2API、PostgreSQL、Redis、Caddy 或账号出口代理;只运行 nginx 反向代理。当前已启用独立 origin 回源、3c4g 来源 IP 白名单和 `X-Proxy-Ng-Token` 校验。 ## JPpro 历史部署记录 | 项目 | 详情 | |------|------| | 服务器 | JP Pro VPS `151.242.164.72`,Debian Trixie 1C1G20G | | 域名 | `proxy.api.cyan2000.uk` | | Tabby 连接 | `个人-JPpro-akile-0504-1c1g` | | 部署目录 | `/opt/sub2api/`,已于 2026-05-26 清理 | | 访问 | `https://proxy.api.cyan2000.uk/`,当前未在 JPpro 上提供服务 | | 详细记录 | `ops/remote/jppro-sub2api/` | ### 远程目录结构 ``` /opt/sub2api/ ├── docker-compose.yml # 官方 docker-compose.yml + Caddy ├── .env # 密钥配置 (chmod 600) └── Caddyfile # Caddy 反向代理配置 ``` 数据存储在 Docker 命名卷:`sub2api_data`、`postgres_data`、`redis_data`、`caddy_data`、`caddy_config`。 ### 历史 Docker 服务架构 ``` Browser :443 (HTTPS) → Caddy → sub2api :8080 (内部) → postgres :5432 (内部) :80 → 301 redirect → redis :6379 (内部) ``` | 容器 | 镜像 | 角色 | |------|------|------| | `sub2api-caddy` | `caddy:2-alpine` | HTTPS 自动证书 + 反向代理 | | `sub2api` | `weishaw/sub2api:latest` | Go 后端 + 内嵌 Vue 前端 | | `sub2api-postgres` | `postgres:18-alpine` | 主数据库 | | `sub2api-redis` | `redis:8-alpine` | 缓存 | ### Caddy 配置 ``` proxy.api.cyan2000.uk { reverse_proxy sub2api:8080 encode gzip } ``` Caddy 自动从 Let's Encrypt 获取和管理 TLS 证书,HTTP(:80) 自动 301 跳转到 HTTPS(:443)。 ## 发版流程 远程服务器可直接拉取 Docker Hub,常规升级只需 pull + restart。 ### 常规升级(官方镜像) ```bash cd /opt/sub2api docker compose pull sub2api docker compose up -d ``` ### 本地编译部署(二开修改时使用) 当 GitHub 不可达需要国内 GOPROXY,或需要本地修改代码后部署时: ```bash # 1. 拉取代码 cd /Users/qingse/Sync/local-git/sub2api git fetch ea-ali git checkout # 2. 构建前端 cd frontend && pnpm install --frozen-lockfile && pnpm run build # 3. 交叉编译 Go cd ../backend CGO_ENABLED=0 GOOS=linux GOARCH=amd64 \ GOPROXY=https://goproxy.cn,direct \ go build -tags embed -ldflags="-s -w -X main.Version=<版本>" -trimpath \ -o /tmp/sub2api ./cmd/server # 4. 构建最小 Docker 镜像 mkdir -p /tmp/sub2api-build/{deploy,backend/resources} cp /tmp/sub2api /tmp/sub2api-build/ cp -r ../backend/resources/* /tmp/sub2api-build/backend/resources/ cp ../deploy/docker-entrypoint.sh /tmp/sub2api-build/deploy/ cat > /tmp/sub2api-build/Dockerfile << 'EOF' FROM alpine:latest RUN apk add --no-cache ca-certificates tzdata su-exec libpq wget RUN addgroup -g 1000 sub2api && adduser -u 1000 -G sub2api -s /bin/sh -D sub2api COPY sub2api /app/sub2api COPY backend/resources /app/resources COPY deploy/docker-entrypoint.sh /app/docker-entrypoint.sh RUN chmod +x /app/docker-entrypoint.sh && mkdir -p /app/data && chown sub2api:sub2api /app/data EXPOSE 8080 HEALTHCHECK --interval=30s --timeout=10s --start-period=10s --retries=3 \ CMD wget -q -T 5 -O /dev/null http://localhost:8080/health || exit 1 WORKDIR /app ENTRYPOINT ["/app/docker-entrypoint.sh"] CMD ["/app/sub2api"] EOF docker build --platform linux/amd64 -t sub2api:<版本> /tmp/sub2api-build # 5. 导出上传 docker save sub2api:<版本> | gzip > /tmp/sub2api-<版本>.tar.gz # Tabby SFTP: open_profile(个人-JPpro-akile-0504-1c1g) → sftp_upload → /tmp/ # 6. 远程部署 docker load < /tmp/sub2api-<版本>.tar.gz cd /opt/sub2api sed -i 's|image:.*|image: sub2api:<版本>|' docker-compose.yml docker compose up -d # 7. 清理 rm -rf /tmp/sub2api-build /tmp/sub2api /tmp/sub2api-*.tar.gz ``` ## 运维命令 ```bash # 查看服务状态 cd /opt/sub2api && docker compose ps # 查看日志 docker logs sub2api --tail 50 -f # 查询数据库 docker exec sub2api-postgres psql -U sub2api -d sub2api -c "SELECT ..." # 重启服务 cd /opt/sub2api && docker compose up -d # 停止服务 cd /opt/sub2api && docker compose down # 数据备份 cd /opt/sub2api && tar czf /tmp/sub2api-backup-$(date +%Y%m%d).tar.gz data/ postgres_data/ redis_data/ ``` ## Git 远程 | 远程 | URL | 角色 | |------|-----|------| | `origin` | `https://github.com/Wei-Shaw/sub2api.git` | 上游 | | `ea-ali` | `ssh://git@101.200.34.71:2222/zizi-al/sub2api.git` | 可写开发远程 | ## 注意事项 - Go 编译必须加 `-tags embed`,否则前端不会嵌入二进制 - 前端 build 输出到 `backend/internal/web/dist`,Go 编译时通过 `//go:embed` 嵌入 - GitHub 和 Docker Hub 在国内网络不可达时,Go proxy 用 `goproxy.cn`,Docker base image 用本地缓存 - 远程服务器可访问 Docker Hub,postgres:18-alpine 和 redis:8-alpine 自动拉取 - `.env` 文件权限必须是 600,包含数据库密码和 JWT 密钥 - 首次启动会自动创建管理员账号(`AUTO_SETUP=true`)