目录

NewAPI Docker 部署指南

本文记录在 VPS 上使用 Docker 部署 NewAPI,并通过 nginx + Cloudflare Origin CA 证书配置 HTTPS 反向代理的完整流程。该流程具有通用性,可供任何人复现。

环境准备

前期需要准备:

  1. 一台 VPS(本文以 Debian 12 为例)
  2. 一个托管在 Cloudflare 的域名
  3. 服务器已安装 Docker 和 Docker Compose
  4. 服务器已安装 nginx

第一步:创建项目目录

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

mkdir -p /root/newapi/data

第二步:编写 Docker Compose 配置

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

services:
  new-api:
    image: calciumion/new-api:v1.0.0-rc.21-amd64
    container_name: new-api
    restart: always
    environment:
      - TZ=Asia/Shanghai
      - SESSION_SECRET=<生成一个64位随机十六进制字符串>
    ports:
      - "127.0.0.1:3000:3000"
    volumes:
      - ./data:/data

关键说明:

  1. 镜像版本:`v1.0.0-rc.21-amd64` 为本文撰写时的最新版,请根据实际检查获取最新版本号
  2. SESSION_SECRET:用于会话加密,必须自行生成。在终端执行 `openssl rand -hex 32` 生成一个 64 位十六进制字符串
  3. 端口映射:绑定到 `127.0.0.1`,避免容器端口直接暴露到公网。外部访问通过 nginx 反向代理
  4. 数据持久化:`./data:/data` 将 SQLite 数据库映射到宿主机目录,容器重启数据不丢失

第三步:配置 Nginx 反向代理

创建 `/etc/nginx/sites-enabled/newapi`:

# HTTP → HTTPS 自动跳转
server {
    listen 80;
    listen [::]:80;
    server_name your-domain.example.com;
    return 301 https://$host$request_uri;
}
 
# HTTPS
server {
    listen 443 ssl;
    listen [::]:443 ssl;
    server_name 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;
 
    client_max_body_size 20M;
    proxy_read_timeout 120;
    proxy_send_timeout 120;
 
    location / {
        proxy_pass http://127.0.0.1:3000;
        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";
    }
}

配置完成后测试并重载 nginx:

nginx -t          # 测试配置语法
nginx -s reload   # 重载配置

第四步:开放防火墙

如果服务器启用了 ufw 防火墙,放行 80 和 443 端口:

ufw allow 80/tcp comment 'HTTP'
ufw allow 443/tcp comment 'HTTPS'

第五步:配置 Cloudflare SSL 证书

本文使用 Cloudflare Origin CA 证书实现 HTTPS。步骤如下:

  1. 登录 Cloudflare Dashboard,进入目标域名的 SSL/TLS → Origin Server
  2. 点击 Create Certificate
  3. 私钥类型选择 RSA(2048),主机名保持默认(包含裸域和通配符)
  4. 有效期选择 15 年
  5. 点击 Create
  6. 将显示的 Origin Certificate 保存为 `your-cert.crt`,Private Key 保存为 `your-cert.key`

注意:私钥只展示一次,务必及时保存。

上传证书到服务器:

scp your-cert.crt user@your-server:/etc/ssl/
scp your-cert.key user@your-server:/etc/ssl/

设置私钥权限:

chown root:www-data /etc/ssl/your-cert.key
chmod 640 /etc/ssl/your-cert.key

回到 Cloudflare Dashboard → SSL/TLS,将加密模式设为 Full (Strict)。

第六步:配置 Cloudflare WAF(避免下游客户端被拦截)

NewAPI 部署完成后,下游客户端使用 OpenAI 官方 Python 库连接时可能遇到 HTTP 403「Your request was blocked」错误。原因是该库发出的 HTTP 请求默认使用 User-Agent: OpenAI/Python …,会被 Cloudflare WAF 的托管规则集拦截。

在 Cloudflare 仪表盘中添加一条 WAF 自定义规则即可解决:

  1. 登录 dash.cloudflare.com → 选择域名 → Security → WAF → Custom rules
  2. 点击 Create rule
  3. Rule name:可填写「Allow OpenAI Python client」
  4. 条件:字段 User Agent,运算符 contains,值 OpenAI/Python
  5. (可选)如果只想对该 NewAPI 子域名生效,再添加一行条件:Hostname equals your-domain.example.com
  6. Action:选择 Skip
  7. 在「WAF components to skip」中勾选 All managed rules
  8. 点击 Deploy

注意表达式中的 OpenAI/Python 前面不要加空格,否则规则无法匹配。部署后立即生效。

替代方案:如果无法修改 Cloudflare 配置,也可以在客户端侧解决。以 Hermes Agent 为例,通过自定义请求头将 User-Agent 改为非 SDK 默认值:

hermes config set model.extra_headers.User-Agent "curl/7.86.0"

修改后所有调用都会使用 User-Agent: curl/7.86.0,不再被 WAF 拦截。

第七步:启动容器

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

验证容器运行状态:

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

第八步:验证

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

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

应返回 HTTP/2 200 或 301。

浏览器访问 https://your-domain.example.com,应看到 NewAPI 的初始化页面。

常见问题排查

错误 原因 解决方法
容器反复重启 数据目录权限问题 检查 `./data` 目录的权限,执行 `chown -R 1000:1000 ./data`
521 Web 服务器拒绝连接 端口未放行或 nginx 未运行 确认 ufw 放行了 80/443,`nginx -t` 检查配置
526 无效的 SSL 证书 Full (Strict) 模式下使用了自签名证书 改用 Origin CA 证书,或将 CF 模式降级为 Full
容器启动后无法访问 SESSION_SECRET 未设置或为空 检查 docker-compose.yml 中 SESSION_SECRET 是否正确
403 Your request was blocked CF WAF 拦截了 OpenAI Python 库的 User-Agent 按第六步添加 WAF Skip 规则