CLIProxyAPI(四):生产部署——Nginx、TLS 与安全加固
前三篇覆盖了 CLIProxyAPI 的安装、基础配置、多账号轮询和高级路由策略。本篇聚焦生产环境落地:如何在公网服务器上稳定、安全地运行 CLIProxyAPI。
系列目录
1. 部署架构概览
生产环境推荐将 CLIProxyAPI 置于反向代理之后,不直接暴露到公网。架构如下:
核心原则:
- 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)的必要条件。如果忘记配置,客户端会等到响应完整后才收到数据,导致超时或体验极差。
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,可以额外:
- 在 Cloudflare WAF 中对
/v0/management/路径设置访问规则,限制只有你的 IP 才能访问 - 启用 Cloudflare Rate Limiting,对
/v1/chat/completions设置每分钟请求上限 - 开启 Bot Fight Mode,过滤明显的自动化攻击流量
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 目录结构
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 流式输出卡顿
症状:客户端收到数据一段一段的,有明显的延迟感,而不是逐字流式输出。
排查顺序:
- 确认 Nginx 配置中有
proxy_buffering off - 确认客户端请求头包含
Accept: text/event-stream - 检查 Cloudflare 是否启用了缓冲(在 Page Rules 中对 API 路径关闭 Rocket Loader 和 Polish)
- 如果使用了 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 |
系列导航
- (一)入门——把 CLI 订阅变成标准 API
- (二)多账号轮询与配额策略
- (三)接入主流 AI 编程工具
- (四)生产部署——Nginx、TLS 与安全加固(本文)
- (五)Antigravity——用 Google 订阅解锁 Claude Opus 4.8
- (六)结合 new-api 打造多用户 API 网关
- (七)自动化运维——配额监控与告警
- (八)cpa_keeper 与 cpa_cost——用量追踪与成本分析工具
实操清单
- Caddy 反向代理配置完成(cliproxy.k330.com,自动 HTTPS)
- flush_interval -1 已配置(流式输出正常)
- systemd 服务运行中(开机自启)
- Remote management 已开启(allow-remote: true,secret-key 已设)
- 将
host改为"127.0.0.1"(已配置,服务只监听本地接口) - 开启文件日志:
logging-to-file: true,logs-dir: /home/sdmike/cliproxyapi/logs,logs-max-total-size-mb: 500 - TLS 证书有效期验证通过(有效至 2026-09-03)
- 服务只监听 127.0.0.1:8317(
ss -tlnp | grep 8317已确认) - 重启服务(
sudo systemctl restart cliproxyapi)并验证功能正常