Ubuntu20.04 部署 CLIProxyAPI 及 Win/Mac/Linux 三端 CLI 配置笔记
Ubuntu20.04 部署 CLIProxyAPI 及 Win/Mac/Linux 三端 CLI 配置笔记
最近把 Claude Code、Codex CLI、Gemini CLI、Cursor 统一接入了 CLIProxyAPI,让多台设备共享同一套订阅,不用每台机器都单独登录,这里记录一下服务端部署和客户端配置的过程,笔者用的是 Ubuntu 20.04 做服务端,客户端分别有 Windows 11、macOS 和 Linux,如有疏漏欢迎指出
服务端部署
安装
一键安装:
curl -fsSL https://raw.githubusercontent.com/brokechubb/cliproxyapi-installer/refs/heads/master/cliproxyapi-installer | bash
手动安装的话直接下载二进制就行:
mkdir -p /opt/cli-proxy-api && cd /opt/cli-proxy-api
wget https://github.com/router-for-me/CLIProxyAPI/releases/latest/download/cli-proxy-api-linux-amd64 -O cli-proxy-api
chmod +x cli-proxy-api
配置文件
默认路径 ~/.cli-proxy-api/config.yaml,也可以放在二进制同级目录
port: 8317
tls:
enable: false
remote-management:
allow-remote: true
secret-key: <bcrypt哈希>
disable-control-panel: false
auth-dir: /opt/cli-proxy-api/auths
api-keys:
- <自行生成的api-key>
debug: false
logging-to-file: true
logs-max-total-size-mb: 100
request-retry: 3
max-retry-interval: 30
routing:
strategy: round-robin
ws-auth: false
usage-statistics-enabled: true
port 默认 8317,可以改成自己想用的端口,api-keys 是给客户端鉴权用的,后面客户端配置里填的 key 就是这里的值,自行生成即可:
import secrets
print('sk-' + secrets.token_hex(32))
给多个用户用就在 api-keys 下面加多行,每人一个 key
OAuth 登录
启动服务后打开管理面板 http://服务端IP:端口/management.html,页面上有各平台的 OAuth 登录按钮,直接在浏览器里完成授权
如果服务端没有桌面环境,用命令行登录:
./cli-proxy-api --claude-login -no-browser
./cli-proxy-api --codex-login
./cli-proxy-api --login --project_id <Google Cloud项目ID>
-no-browser 会在终端输出 URL,复制到其他设备的浏览器里完成授权,同一命令重复执行可以添加多个账号做负载均衡
systemd 服务
cat > /etc/systemd/system/cli-proxy-api.service << 'EOF'
[Unit]
Description=CLIProxyAPI - Multi-provider AI API Proxy
After=network.target
[Service]
Type=simple
WorkingDirectory=/opt/cli-proxy-api
Environment=HOME=/root
ExecStart=/opt/cli-proxy-api/cli-proxy-api
Restart=on-failure
RestartSec=5
LimitNOFILE=65536
[Install]
WantedBy=multi-user.target
EOF
systemctl daemon-reload
systemctl enable cli-proxy-api
systemctl start cli-proxy-api
验证服务是否正常:
curl http://127.0.0.1:8317/v1/models -H "Authorization: Bearer <你的api-key>"
能返回模型列表就没问题,别忘了防火墙放行端口:
ufw allow 8317/tcp
客户端配置
下文中 <your-api-key> 统一指服务端 config.yaml 里 api-keys 中的值,<server-ip> 和 <port> 指服务端的 IP 和端口
如果服务端开启了 TLS,或者前面接了 HTTPS 反代,下面所有 http://<server-ip>:<port> 都改成域名形式,比如 https://<your-domain>,Claude Code 的 ANTHROPIC_BASE_URL 填到域名根路径,Codex、Cursor 走 OpenAI 兼容接口,base_url 要在域名后面加 /v1,也就是 https://<your-domain>/v1
Claude Code
安装
Claude Code 已切换为 native installer,不再推荐 npm 方式:
# macOS / Linux / WSL
curl -fsSL https://claude.ai/install.sh | bash
# Windows PowerShell
irm https://claude.ai/install.ps1 | iex
# Windows CMD
curl -fsSL https://claude.ai/install.cmd -o install.cmd && install.cmd && del install.cmd
也支持包管理器安装(不会自动更新,需手动升级):
# macOS (Homebrew)
brew install --cask claude-code
# Windows (WinGet)
winget install Anthropic.ClaudeCode
安装后二进制位于 ~/.local/bin/claude(Windows 为 %USERPROFILE%\.local\bin\claude.exe),确保该路径在 PATH 中
配置
编辑 ~/.claude/settings.json(Windows 路径为 C:\Users\用户名\.claude\settings.json):
{
"cleanupPeriodDays": 3650,
"autoCompactWindow": 400000,
"env": {
"ANTHROPIC_API_KEY": "<your-api-key>",
"ANTHROPIC_BASE_URL": "http://<server-ip>:<port>",
"CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC": "1",
"ANTHROPIC_MODEL": "claude-opus-4-7",
"ANTHROPIC_DEFAULT_OPUS_MODEL": "claude-opus-4-7",
"ANTHROPIC_DEFAULT_SONNET_MODEL": "claude-sonnet-4-6",
"ANTHROPIC_DEFAULT_HAIKU_MODEL": "claude-haiku-4-5-20251001"
}
}
上面这个是 Claude 官方模型名的写法,ANTHROPIC_MODEL 决定启动时直接使用哪个模型,ANTHROPIC_DEFAULT_OPUS_MODEL、ANTHROPIC_DEFAULT_SONNET_MODEL、ANTHROPIC_DEFAULT_HAIKU_MODEL 决定 /model 里 Opus / Sonnet / Haiku 档位分别指向谁,这里把三档固定到 4.7、4.6、4.5,默认启动 Opus,Haiku 4.5 要写完整的 claude-haiku-4-5-20251001
如果 CLIProxyAPI 里把 Claude Code 接到了 GPT、Gemini 或其他模型,也可以把这些变量指向服务端暴露出来的模型名:
{
"cleanupPeriodDays": 3650,
"autoCompactWindow": 400000,
"env": {
"ANTHROPIC_API_KEY": "<your-api-key>",
"ANTHROPIC_BASE_URL": "http://<server-ip>:<port>",
"CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC": "1",
"ANTHROPIC_MODEL": "gpt-5.5",
"ANTHROPIC_DEFAULT_OPUS_MODEL": "gpt-5.5",
"ANTHROPIC_DEFAULT_SONNET_MODEL": "gpt-5.5",
"ANTHROPIC_DEFAULT_HAIKU_MODEL": "gpt-5.5",
"ANTHROPIC_SMALL_FAST_MODEL": "gpt-5.5"
}
}
模型名按服务端 /v1/models 返回值填写,cleanupPeriodDays 是本地会话保留天数,不能设为 0,Claude Code 会拒绝无效值,想长期保留可以设大一点,比如 3650
autoCompactWindow 是自动压缩触发阈值,Claude Code 长会话超过这个阈值后,会把历史压成摘要再继续聊,在考虑到模型注意力和费用的前提下尽可能用上更大的上下文,综合社区讨论意见,推荐设置为 400k,当然用户可以根据自己的实际需要自行调整
CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC 建议保留,代理环境里尤其重要,它会关掉自动更新、反馈命令、错误上报和遥测,避免客户端在 API 请求之外继续访问官方服务,否则主请求走了 CLIProxyAPI,周边流量仍可能直连官方域名
1M 上下文
Claude Code 新版本会在需要长上下文时带上 context-1m 相关 beta header,如果直接走官方 Claude 模型,客户端会自己处理,经过 CLIProxyAPI 时,模型名可以加 [1m] 后缀,例如:
claude-opus-4-7[1m]
claude-sonnet-4-6[1m]
gpt-5.4[1m]
[1m] 表示按 1M 上下文请求模型,Claude OAuth 路径下 CPA 会补 context-1m-2025-08-07 beta,让上游按 1M 上下文处理;OpenAI 兼容模型没有这个 beta,CPA 会按模型目录里的上下文长度判断是否支持 1M,不支持的模型不要加 [1m]
[1m] 和 autoCompactWindow 管的是两层东西,[1m] 是模型能接收的上限,autoCompactWindow 是 Claude Code 本地什么时候开始压缩历史,两者取更早触发的那个,比如模型支持 1M,但 autoCompactWindow 设成 400k,Claude Code 仍会在 400k 左右自动压缩
清除旧 OAuth 凭证
如果之前用订阅方式登录过(/login 或 OAuth 授权),Claude Code 会优先使用缓存的 OAuth token 而非 settings.json 中的 API key 配置,所以 settings.json 改成 CLIProxyAPI 后,界面上仍显示 sk-ant-... 或继续走原订阅账号时,要先清除旧凭证
Claude Code 的凭证不是只放在一个 JSON 文件里,不同平台的位置如下:
| 平台 | 主存储位置 | 说明 |
|---|---|---|
| macOS | Keychain | 凭证存入系统钥匙串,~/.claude/.credentials.json 迁移后会被自动删除 |
| Linux(桌面) | Secret Service / libsecret | 通过系统密钥环存储,回退到 ~/.claude/.credentials.json |
| Linux(无头/容器) | ~/.claude/.credentials.json |
无桌面环境时直接用文件存储 |
| Windows | Credential Manager | 存入 Windows 凭据管理器,但在 Git Bash 环境下存在已知 bug 可能未持久化(#29049),回退到 ~/.claude/.credentials.json |
清除方法:
macOS——删除 Keychain 中的条目:
security delete-generic-password -s "Claude Code-credentials"
Linux——删除凭证文件:
rm ~/.claude/.credentials.json
Windows——需要同时清除两个位置(因为 已知 bug,token 可能没进 Credential Manager 而是落在文件里):
# 1. 删除凭据管理器中的条目(如果存在)
# 打开「控制面板 → 凭据管理器 → Windows 凭据」,找到 Claude Code 相关条目删除
# 或通过命令行:
cmdkey /delete:Claude Code-credentials
# 2. 删除文件凭证(如果存在)
del %USERPROFILE%\.claude\.credentials.json
三个平台通用的方式是在 Claude Code 交互界面中执行 /logout,然后重启
交互模式 "Not logged in" 问题
配好 API key 后,claude -p "say hi" 能正常返回,但交互模式提示 "Not logged in",优先检查 ~/.claude.json,非交互模式只发一次请求,交互模式还会读本地登录状态和自定义 API key 信任记录,所以两者表现可能不一致,这个问题已有记录(#27900)
排查步骤:
- 检查
~/.claude.json(注意不是~/.claude/settings.json)中的customApiKeyResponses字段,首次使用自定义 API key 时,Claude Code 会记录是否信任这个 key,key 后缀如果在rejected列表中,交互模式会拒绝使用它:
# 查看当前状态
python3 -c "import json; d=json.load(open('$HOME/.claude.json')); print(json.dumps(d.get('customApiKeyResponses', {}), indent=2))"
如果 rejected 列表中包含你的 key 后缀,将它移到 approved:
python3 -c "
import json, os
p = os.path.expanduser('~/.claude.json')
d = json.load(open(p))
d['customApiKeyResponses'] = {'approved': ['<你的key后20位>'], 'rejected': []}
json.dump(d, open(p, 'w'), indent=2)
"
- 检查同一文件中是否有残留的
oauthAccount字段,这个字段记录交互模式看到的 OAuth 账号,旧账号残留时会影响当前 API key:
python3 -c "
import json, os
p = os.path.expanduser('~/.claude.json')
d = json.load(open(p))
d.pop('oauthAccount', None)
json.dump(d, open(p, 'w'), indent=2)
"
跳过 onboarding
Claude Code 首次启动会进入交互式引导,包含信任目录和使用条款等状态,走代理时这个流程可能卡住,可以手动写入完成标记跳过,注意 ~/.claude.json 可能已经存在其他配置,不要用 cat > 或重定向覆盖,用 merge 方式写入:
python3 -c "
import json, os
p = os.path.expanduser('~/.claude.json')
d = json.load(open(p)) if os.path.exists(p) else {}
d['hasCompletedOnboarding'] = True
json.dump(d, open(p, 'w'), indent=2)
"
启动和验证
claude
或者非交互式测试:
claude -p "say hi"
能正常返回就说明配置没问题
Codex CLI
安装和更新
npm install -g @openai/codex
npm update -g @openai/codex
配置
用户级配置文件是 ~/.codex/config.toml,Windows 一般在 %USERPROFILE%\.codex\config.toml,Codex Desktop 的高级配置同样改这个 config.toml
model = "gpt-5.5"
model_provider = "cliproxyapi"
[model_providers.cliproxyapi]
name = "CLIProxyAPI"
base_url = "http://<server-ip>:<port>/v1"
wire_api = "responses"
API key 写到 ~/.codex/auth.json:
{
"OPENAI_API_KEY": "<your-api-key>"
}
base_url 注意末尾要带 /v1,wire_api = "responses" 不能省,Codex 现在走 OpenAI Responses API,少了这个字段可能会按默认协议发错请求,模型启动后可以用 /model 命令切换,Codex Desktop 会继承 CLI / IDE 的 agent 配置,高级项仍然改 config.toml,自定义 provider 没出现在桌面端模型选择器里时,以配置文件为准
启动和验证
codex
Gemini CLI
安装和更新
npm install -g @google/gemini-cli
npm update -g @google/gemini-cli
配置
Gemini CLI 没有配置文件,通过环境变量配置:
export GEMINI_API_KEY="<your-api-key>"
export GOOGLE_GEMINI_BASE_URL="http://<server-ip>:<port>"
写入 ~/.bashrc 或 ~/.zshrc 持久化,Windows 用 PowerShell 设用户级环境变量:
[System.Environment]::SetEnvironmentVariable('GEMINI_API_KEY', '<your-api-key>', 'User')
[System.Environment]::SetEnvironmentVariable('GOOGLE_GEMINI_BASE_URL', 'http://<server-ip>:<port>', 'User')
Gemini CLI 也支持 Google OAuth 直连,不走代理时可以免费用 Gemini 系列(1000次/天),启动 gemini 后选 Login with Google 就行,此时不要设上面的环境变量,因为 GEMINI_API_KEY 和 GOOGLE_GEMINI_BASE_URL 会让客户端走 CLIProxyAPI,和 Google OAuth 直连是两条路径
启动和验证
gemini
Cursor
Cursor 不是 CLI 工具,但通过 Override OpenAI Base URL 也能接入 CLIProxyAPI,所有模型(包括 Claude)统一走 OpenAI 兼容接口
配置
打开 Cursor → Settings → Models,在 OpenAI API Key 输入框填入 <your-api-key>,开启 Override OpenAI Base URL,填入:
http://<server-ip>:<port>/v1
然后在顶部 Add model 输入框手动添加 CLIProxyAPI 暴露的模型名,如 claude-opus-4-6、gpt-5.3-codex 等,添加后打开模型开关即可在 Chat/Composer 中选用,可用模型名通过 http://<server-ip>:<port>/v1/models 查看
Anthropic API Key、Google API Key 等其他 provider 的 key 不需要填,统一走 OpenAI Override,CPA 收到 OpenAI 格式请求后再转成 Claude 或 Gemini 上游格式
Cursor 目前没有独立的 Anthropic Base URL 覆盖选项,Claude 模型也要通过 OpenAI 兼容接口访问,Agent 模式比普通聊天更依赖 tool calling、streaming 和模型能力声明,这部分可能存在兼容性问题,普通聊天和代码生成不受影响
代理与 NO_PROXY 配置
如果客户端通过本地代理访问外网,务必把 CLIProxyAPI 服务端地址加入直连规则或 NO_PROXY
这条配置处理的是长连接空闲超时,Claude Code 做上下文压缩、处理大文件时,请求体已经发出,但模型在 prefill 阶段可能几十秒都没有流式输出,部分本地代理、机场节点、CDN 或反代会把这段时间当成连接空闲,60 秒左右主动断开,客户端收到错误后自动重试,下一次请求仍然卡在同一阶段,最后表现就是同一个请求反复失败十几次,耗时很久还没有结果
所以客户端访问自己的 CLIProxyAPI 时,最好直连服务端,不要再绕本地代理链路;如果服务端自己也走代理,请在 systemd 里把 localhost,127.0.0.1 放进 NO_PROXY,避免本机访问也绕出去
配置方法
macOS / Linux
在 ~/.zshrc 或 ~/.bashrc 中添加:
export NO_PROXY="localhost,127.0.0.1,<server-ip>"
Windows
设置用户级环境变量(通过「系统属性 → 环境变量」或 PowerShell):
[System.Environment]::SetEnvironmentVariable('NO_PROXY', 'localhost,127.0.0.1,<server-ip>', 'User')
同时在代理客户端的路由规则中将 <server-ip> 加入直连列表,仅设 NO_PROXY 环境变量可能不够——部分代理客户端通过系统代理或 TUN 模式接管流量,不受环境变量控制
Ubuntu 服务端(如果服务端自身也需要走代理)
在 systemd service 中配置代理时同样要排除自身:
[Service]
Environment="HTTP_PROXY=http://代理地址:端口"
Environment="HTTPS_PROXY=http://代理地址:端口"
Environment="NO_PROXY=localhost,127.0.0.1"
基于原版的二次改进
基于原版代码,做了安全、配置、使用统计和前端管理面板方面的优化,前后端仓库链接为:
后端:https://github.com/Pyrokine/CLIProxyAPI
前端:https://github.com/Pyrokine/Cli-Proxy-API-Management-Center
主要改动如下:
后端
- API Key 暴力破解防护:按来源 IP 统计失败次数,超限封禁
- 管理接口速率限制:管理密钥也不能无限试
- Key 校验改成恒定时间比较,降低时序攻击风险
- URL 查询参数传 Key 默认关闭,避免 key 进日志和 Referer
- WebSocket 认证默认开启
- SSRF 防护:拦截私有 IP、固定 DNS 解析结果、重定向后二次校验
- 代理地址校验:per-key proxy 不允许指向内网地址
- OAuth token 外泄防护:$TOKEN$ 只允许发往已知 AI 服务商域名
- 自更新链路加固:下载地址限制在 GitHub 域名,checksum 缺失或不匹配直接拒绝
- Gemini / iFlow OAuth 增加 state、PKCE 和 callback 校验
- CORS 改成可配置白名单
- 默认监听地址改成 127.0.0.1
- 配置保存保留注释,写盘权限改为 0600
- 使用统计持久化,按天归档,重启后统计不丢
- 读取上游响应和管理请求体时加大小限制,防止大响应撑爆内存
- Go 命名、日志、重复常量、Transport 构造等代码清理
前端
- 管理密钥从 localStorage XOR 混淆改为 AES-256-GCM 加密
- 敏感数据改存 sessionStorage,关闭标签页后清掉
- OAuth 跳转前校验 URL 协议,拦截 javascript: 这类注入
- 凭证管理页重做,按厂商分栏展示 API Key、OAuth、授权文件等
- Quota 信息嵌进凭证卡片
- API Key 支持别名,列表里优先显示别名
- 使用统计增加概览、模型分析、凭证分析、请求明细和设置页
- 使用统计支持 has_cost,不把缺价格的数据画成 0
- 请求明细导出改成分页拉全量,不只导出当前页
- 配置页支持可视化和源码双模式
- 离开配置页前提示未保存变更
- 上游仓库地址可在面板里配置
- 增加时区设置
- 增加 Qwen / iFlow 等服务商支持
- 模型价格支持在面板里维护
感谢
# CLIProxyAPI GitHub
https://github.com/router-for-me/CLIProxyAPI
# CLIProxyAPI 官方文档
https://help.router-for.me/
# Claude Code 官方文档
https://code.claude.com/docs/en/overview
# Claude Code 认证文档
https://code.claude.com/docs/en/authentication
# Claude Code 故障排查
https://code.claude.com/docs/en/troubleshooting
# Codex 配置文档
https://developers.openai.com/codex/config-advanced/
https://developers.openai.com/codex/config-reference/
https://developers.openai.com/codex/app/settings

浙公网安备 33010602011771号