目录

Sub2API Docker 部署指南

Sub2API 是一款开源的 AI API 网关平台,用于分发和管理 AI 产品订阅的 API 配额。它支持多账号管理(OAuth、API Key)、Token 级精确计费、智能调度和并发控制,适合作为 NewAPI 等下游网关的上游渠道。

本文记录在 VPS 上使用 Docker Compose 部署 Sub2API,并通过 nginx + Cloudflare Origin CA 配置 HTTPS 反向代理的完整过程。Sub2API 仅作为 NewAPI 的内部上游使用,不直接对外开放。

环境准备

前期需要准备:

  1. 一台 VPS(本文以 Debian 12 为例)
  2. 一个托管在 Cloudflare 的域名(需通配符 SSL 证书或单独生成子域名证书)
  3. 服务器已安装 Docker 和 Docker Compose
  4. 服务器已安装 nginx

第一步:创建项目目录

在服务器上创建 Sub2API 的数据目录:

mkdir -p /root/sub2api

第二步:编写 Docker Compose 配置

创建 `/root/sub2api/docker-compose.yml`:

services:
  sub2api:
    image: weishaw/sub2api:latest
    container_name: sub2api
    restart: unless-stopped
    ports:
      - "${BIND_HOST:-127.0.0.1}:${SERVER_PORT:-8081}:8080"
    volumes:
      - sub2api_data:/app/data
    environment:
      - AUTO_SETUP=true
      - SERVER_PORT=8080
      - TZ=Asia/Shanghai
      # PostgreSQL
      - DATABASE_HOST=postgres
      - DATABASE_PORT=5432
      - DATABASE_USER=${POSTGRES_USER:-sub2api}
      - DATABASE_PASSWORD=${POSTGRES_PASSWORD}
      - DATABASE_DBNAME=${POSTGRES_DB:-sub2api}
      - DATABASE_SSLMODE=disable
      # Redis
      - REDIS_HOST=redis
      - REDIS_PORT=6379
      - REDIS_PASSWORD=
      - REDIS_DB=0
      # Admin
      - ADMIN_EMAIL=${ADMIN_EMAIL:[email protected]}
      - ADMIN_PASSWORD=${ADMIN_PASSWORD:-}
      # JWT(必须固定,否则每次重启导致登录失效)
      - JWT_SECRET=${JWT_SECRET}
      - TOTP_ENCRYPTION_KEY=${TOTP_ENCRYPTION_KEY}
      # 安全配置(内部使用,允许 HTTP)
      - SECURITY_URL_ALLOWLIST_ENABLED=false
      - SECURITY_URL_ALLOWLIST_ALLOW_INSECURE_HTTP=true
      - SECURITY_URL_ALLOWLIST_ALLOW_PRIVATE_HOSTS=true
    depends_on:
      postgres:
        condition: service_healthy
      redis:
        condition: service_healthy
    networks:
      - sub2api-network

  postgres:
    image: postgres:18-alpine
    container_name: sub2api-postgres
    restart: unless-stopped
    volumes:
      - postgres_data:/var/lib/postgresql/data
    environment:
      - PGDATA=/var/lib/postgresql/data
      - POSTGRES_USER=${POSTGRES_USER:-sub2api}
      - POSTGRES_PASSWORD=${POSTGRES_PASSWORD}
      - POSTGRES_DB=${POSTGRES_DB:-sub2api}
      - TZ=Asia/Shanghai
    networks:
      - sub2api-network
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U ${POSTGRES_USER:-sub2api} -d ${POSTGRES_DB:-sub2api}"]
      interval: 10s
      timeout: 5s
      retries: 5
      start_period: 10s

  redis:
    image: redis:8-alpine
    container_name: sub2api-redis
    restart: unless-stopped
    volumes:
      - redis_data:/data
    command: redis-server --save 60 1 --appendonly yes
    environment:
      - TZ=Asia/Shanghai
    networks:
      - sub2api-network
    healthcheck:
      test: ["CMD", "redis-cli", "ping"]
      interval: 10s
      timeout: 5s
      retries: 5
      start_period: 5s

volumes:
  sub2api_data:
  postgres_data:
  redis_data:

networks:
  sub2api-network:
    driver: bridge

第三步:配置环境变量

创建 `/root/sub2api/.env`:

# 服务器绑定
BIND_HOST=127.0.0.1
SERVER_PORT=8081
SERVER_MODE=release
TZ=Asia/Shanghai
 
# PostgreSQL
POSTGRES_USER=sub2api
POSTGRES_PASSWORD=<设置一个强密码>
POSTGRES_DB=sub2api
 
# 管理员(留空密码则首次启动自动生成)
ADMIN_EMAIL=admin@sub2api.local
ADMIN_PASSWORD=
 
# 密钥(必须固定,否则每次重启会话失效)
JWT_SECRET=<openssl rand -hex 32 生成>
TOTP_ENCRYPTION_KEY=<openssl rand -hex 32 生成>

关键说明:

  1. 端口映射:容器内部监听 8080,宿主机映射到 8081,绑定 `127.0.0.1` 避免直接暴露到公网
  2. JWT_SECRET:必须固定,否则每次容器重启所有用户登录失效。用 `openssl rand -hex 32` 生成
  3. TOTP_ENCRYPTION_KEY:同上,用于双因素认证加密,必须固定
  4. ADMIN_PASSWORD:留空则首次启动时自动生成,密码在日志中输出,仅显示一次

第四步:启动容器

cd /root/sub2api
docker compose pull
docker compose up -d

检查容器状态:

docker ps --filter name=sub2api --format 'table {{.Names}}\t{{.Status}}\t{{.Ports}}'

确认所有容器均为 healthy。首次启动时 Sub2API 会自动初始化数据库并创建管理员账号。查看管理员密码:

docker logs sub2api 2>&1 | grep -i 'admin password'

输出类似:

Generated admin password (one-time): 66c159b728f3b49f9537078c9a1367d6

第五步:配置 Nginx 反向代理

如果仅需内部使用(如供给同一台 VPS 上的 NewAPI),可跳过这一步,直接使用 `http://127.0.0.1:8081`。

如需通过域名访问管理后台,创建 `/etc/nginx/sites-enabled/sub2api`:

server {
    listen 80;
    listen [::]:80;
    server_name sub2api.your-domain.example.com;
    return 301 https://$host$request_uri;
}
 
server {
    listen 443 ssl;
    listen [::]:443 ssl;
    server_name sub2api.your-domain.example.com;
 
    ssl_certificate /etc/ssl/your-cert.crt;
    ssl_certificate_key /etc/ssl/your-cert.key;
    ssl_protocols TLSv1.2 TLSv1.3;
 
    underscores_in_headers on;
 
    client_max_body_size 20M;
 
    location / {
        proxy_pass http://127.0.0.1:8081;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
    }
}

注意: `underscores_in_headers on;` 必须添加,否则 Nginx 默认会丢弃名称中带下划线的请求头(如 `session_id`),导致 Sub2API 的粘性会话功能失效。

测试并重载 nginx:

nginx -t
nginx -s reload

第六步:配置 DNS 和 SSL

在 Cloudflare 的 DNS 设置中添加 A 记录:

  1. 类型:A
  2. 名称:sub2api(或你选择的子域名)
  3. 目标:你的 VPS IP 地址
  4. 代理:开启(橙色云朵)

SSL 证书推荐使用 Cloudflare Origin CA:

第七步:验证

通过 curl 测试 HTTPS 是否正常工作:

curl -sI https://sub2api.your-domain.example.com | grep -i 'HTTP/'

应返回 HTTP/2 200。浏览器打开该地址,应能看到 Sub2API 的初始设置页面。

第八步:接入 NewAPI

Sub2API 部署完成后,在 NewAPI 管理后台的渠道页面添加自定义渠道:

  1. 类型:自定义渠道
  2. 名称:Sub2API
  3. Base URL:`https://sub2api.your-domain.example.com`(如在同一台 VPS 内部使用可直接写 `http://127.0.0.1:8081`)
  4. 密钥:在 Sub2API 管理后台生成的 API Key

这样 NewAPI 就可以将 Sub2API 作为上游渠道,把订阅配额分发给下游用户。

常见问题排查

错误 原因 解决方法
容器反复重启 PostgreSQL/Redis 未就绪 检查 `depends_on` 中的 condition 是否配置正确
端口冲突(port is already allocated) 宿主机端口已被占用 修改 `.env` 中的 `SERVER_PORT` 使用其他端口,或停掉占用端口的服务
502 Bad Gateway nginx 代理端口与容器端口不一致 确认 `proxy_pass` 的端口号与 `SERVER_PORT` 一致
管理员无法登录 JWT_SECRET 每次重启变化 设置固定的 `JWT_SECRET` 环境变量
粘性会话不生效 Nginx 丢弃了 `session_id` 头 检查 nginx 配置中是否包含 `underscores_in_headers on;`