CLIProxyAPI(四):生产部署——Nginx、TLS 与安全加固

前三篇覆盖了 CLIProxyAPI 的安装、基础配置、多账号轮询和高级路由策略。本篇聚焦生产环境落地:如何在公网服务器上稳定、安全地运行 CLIProxyAPI。

系列目录

  1. (一)入门——把 CLI 订阅变成标准 API
  2. (二)多账号轮询与配额策略
  3. (三)接入主流 AI 编程工具
  4. (四)生产部署——Nginx、TLS 与安全加固(本文)
  5. (五)Antigravity——用 Google 订阅解锁 Claude Opus 4.8
  6. (六)结合 new-api 打造多用户 API 网关
  7. (七)自动化运维——配额监控与告警
  8. (八)cpa_keeper 与 cpa_cost——用量追踪与成本分析工具

# 生产部署 ## 架构概览 - 公网域名 → Nginx/Caddy → CLIProxyAPI → 上游 ## Nginx 反代 - proxy_buffering off(流式必须) - proxy_read_timeout 300s - upstream 负载均衡 ## Caddy - 自动 TLS(Let's Encrypt) - 配置更简洁 ## TLS 直连 - 证书路径直接配置在 CLIProxyAPI - 省去反代层 ## 安全加固 - 绑定 127.0.0.1 禁止直接访问 - Cloudflare IP 白名单 - Nginx 限速 limit_req - 管理面板强密码 ## systemd 自启 - User= 非 root 运行 - Restart=always - WantedBy=default.target ## Docker Compose - OAuth 回调端口全部映射 - auth/ 目录持久化挂载 ## 日志 - logging-to-file: true - logrotate 定期轮转 ## 监控运维 - 定时检查清单 - proxy_buffering / TLS / 磁盘占用 - 常见故障排查

1. 部署架构概览

生产环境推荐将 CLIProxyAPI 置于反向代理之后,不直接暴露到公网。架构如下:

flowchart LR CL["客户端\nClaude Code / Cursor / Cline"] --> CF["Cloudflare\nDDoS 防护"] CF --> NG["Nginx / Caddy\nTLS + 限速"] NG -->|proxy_pass| CPA["CLIProxyAPI\n:8317 绑定 127.0.0.1"] CPA -. "登录时\n临时监听" .-> PO["OAuth 端口\n54545 / 8085 / 1455 / 51121"]

核心原则:

  • CLIProxyAPI 绑定 127.0.0.1,不对外暴露
  • Nginx/Caddy 负责 TLS 终止和限速
  • OAuth 回调端口仅在登录期间临时开放,平时可通过防火墙封闭
  • 可选在最前端加 Cloudflare 做 DDoS 防护

2. Nginx 反代配置

2.1 安装与站点配置

sudo apt install nginx -y
sudo nano /etc/nginx/sites-available/cpa

完整配置文件:

# /etc/nginx/sites-available/cpa

# 限速区域:每个 IP 每秒最多 10 个请求,突发 20
limit_req_zone $binary_remote_addr zone=cpa_limit:10m rate=10r/s;

# HTTP → HTTPS 重定向
server {
    listen 80;
    server_name api.example.com;
    return 301 https://$host$request_uri;
}

server {
    listen 443 ssl;
    http2 on;
    server_name api.example.com;

    # TLS 证书(Let's Encrypt 或自签)
    ssl_certificate     /etc/letsencrypt/live/api.example.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/api.example.com/privkey.pem;

    # 现代 TLS 配置
    ssl_protocols TLSv1.2 TLSv1.3;
    ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384;
    ssl_prefer_server_ciphers off;
    ssl_session_cache shared:SSL:10m;
    ssl_session_timeout 1d;

    # 安全头
    add_header Strict-Transport-Security "max-age=63072000; includeSubDomains" always;
    add_header X-Content-Type-Options nosniff always;
    add_header X-Frame-Options DENY always;

    # 限速(管理 API 单独限速更严格)
    location /v0/management/ {
        limit_req zone=cpa_limit burst=5 nodelay;
        proxy_pass http://127.0.0.1:8317;
        include /etc/nginx/cpa_proxy_params;
    }

    location / {
        limit_req zone=cpa_limit burst=20 nodelay;
        proxy_pass http://127.0.0.1:8317;
        include /etc/nginx/cpa_proxy_params;
    }
}

2.2 公共代理参数文件

将重复的代理参数提取到独立文件,便于复用:

# /etc/nginx/cpa_proxy_params

proxy_http_version 1.1;
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_set_header Connection "";

# 流式输出关键配置:必须关闭缓冲
proxy_buffering off;
proxy_cache off;

# 超时设置:AI 推理可能较慢,设置宽松一些
proxy_read_timeout 300s;
proxy_connect_timeout 10s;
proxy_send_timeout 60s;

# 支持大请求体(上传文件等场景)
client_max_body_size 50m;

注意proxy_buffering off 是流式输出(SSE)的必要条件。如果忘记配置,客户端会等到响应完整后才收到数据,导致超时或体验极差。

flowchart LR C["客户端\nSSE 请求"] --> NG["Nginx :443\nTLS 终止 + limit_req"] NG -->|"proxy_buffering off\nproxy_pass"| CPA["CLIProxyAPI :8317\n127.0.0.1"] CPA -->|"流式 token"| NG -->|"逐块转发"| C

2.3 启用站点

sudo ln -s /etc/nginx/sites-available/cpa /etc/nginx/sites-enabled/
sudo nginx -t          # 检查配置语法
sudo systemctl reload nginx

2.4 申请 Let's Encrypt 证书

sudo apt install certbot python3-certbot-nginx -y
sudo certbot --nginx -d api.example.com
# 按提示操作,certbot 会自动修改 nginx 配置并设置自动续期

3. Caddy 反代配置

如果不想手动管理证书,Caddy 是更简单的选择——自动申请和续期 TLS 证书。

3.1 安装 Caddy

sudo apt install -y debian-keyring debian-archive-keyring apt-transport-https curl
curl -1sLf 'https://dl.cloudsmith.io/public/caddy/stable/gpg.key' | sudo gpg --dearmor -o /usr/share/keyrings/caddy-stable-archive-keyring.gpg
curl -1sLf 'https://dl.cloudsmith.io/public/caddy/stable/debian.deb.txt' | sudo tee /etc/apt/sources.list.d/caddy-stable.list
sudo apt update && sudo apt install caddy -y

3.2 Caddyfile 配置

# /etc/caddy/Caddyfile

api.example.com {
    # Caddy 自动申请 Let's Encrypt 证书

    # 限速(需要 caddy-ratelimit 插件,或使用 Cloudflare 限速)
    # rate_limit {
    #     zone dynamic 10r/s
    # }

    # 流式输出:禁用响应缓冲
    reverse_proxy 127.0.0.1:8317 {
        flush_interval -1   # -1 表示立即 flush,等同于 proxy_buffering off
        transport http {
            read_buffer  0
            write_buffer 0
        }
        header_up X-Forwarded-For {remote_host}
        header_up X-Real-IP {remote_host}

        # 超时配置
        transport http {
            dial_timeout        10s
            response_header_timeout 300s
            tls_handshake_timeout   10s
        }
    }

    # 安全头
    header {
        Strict-Transport-Security "max-age=63072000; includeSubDomains"
        X-Content-Type-Options nosniff
        X-Frame-Options DENY
        -Server
    }

    # 管理 API 限制仅内网访问(可选)
    @management path /v0/management/*
    handle @management {
        # 如只允许特定 IP 访问管理接口,取消下面注释
        # @allowed remote_ip 1.2.3.4/32
        # handle @allowed {
        #     reverse_proxy 127.0.0.1:8317 { flush_interval -1 }
        # }
        # respond "Forbidden" 403
        reverse_proxy 127.0.0.1:8317 {
            flush_interval -1
        }
    }
}

启动 Caddy:

sudo systemctl enable --now caddy
sudo caddy validate --config /etc/caddy/Caddyfile  # 验证配置
sudo systemctl reload caddy

4. TLS 直连模式(不使用反代)

如果不想配置反代,CLIProxyAPI 支持在 config.yaml 中直接配置 TLS:

# config.yaml

port: 8317
host: "0.0.0.0"   # 直连模式需要监听所有接口

tls:
  cert: "/etc/certs/api.example.com/fullchain.pem"
  key:  "/etc/certs/api.example.com/privkey.pem"

api-keys:
  - "your-strong-api-key"

直连模式的客户端访问地址为 https://api.example.com:8317

适用场景:内网部署、个人使用、不想维护 Nginx/Caddy 的情况。

注意:直连模式无法享受 Nginx 的限速、访问控制等功能,公网部署建议仍使用反代。


5. 公网访问安全加固

5.1 绑定本地接口

反代模式下,CLIProxyAPI 只监听 127.0.0.1,防止绕过反代直接访问:

# config.yaml
host: "127.0.0.1"
port: 8317

5.2 启用远程管理与安全策略

# config.yaml

remote-management:
  allow-remote: true          # 允许非 127.0.0.1 的请求访问管理 API
  # 5 次密码错误后封禁 30 分钟(内置暴力破解防护)
  # 此行为是默认启用的,无需额外配置

管理面板的 API Key 务必使用高强度密码:

api-keys:
  - "cpa-Xk9mP2qR7vL4nT8wZ1jY5cA3bF6hD0eG"   # 随机生成,至少32位

生成随机密钥:

openssl rand -hex 24
# 输出示例:a3f8c2e1b5d4a9f7e6c3b2a1d8e5f4c3a9b8e7d6

5.3 配合 Nginx 限速防暴力破解

上文 Nginx 配置中已经包含了 limit_req_zone。对管理接口可以设置更严格的限速:

limit_req_zone $binary_remote_addr zone=cpa_mgmt:1m rate=2r/m;

location /v0/management/auth {
    limit_req zone=cpa_mgmt burst=3 nodelay;
    proxy_pass http://127.0.0.1:8317;
    include /etc/nginx/cpa_proxy_params;
}

5.4 配合 Cloudflare

如果域名使用了 Cloudflare,可以额外:

  1. 在 Cloudflare WAF 中对 /v0/management/ 路径设置访问规则,限制只有你的 IP 才能访问
  2. 启用 Cloudflare Rate Limiting,对 /v1/chat/completions 设置每分钟请求上限
  3. 开启 Bot Fight Mode,过滤明显的自动化攻击流量
flowchart LR ATK["攻击流量 / 公网请求"] --> CF["Cloudflare\nWAF + Rate Limit\nBot Fight Mode"] CF -->|"合法流量"| NG["Nginx\nlimit_req + TLS\n安全响应头"] NG -->|"proxy_pass\n127.0.0.1"| CPA["CLIProxyAPI\n本地绑定\nAPI Key 鉴权"]

6. systemd 服务配置

手动安装(非 Docker)时,使用 systemd 管理进程生命周期。

6.1 创建服务文件

# /etc/systemd/system/cliproxyapi.service

[Unit]
Description=CLIProxyAPI - CLI OAuth to API Proxy
Documentation=https://help.router-for.me/cn/
After=network-online.target
Wants=network-online.target

[Service]
Type=simple
User=cpa                           # 建议用专用低权限用户运行
Group=cpa
WorkingDirectory=/opt/cliproxyapi

# 指定配置文件路径
ExecStart=/usr/local/bin/cliproxyapi --config /etc/cliproxyapi/config.yaml

# 进程异常退出时自动重启
Restart=on-failure
RestartSec=5s
StartLimitInterval=60s
StartLimitBurst=3

# 安全加固:限制系统调用权限
NoNewPrivileges=true
PrivateTmp=true
ProtectSystem=strict
ReadWritePaths=/etc/cliproxyapi /var/log/cliproxyapi /var/lib/cliproxyapi

# 日志输出到 journald
StandardOutput=journal
StandardError=journal
SyslogIdentifier=cliproxyapi

[Install]
WantedBy=multi-user.target

6.2 创建专用用户

sudo useradd --system --no-create-home --shell /sbin/nologin cpa
sudo mkdir -p /etc/cliproxyapi /var/log/cliproxyapi /var/lib/cliproxyapi
sudo chown -R cpa:cpa /etc/cliproxyapi /var/log/cliproxyapi /var/lib/cliproxyapi

6.3 启动服务

sudo systemctl daemon-reload
sudo systemctl enable cliproxyapi
sudo systemctl start cliproxyapi
sudo systemctl status cliproxyapi

# 查看实时日志
sudo journalctl -u cliproxyapi -f

7. Docker 生产部署

7.1 目录结构

/opt/cliproxyapi/
├── docker-compose.yml
├── config.yaml
├── auth/ # OAuth 认证文件(需持久化)
│ ├── claude/
│ ├── gemini/
│ └── codex/
└── logs/ # 日志文件

7.2 docker-compose.yml

# docker-compose.yml

services:
  cliproxyapi:
    image: cliproxyapi/cliproxyapi:7.1.45   # 固定版本,避免自动升级破坏稳定性
    container_name: cliproxyapi
    restart: unless-stopped

    # 端口映射说明:
    # - 8317: 主服务端口(仅绑定本地,由 Nginx 反代)
    # - 54545: Claude Code OAuth 回调
    # - 8085: Gemini CLI OAuth 回调
    # - 1455: Codex OAuth 回调
    # - 51121: Antigravity OAuth 回调
    ports:
      - "127.0.0.1:8317:8317"    # 主服务只绑定本地
      - "54545:54545"             # OAuth 回调需要公网可达(登录期间)
      - "8085:8085"
      - "1455:1455"
      - "51121:51121"

    volumes:
      - ./config.yaml:/app/config.yaml:ro
      - ./auth:/app/auth
      - ./logs:/app/logs

    environment:
      - TZ=Asia/Shanghai

    # 资源限制
    deploy:
      resources:
        limits:
          cpus: "2.0"
          memory: 512M
        reservations:
          cpus: "0.1"
          memory: 64M

    # 健康检查
    healthcheck:
      test: ["CMD", "wget", "-qO-", "http://localhost:8317/health"]
      interval: 30s
      timeout: 10s
      retries: 3
      start_period: 10s

    # 日志轮转(防止日志文件无限增长)
    logging:
      driver: "json-file"
      options:
        max-size: "50m"
        max-file: "5"

    networks:
      - cpa_net

networks:
  cpa_net:
    driver: bridge

7.3 对应的 config.yaml(Docker 版)

# config.yaml(Docker 容器内路径)

port: 8317
host: "0.0.0.0"      # 容器内监听所有接口,由 docker ports 控制外部访问

auth-dir: "/app/auth"

api-keys:
  - "your-strong-api-key-here"

# 日志配置
logging-to-file: true
logs-dir: "/app/logs"
logs-max-total-size-mb: 500
error-logs-max-files: 10

# 远程管理
remote-management:
  allow-remote: true

# 路由策略
routing:
  strategy: "round-robin"
  session-affinity: true

# 配额超限自动切换
quota-exceeded:
  switch-project: true

providers:
  - name: "claude"
    type: "claude-code"
  - name: "gemini"
    type: "gemini-cli"

7.4 启动与管理

cd /opt/cliproxyapi

# 首次启动
docker compose up -d

# 查看日志
docker compose logs -f

# 更新版本
docker compose pull
docker compose up -d

# 进入容器执行登录(首次需要)
docker compose exec cliproxyapi cliproxyapi --claude-login

7.5 Docker 网络注意事项

如果 Nginx 也跑在 Docker 中,需要让两个容器在同一网络下,否则 proxy_pass http://127.0.0.1:8317 会失败:

# nginx 的 docker-compose.yml 片段
services:
  nginx:
    image: nginx:alpine
    networks:
      - cpa_net      # 加入同一网络

# cliproxyapi 的端口改为不绑定本地
ports:
  - "8317:8317"     # 去掉 127.0.0.1: 前缀,允许同网络容器访问

Nginx 配置中的 proxy_pass 改为容器名:

proxy_pass http://cliproxyapi:8317;

8. 日志配置

# config.yaml 日志相关字段

# 是否写入文件日志(默认只输出到 stdout)
logging-to-file: true

# 日志文件目录
logs-dir: "/var/log/cliproxyapi"

# 所有日志文件总大小上限(MB),超出后自动轮转删除旧文件
logs-max-total-size-mb: 1000

# 错误日志最多保留几个文件
error-logs-max-files: 20

日志级别(通过启动参数控制):

cliproxyapi --config config.yaml --log-level debug   # 调试模式,输出详细信息
cliproxyapi --config config.yaml --log-level info    # 默认级别
cliproxyapi --config config.yaml --log-level warn    # 只记录警告和错误

使用 journalctl 查看 systemd 服务日志(如果使用 systemd):

# 查看最近 100 行
sudo journalctl -u cliproxyapi -n 100

# 按时间范围筛选
sudo journalctl -u cliproxyapi --since "2026-06-05 08:00" --until "2026-06-05 12:00"

# 只看错误
sudo journalctl -u cliproxyapi -p err

9. 监控与运维

9.1 管理 API 查看使用量

CLIProxyAPI 提供管理 API,可以查询各账号的用量数据:

# 查看所有 API Key 的用量统计
curl -H "Authorization: Bearer your-api-key" \
     https://api.example.com/v0/management/api-key-usage

# 查看当前所有账号状态(是否在线、配额剩余等)
curl -H "Authorization: Bearer your-api-key" \
     https://api.example.com/v0/management/providers

# 查看路由统计
curl -H "Authorization: Bearer your-api-key" \
     https://api.example.com/v0/management/routing-stats

典型响应示例:

{
  "api_keys": [
    {
      "key_prefix": "cpa-Xk9m...",
      "total_requests": 1523,
      "total_tokens": 2847361,
      "last_used": "2026-06-05T21:30:00Z"
    }
  ]
}

9.2 社区工具

CPA Usage Keeper:监控各账号用量,在配额接近上限时发送通知(支持 Telegram、企业微信)。

CPA-Manager-Plus:带 Web UI 的管理面板增强版,支持可视化查看账号状态、手动触发路由切换、导入导出配置。

这两个工具均由社区维护,可在 CLIProxyAPI 官方社区频道找到。

9.3 与 new-api / One-API 集成

CLIProxyAPI 输出标准 OpenAI 兼容接口,可以作为 new-api 或 One-API 的上游渠道,实现统一的多渠道管理:

用户 → One-API(统一入口、计费、限速) → CLIProxyAPI(OAuth 转换) → Claude/Gemini/Codex

在 One-API 中添加渠道时:

  • 渠道类型:选 OpenAI
  • API 地址:https://api.example.com(你的 CLIProxyAPI 地址)
  • API Key:CLIProxyAPI 配置的 api-keys 中的任意一个
  • 模型:填写 CLIProxyAPI 中配置的模型名或别名

这样可以用 One-API 的计费和 Key 管理功能,将 CLIProxyAPI 作为后端算力池。


10. 常见生产问题

10.1 端口冲突

症状:CLIProxyAPI 启动失败,日志显示 address already in use

# 查看端口占用
sudo ss -tlnp | grep 8317
sudo lsof -i :8317

# 找到占用进程后决定是否终止
sudo kill -9 <pid>

OAuth 回调端口冲突(如 8085 被其他服务占用):在登录前临时停止冲突服务,登录完成后恢复。

10.2 Docker 容器无法访问 OAuth 回调

症状:在 Docker 容器内执行 --claude-login,浏览器重定向到 localhost:54545 但无法连接。

原因:OAuth 回调地址是 localhost,浏览器访问的是宿主机,而不是容器内部。

解决方案:OAuth 登录在宿主机执行,将生成的 auth/ 目录挂载进容器:

# 1. 在宿主机(非容器内)先完成登录
cliproxyapi --claude-login --auth-dir ./auth

# 2. auth 目录已挂载进容器,容器自动识别登录态
docker compose restart cliproxyapi

10.3 Nginx 流式输出卡顿

症状:客户端收到数据一段一段的,有明显的延迟感,而不是逐字流式输出。

排查顺序

  1. 确认 Nginx 配置中有 proxy_buffering off
  2. 确认客户端请求头包含 Accept: text/event-stream
  3. 检查 Cloudflare 是否启用了缓冲(在 Page Rules 中对 API 路径关闭 Rocket Loader 和 Polish)
  4. 如果使用了 AWS ALB / CloudFront 等,检查其是否有响应缓冲设置

10.4 Let's Encrypt 证书续期失败

证书每 90 天需要续期。Certbot 安装时会自动创建 systemd timer 或 cron job,验证是否生效:

sudo systemctl status certbot.timer
sudo certbot renew --dry-run    # 模拟续期,测试配置是否正确

如果使用 Caddy,续期是全自动的,无需手动操作。

10.5 生产环境配置核查清单

检查项 命令
CLIProxyAPI 只监听 127.0.0.1 ss -tlnp | grep 8317
Nginx 配置了 proxy_buffering off grep -n proxy_buffering /etc/nginx/sites-available/cpa
TLS 证书有效期 openssl s_client -connect api.example.com:443 </dev/null 2>/dev/null | openssl x509 -noout -dates
systemd 服务开机自启 systemctl is-enabled cliproxyapi
日志磁盘占用 du -sh /var/log/cliproxyapi/
防火墙只开放必要端口 sudo ufw status

系列导航

实操清单

  • Caddy 反向代理配置完成(cliproxy.k330.com,自动 HTTPS)
  • flush_interval -1 已配置(流式输出正常)
  • systemd 服务运行中(开机自启)
  • Remote management 已开启(allow-remote: true,secret-key 已设)
  • host 改为 "127.0.0.1"(已配置,服务只监听本地接口)
  • 开启文件日志:logging-to-file: truelogs-dir: /home/sdmike/cliproxyapi/logslogs-max-total-size-mb: 500
  • TLS 证书有效期验证通过(有效至 2026-09-03)
  • 服务只监听 127.0.0.1:8317(ss -tlnp | grep 8317 已确认)
  • 重启服务(sudo systemctl restart cliproxyapi)并验证功能正常