new-api 与 sub2api 本地开发与部署
本文面向站点维护者,整理 new-api 与 sub2api 的本地开发、远程数据库联调和生产部署流程。
安全提醒
不要把生产数据库密码、Redis 密码、SSH 私钥、面板地址或真实服务器 IP 写入公开仓库。本文使用占位符展示配置结构,实际值请从密码管理器、服务器环境变量或 1Panel 应用配置中读取。
项目仓库
| 项目 | 官方仓库 | Fork |
|---|---|---|
| new-api | https://github.com/QuantumNous/new-api | https://github.com/2Red1Blue/new-api |
| sub2api | https://github.com/mansebia/sub2api | https://github.com/2Red1Blue/sub2api |
本地源码通常放在:
~/Code/kaiyuan/cpa/new-api
~/Code/kaiyuan/cpa/sub2apiGit 远程分支策略
origin 指向自己的 fork,用来推送自定义改动;upstream 指向官方仓库,用来同步上游更新。
git remote -v
git fetch upstream
git merge upstream/main
git push origin main如果希望提交历史更线性,也可以用 rebase,但已经与远程协作的分支要谨慎改写历史。
new-api 本地全量开发
new-api 仓库提供了开发用 compose,包含后端、PostgreSQL 和 Redis,适合不依赖生产数据的本地调试。
cd ~/Code/kaiyuan/cpa/new-api
podman compose -f docker-compose.dev.yml up -d后端地址:
http://localhost:3000修改 Go 代码后重建:
podman compose -f docker-compose.dev.yml up -d --build new-api停止服务:
podman compose -f docker-compose.dev.yml down清空本地数据并重置:
podman compose -f docker-compose.dev.yml down -v前端开发服务器:
cd ~/Code/kaiyuan/cpa/new-api/web/default
bun install
bun run dev前端默认访问 http://localhost:3001,API 代理到后端 :3000。
远程数据库联调模式
当需要使用服务器上的真实数据调试时,可以通过 SSH 隧道把服务器内网 PostgreSQL 和 Redis 映射到本地。
本地 5433 -> SSH 隧道 -> 服务器 127.0.0.1:5432 PostgreSQL
本地 6381 -> SSH 隧道 -> 服务器 127.0.0.1:6379 Redis建立隧道:
ssh -N \
-L 5433:127.0.0.1:5432 \
-L 6381:127.0.0.1:6379 \
qianshan-oci验证端口:
nc -z 127.0.0.1 5433 && echo "PG OK"
nc -z 127.0.0.1 6381 && echo "Redis OK"new-api 连接远程数据库调试
容器模式适合日常联调:
cd ~/Code/kaiyuan/cpa/new-api
podman compose -f docker-compose.remote-db.yml up -d
podman compose -f docker-compose.remote-db.yml logs -f new-api本地 Go 进程模式适合 GoLand 或 VS Code 打断点。由于后端会嵌入前端构建产物,调试前先准备占位文件:
cd ~/Code/kaiyuan/cpa/new-api
mkdir -p web/default/dist web/classic/dist
printf '<!doctype html><html><body>use frontend dev server</body></html>' > web/default/dist/index.html
printf '<!doctype html><html><body>use frontend dev server</body></html>' > web/classic/dist/index.html启动后端:
SQL_DSN="postgresql://<db_user>:<db_password>@127.0.0.1:5433/new_api" \
REDIS_CONN_STRING="redis://:<redis_password>@127.0.0.1:6381" \
TZ="Asia/Shanghai" \
BATCH_UPDATE_ENABLED=true \
NODE_TYPE=slave \
go run .本地调试建议
如果本地连的是共享或生产数据库,建议使用 NODE_TYPE=slave,让本地进程只处理请求,不跑定时任务,避免和服务器主节点重复执行后台任务。
sub2api 本地开发
sub2api 通常直接走远程数据库联调模式。它和 new-api 可以共用同一条 SSH 隧道。
容器模式:
cd ~/Code/kaiyuan/cpa/sub2api
podman compose -f docker-compose.remote-db.yml up -d
podman compose -f docker-compose.remote-db.yml logs -f sub2api本地 Go 进程模式:
cd ~/Code/kaiyuan/cpa/sub2api/backend
DATABASE_HOST=127.0.0.1 \
DATABASE_PORT=5433 \
DATABASE_USER="<db_user>" \
DATABASE_PASSWORD="<db_password>" \
DATABASE_DBNAME=sub2api \
DATABASE_SSLMODE=disable \
REDIS_HOST=127.0.0.1 \
REDIS_PORT=6381 \
REDIS_PASSWORD="<redis_password>" \
TZ=Asia/Shanghai \
AUTO_SETUP=true \
go run ./cmd/server前端开发服务器:
cd ~/Code/kaiyuan/cpa/sub2api/frontend
pnpm install
pnpm dev常用端口:
| 服务 | 地址 |
|---|---|
| new-api 后端 | http://localhost:3000 |
| new-api 前端 | http://localhost:3001 |
| sub2api 后端 | http://localhost:8080 |
| sub2api 前端 | http://localhost:5173 |
生产部署概览
生产环境通常由 Docker/1Panel 管理基础服务:
| 服务 | 说明 |
|---|---|
| PostgreSQL | 只监听服务器内网地址 |
| Redis | 只监听服务器内网地址 |
| OpenResty | 负责 HTTPS 和反向代理 |
| new-api | API 网关与控制台 |
| sub2api | 独立服务 |
建议部署流程:
- 推送代码到 GitHub fork。
- GitHub Actions 构建
linux/arm64镜像。 - 推送镜像到 GHCR。
- 服务器拉取新镜像。
- 使用 Docker Compose 或 1Panel 重启服务。
- 检查健康接口、登录页和关键 API。
域名规划
| 域名 | 目标 |
|---|---|
ai.laiber.cloud | new-api 控制台与 API |
sub2api.laiber.cloud | sub2api 服务 |
docs.laiber.cloud | VitePress 文档站 |
Cloudflare DNS 中通常添加 A 或 CNAME 记录,并开启 HTTPS。业务服务由服务器反向代理处理,文档站建议直接部署到 Cloudflare Pages。
常用排障命令
# 登录服务器
ssh qianshan-oci
# 查看容器
docker ps
# 查看本地 new-api 日志
podman compose -f docker-compose.dev.yml logs -f new-api
# 查看远程数据库联调容器日志
podman compose -f docker-compose.remote-db.yml logs -f new-api常见问题
本地后端启动后 localhost:3000 打不开
GoLand 的 Delve 调试端口不是应用端口。应用只有在数据库迁移和初始化完成后才会监听 :3000。如果日志停在数据库迁移阶段,先检查数据库连接、隧道和迁移是否卡住。
可以同时启动两个 master 吗
不建议。master 会跑后台任务和定时任务,本地连共享数据库时容易和服务器重复执行。调试请求链路时优先用 NODE_TYPE=slave。
密码显示接口报 cipher: message authentication failed
这通常表示数据库里的加密值不是用当前密钥链加密的。相关环境变量优先级通常是:
UPSTREAM_SECRET_KEY > CRYPTO_SECRET > SESSION_SECRET本地和服务器的密钥不一致时,旧数据可能无法解密,需要确认环境变量一致或重新保存对应密码。