CLI-Proxy-API
CLIProxyAPI 的 Docker Compose 部署、管理接口保护、更新及统计数据备份恢复。
介绍
- 无需安装 Gemini CLI,即可将其授权转换为通用的 API Key,从而在任何应用中调用功能完整的 Gemini 2.5 Pro、Gemini 2.5 Flash、Gemini 2.5 Flash Lite 模型。当正式版模型配额用尽后,它会自动切换到 Preview 模型(如
gemini-2.5-pro-preview-05-06),基本能用足每天 1000 次的调用配额,轻松实现“Gemini 自由”。 - 无需安装 Qwen Code,即可将其授权转换为通用的 API Key,在任何地方调用 Qwen3 Coder Plus、Qwen3 Coder Flash 模型,实现“Qwen3 Coder 自由”。
- 无需安装 Codex,即可将其授权转换为通用的 API Key,在任何地方调用 GPT-5、GPT-5-Codex 模型。尤其在目前可以免费开设 Team 账户的活动下,轻松实现“GPT 自由”。
- 将 Gemini 网页版转换为 API Key,在任何地方调用 Nano Banana 等网页版模型(需客户端支持。据网友分享,免费版 Gemini 网页账户每天可调用约 100 次,而 Gemini Pro 用户则高达 1000 次)。
- 强大的负载均衡能力。CLIProxyAPI 支持将不同来源(无论是 API Key 还是 OAuth 授权)的多个账户整合在一起进行负载均衡轮询,这意味着你可以轻松地将调用配额翻倍。
- 极低的资源消耗。值得一提的是,该程序对系统资源的消耗极低。程序本身仅 10MB 左右,启动时内存占用不到 10MB,长时间峰值内存占用也仅有 100MB 左右,几乎任何电脑都能流畅运行。
docker compost部署
1.创建目录和配置文件
mkdir -p /data/CLIProxyAPI && touch /data/CLIProxyAPI/config.yaml
2.修改配置文件
# Server host/interface to bind to. Default is empty ("") to bind all interfaces (IPv4 + IPv6).
# Use "127.0.0.1" or "localhost" to restrict access to local machine only.
host: ""
# Server port
port: 8317
# TLS settings for HTTPS. When enabled, the server listens with the provided certificate and key.
tls:
enable: false
cert: ""
key: ""
# Management API settings
remote-management:
# Whether to allow remote (non-localhost) management access.
# When false, only localhost can access management endpoints (a key is still required).
allow-remote: true
# Management key. If a plaintext value is provided here, it will be hashed on startup.
# All management requests (even from localhost) require this key.
# Leave empty to disable the Management API entirely (404 for all /v0/management routes).
secret-key: "REPLACE_WITH_STRONG_SECRET"
# Disable the bundled management control panel asset download and HTTP route when true.
disable-control-panel: false
# GitHub repository for the management control panel. Accepts a repository URL or releases API URL.
panel-github-repository: "https://github.com/router-for-me/Cli-Proxy-API-Management-Center"
# Authentication directory (supports ~ for home directory)
auth-dir: "~/.cli-proxy-api"
3.运行 mkdir -p /data/CLIProxyAPI && touch /data/CLIProxyAPI/compose.yaml ,创建 docker compose 文件,并配置
services:
cli-proxy-api:
image: eceasy/cli-proxy-api:latest
container_name: cli-proxy-api
ports:
- "8317:8317"
volumes:
- ./config.yaml:/CLIProxyAPI/config.yaml
- ./auths:/root/.cli-proxy-api
restart: unless-stopped
4.运行命令 cd /data/CLIProxyAPI && docker compose up -d ,创建容器
5.访问:服务器IP:8317/management.html
webUI启动
注意:
WebUI 中的 OAuth 认证功能仅支持本地运行(例如 localhost 或 127.0.0.1)的 CLIProxyAPI 实例。对于部署在远程服务器上的实例,由于 OAuth 服务商的安全策略限制,将无法通过 WebUI 直接完成认证。
访问页面http://localhost:8317/management.html#/ `

更新cpa
最稳的更新流程:
1.先导出统计数据 用面板里的“导出”按钮,或者先备份一份导出文件。
2.备份配置 建议至少备份这几个: -
/data/CLIProxyAPI/.env
/data/CLIProxyAPI/config.yaml
/data/CLIProxyAPI/auths/
/data/CLIProxyAPI/compose.yaml
3.拉新镜像并重建主容器
cd /data/CLIProxyAPI
docker pull eceasy/cli-proxy-api:latest
docker compose up -d --force-recreate cli-proxy-api
4.检查是否启动成功
docker ps | grep cli-proxy-api
docker logs --tail 100 cli-proxy-api
5.登录面板确认版本和统计
自动更新 + 备份恢复
CPA 可以用 watchtower 做镜像自动更新,并配合生命周期钩子在更新前导出统计数据、更新后再导入统计数据。这样更新容器时,运行态统计数据可以先保存到宿主机目录,容器重建完成后再恢复。
自动更新配置
核心服务仍然由 compose.yaml 管理,watchtower 负责定时检查镜像:
watchtower:
image: nickfedor/watchtower:latest
container_name: watchtower
restart: always
volumes:
- /var/run/docker.sock:/var/run/docker.sock
environment:
TZ: Asia/Shanghai
WATCHTOWER_CLEANUP: "true"
WATCHTOWER_POLL_INTERVAL: "3600"
WATCHTOWER_SCOPE: "cliproxy"
WATCHTOWER_LIFECYCLE_HOOKS: "true"
command: --scope cliproxy
业务容器需要加上相同的 scope 标签,并配置更新前、更新后的钩子:
labels:
- "com.centurylinklabs.watchtower.scope=cliproxy"
- "com.centurylinklabs.watchtower.lifecycle.pre-update=/bin/sh -c 'curl -sf -H \"Authorization: Bearer ${MANAGEMENT_PASSWORD}\" http://localhost:8317/v0/management/usage/export -o /CLIProxyAPI/persist/usage-backup.json.tmp && test -s /CLIProxyAPI/persist/usage-backup.json.tmp && mv /CLIProxyAPI/persist/usage-backup.json.tmp /CLIProxyAPI/persist/usage-backup.json || { rm -f /CLIProxyAPI/persist/usage-backup.json.tmp; exit 1; }'"
- "com.centurylinklabs.watchtower.lifecycle.post-update=/bin/sh -c 'sleep 3 && test -s /CLIProxyAPI/persist/usage-backup.json && curl -sf -X POST -H \"Content-Type: application/json\" -H \"Authorization: Bearer ${MANAGEMENT_PASSWORD}\" --data-binary @/CLIProxyAPI/persist/usage-backup.json http://localhost:8317/v0/management/usage/import'"
这里更新前先写入 .tmp 临时文件,确认导出成功且文件非空后,再替换正式备份文件。这样可以避免导出失败时把旧备份清空。
MANAGEMENT_PASSWORD 来自 /data/CLIProxyAPI/.env 或执行 docker compose 时所在 Shell 的环境变量。docker compose 读取 compose.yaml 时会把 ${MANAGEMENT_PASSWORD} 替换成实际值,然后写入容器标签和容器环境变量。watchtower 执行生命周期钩子时,标签里的命令已经带有实际管理密码,所以 Authorization: Bearer ${MANAGEMENT_PASSWORD} 最终会变成真实密码。
可以用下面命令确认容器环境变量中存在该值,输出时注意不要把明文密码贴到公开位置:
docker inspect cli-proxy-api --format '{{range .Config.Env}}{{println .}}{{end}}' | grep '^MANAGEMENT_PASSWORD='
手动备份脚本
手动备份脚本放在:
/data/CLIProxyAPI/backup-usage.sh
用途是调用管理接口导出统计数据,保存到:
/data/CLIProxyAPI/usage-backup/
执行方式:
cd /data/CLIProxyAPI
./backup-usage.sh
脚本逻辑:
1. 从当前容器环境变量读取 MANAGEMENT_PASSWORD。
2. 调用 /v0/management/usage/export 导出统计数据。
3. 先写入临时文件,确认文件非空且 JSON 有效。
4. 校验通过后保存为带时间戳的备份文件。
5. 默认保留最近 10 份备份。
脚本内容:
#!/bin/bash
set -u
BASE_DIR="/data/CLIProxyAPI"
BACKUP_DIR="${BACKUP_DIR:-$BASE_DIR/usage-backup}"
KEEP_COUNT="${KEEP_COUNT:-10}"
CONTAINER_NAME="${CONTAINER_NAME:-cli-proxy-api}"
PORT="${PORT:-8317}"
BACKUP_NAME="${BACKUP_NAME:-instance1}"
TIMESTAMP="$(date +%Y%m%d_%H%M%S)"
mkdir -p "$BACKUP_DIR"
get_management_password() {
docker inspect "$CONTAINER_NAME" --format '{{range .Config.Env}}{{println .}}{{end}}' \
| awk -F= '/^MANAGEMENT_PASSWORD=/{print substr($0, index($0, "=") + 1); exit}'
}
validate_json() {
local file="$1"
python3 -m json.tool "$file" >/dev/null 2>&1
}
management_password="$(get_management_password)"
if [ -z "$management_password" ]; then
echo "[ERR] 未读取到 MANAGEMENT_PASSWORD"
exit 1
fi
output_file="$BACKUP_DIR/${BACKUP_NAME}_${TIMESTAMP}.json"
temp_file="${output_file}.tmp"
if curl -sf \
-H "Authorization: Bearer ${management_password}" \
"http://127.0.0.1:${PORT}/v0/management/usage/export" \
-o "$temp_file" \
&& [ -s "$temp_file" ] \
&& validate_json "$temp_file"; then
mv "$temp_file" "$output_file"
echo "[OK] 备份成功: $output_file"
ls -t "$BACKUP_DIR/${BACKUP_NAME}_"*.json 2>/dev/null | tail -n +$((KEEP_COUNT + 1)) | xargs -r rm -f
exit 0
fi
rm -f "$temp_file"
echo "[ERR] 备份失败"
exit 1
手动恢复脚本
恢复脚本放在:
/data/CLIProxyAPI/restore-usage.sh
执行方式:
cd /data/CLIProxyAPI
./restore-usage.sh
脚本会查找最新的统计备份文件,恢复前先检查文件是否存在、是否为空、JSON 是否有效,然后等待管理接口可访问,再调用:
/v0/management/usage/import
恢复脚本会改动当前统计数据,执行前需要确认最新备份文件就是预期恢复版本。
脚本内容:
#!/bin/bash
set -u
BASE_DIR="/data/CLIProxyAPI"
BACKUP_DIR="${BACKUP_DIR:-$BASE_DIR/usage-backup}"
CONTAINER_NAME="${CONTAINER_NAME:-cli-proxy-api}"
PORT="${PORT:-8317}"
BACKUP_NAME="${BACKUP_NAME:-instance1}"
get_management_password() {
docker inspect "$CONTAINER_NAME" --format '{{range .Config.Env}}{{println .}}{{end}}' \
| awk -F= '/^MANAGEMENT_PASSWORD=/{print substr($0, index($0, "=") + 1); exit}'
}
validate_json() {
local file="$1"
python3 -m json.tool "$file" >/dev/null 2>&1
}
wait_until_ready() {
local management_password="$1"
for i in $(seq 1 15); do
if curl -sf \
-H "Authorization: Bearer ${management_password}" \
"http://127.0.0.1:${PORT}/v0/management/usage" \
>/dev/null 2>&1; then
return 0
fi
echo "[WAIT] 等待接口就绪 $i/15"
sleep 2
done
return 1
}
latest_file="$(ls -t "$BACKUP_DIR/${BACKUP_NAME}_"*.json 2>/dev/null | head -1 || true)"
if [ -z "$latest_file" ]; then
echo "[SKIP] 未找到备份文件"
exit 0
fi
if [ ! -s "$latest_file" ]; then
echo "[ERR] 备份文件为空: $latest_file"
exit 1
fi
if ! validate_json "$latest_file"; then
echo "[ERR] 备份文件 JSON 无效: $latest_file"
exit 1
fi
management_password="$(get_management_password)"
if [ -z "$management_password" ]; then
echo "[ERR] 未读取到 MANAGEMENT_PASSWORD"
exit 1
fi
if ! wait_until_ready "$management_password"; then
echo "[ERR] 接口未就绪"
exit 1
fi
if curl -sf -X POST \
-H "Content-Type: application/json" \
-H "Authorization: Bearer ${management_password}" \
--data-binary "@$latest_file" \
"http://127.0.0.1:${PORT}/v0/management/usage/import" \
>/dev/null; then
echo "[OK] 恢复成功: $latest_file"
exit 0
fi
echo "[ERR] 恢复失败: $latest_file"
exit 1
检查命令
脚本语法检查:
cd /data/CLIProxyAPI
bash -n backup-usage.sh
bash -n restore-usage.sh
compose.yaml 配置检查:
docker compose -f compose.yaml config
执行备份并检查文件:
./backup-usage.sh
ls -lh usage-backup
python3 -m json.tool usage-backup/instance1_*.json >/dev/null
查看容器和自动更新服务:
docker ps --format 'table {{.Names}} {{.Status}} {{.Ports}}'
docker logs --tail 100 watchtower
qwen授权
配置qwen-cli进行测试

完成登录后去到 cherry-studio 中配置, 提供商类型选择 openAi

完成测试

有点牛逼, 但是太多了, 我用不过来, 仅记录一下
codex授权
登录403的问题本质上cliproxy在终端环节中运行的, 需要设置代理

设置代理后即可登录

添加模型

验证一下

开启tun模式后 就正常了, 那么这里不使用tun模式的话有什么办法呢?
iflow授权
cookie登录

因为在配置codex时不想开tun, 所以配置了proxifier 中 cliProxyApi走代理 any主机, 所以导致iflow登录页走了代理失败
通过配置cliProxyApi的规则openai走代理就可以了
chatgpt.com; *.chatgpt.com; api.openai.com; *.openai.com

iflow glm4.7 测试

使用codex 打通cpa 和 new api
1.登录cpa 通过 OAuth进行 codex登录, 点击链接完成登录,等完成后页面报错不要紧,复制链接到cpa进行认证, 自动保存认证文件

2.在配置面板 api密钥处添加密钥
3.回到new api添加渠道,api就是cpa的IP端口, 密钥是cpa的密钥

4.测试, 选择流式输出 注意:
- cpa不可以进行分组, 会将所有认证文件全部接入 new api, 然后在new api中获取模型列表进行选择
- 现有两种类型账号在cpa中,通过new api请求的话,会在cpa中进行切换模型