commit 47218488aa9dbc51cde60b808706773c908972f7 Author: donghongzhi Date: Thu Nov 5 14:10:48 2026 +0800 first commit diff --git a/NewAPI搭建与上线完整实战指南.md b/NewAPI搭建与上线完整实战指南.md new file mode 100644 index 0000000..c3879d6 --- /dev/null +++ b/NewAPI搭建与上线完整实战指南.md @@ -0,0 +1,320 @@ +# New API 专属大模型网关搭建与 HTTPS 上线全流程实战指南 + +> **实战环境记录** +> - **云服务器**:腾讯云新加坡轻量应用服务器(Ubuntu 24.04 LTS,2核 2G 内存,公网 IP:`43.156.118.130`) +> - **共存服务**:Xray Shadowsocks 代理服务(端口 `8388`,全程独立运行,互不干扰) +> - **域名提供商**:Spaceship(根域名:`trivoo.website`,网关二级子域名:`api.trivoo.website`) +> - **网关核心**:New API(官方镜像 `calciumion/new-api:latest`,Docker 容器化 + 内置 SQLite 持久化) +> - **反代与加密**:Nginx 反向代理 + Let's Encrypt 权威 SSL 证书(Certbot 自动化定时续期) + +--- + +## 目录 +- [一、全局架构与准备工作](#一全局架构与准备工作) +- [二、第一阶段:域名注册与 DNS 解析配置](#二第一阶段域名注册与-dns-解析配置) +- [三、第二阶段:云服务器防火墙安全配置](#三第二阶段云服务器防火墙安全配置) +- [四、第三阶段:New API 容器化部署](#四第三阶段new-api-容器化部署) +- [五、第四阶段:Nginx 反向代理与 SSL 证书自动化](#五第四阶段nginx-反向代理与-ssl-证书自动化) +- [六、第五阶段:New API 初始化与渠道配置](#六第五阶段new-api-初始化与渠道配置) +- [七、第六阶段:客户端接入与高频踩坑排错手册](#七第六阶段客户端接入与高频踩坑排错手册) +- [八、第七阶段:日常运维、安全加固与一键清理](#八第七阶段日常运维安全加固与一键清理) + +--- + +## 一、全局架构与准备工作 + +本方案采用**“单容器 SQLite + Nginx 本地反代 + Certbot 自动化证书”**的生产级架构: + +``` +[ 客户端 (Cline / Cherry Studio / 代码) ] + │ HTTPS (端口 443) + ▼ +[ Nginx 反向代理 (api.trivoo.website) ] ── (自动申请/更新 Let's Encrypt 证书) + │ HTTP (仅监听 127.0.0.1:3000,外部无法直连) + ▼ +[ New API 容器 (calciumion/new-api:latest) ] + │ + ┌─────────┴─────────┐ + ▼ ▼ +[ 官方 DeepSeek API ] [ 自定义第三方聚合上游 ] +``` + +### 核心设计优势: +1. **轻量省资源**:相比 PostgreSQL + Redis 的重型部署,内置 SQLite 单容器仅占几十兆内存,完美兼容 2G 内存低配服务器,与已有代理服务(如 Xray)和谐共存。 +2. **端口安全性**:New API 容器端口严格绑定在 `127.0.0.1:3000`,外部网络无法绕过 HTTPS 直接访问,防止明文直连与未授权嗅探。 +3. **流式传输优化**:Nginx 明确关闭 `proxy_buffering`,保障大模型打字机流式输出(SSE)流畅无卡顿。 + +--- + +## 二、第一阶段:域名注册与 DNS 解析配置 + +### 1. 域名选购(以 Spaceship 为例) +1. 访问 [Spaceship 官网](https://www.spaceship.com/) 并注册/登录账号; +2. 搜索低成本优质后缀(如 `.website`、`.top`、`.xyz` 等,首年特价通常仅约 6~10 元人民币); +3. 选定域名(本次实战选定 `trivoo.website`,首年仅 7.88 元含 ICANN 认证工本费); +4. 通过绑定的 **支付宝(Alipay)** 扫码付款完成购买。 +5. **重要防扣费设置**:购买完成后,在域名列表的 `Auto-renew` 列将开关拨至 **Off**,避免次年按原价自动续费。 + +### 2. 添加 DNS A 记录解析 +1. 在 Spaceship 控制台点击域名右侧的 **Advanced DNS ↗**; +2. 点击 **Add Record**(或点击下方小圆圈 `A`): + - **Type**:`A` + - **Host**:`api`(即二级子域名,完整网址为 `api.trivoo.website`) + - **Value / Target IP**:`43.156.118.130`(你的云服务器公网 IP) + - **TTL**:保持默认或选择 `30 min` / `1 min` +3. 点击 **Add / Save** 保存,等待右侧出现绿色的 `ADDED` 提示。 + +--- + +## 三、第二阶段:云服务器防火墙安全配置 + +登录 [腾讯云轻量服务器控制台](https://console.cloud.tencent.com/lighthouse) -> 点击目标实例 -> **防火墙**,确保以下规则已放行: + +| 应用类型 | 协议 | 端口 | 策略 | 作用说明 | +| :--- | :--- | :--- | :--- | :--- | +| Linux 登录 | TCP | 22 | 允许 | SSH 远程登录维护 | +| HTTP | TCP | 80 | 允许 | Certbot 申请 SSL 证书及 HTTP-01 验证 | +| HTTPS | TCP | 443 | 允许 | 安全加密 Web 访问及客户端 API 调用 | +| 自定义 | TCP | 8388 | 允许 | 已有的 Xray / Shadowsocks 梯子服务 | + +> **安全注意**:不要在公网防火墙中开放 `3000` 端口。生产环境下 3000 端口只走服务器内部回环转发,所有外网流量统一由 443 端口接入。 + +--- + +## 四、第三阶段:New API 容器化部署 + +### 1. 登录服务器并切换 root 权限 +在本地终端执行: +```bash +ssh ubuntu@43.156.118.130 +sudo -i +``` +*(必须通过 `sudo -i` 确保提示符为 `root@...:~#`,避免因普通权限导致 Permission Denied)* + +### 2. 初始化目录并生成专属随机密钥 +```bash +# 创建持久化数据与日志目录 +mkdir -p /opt/new-api/data /opt/new-api/logs +cd /opt/new-api + +# 生成 64 位密码级随机安全会话密钥 +echo "SESSION_SECRET=$(openssl rand -hex 32)" > .env +chmod 600 .env +``` + +### 3. 编写安全生产型 docker-compose.yml +```bash +cat > /opt/new-api/docker-compose.yml <<'EOF' +services: + new-api: + image: calciumion/new-api:latest + container_name: new-api + restart: unless-stopped + command: --log-dir /app/logs + + # 严格绑定回环地址,禁止公网直连 3000 + ports: + - "127.0.0.1:3000:3000" + + volumes: + - ./data:/data + - ./logs:/app/logs + + environment: + - TZ=Asia/Shanghai + - ERROR_LOG_ENABLED=true + - BATCH_UPDATE_ENABLED=true + - NODE_NAME=new-api-sg-1 + - STREAMING_TIMEOUT=300 + - "SESSION_SECRET=${SESSION_SECRET:?未设置 SESSION_SECRET,请检查 .env}" + - SESSION_COOKIE_SECURE=true + - SESSION_COOKIE_TRUSTED_URL=https://api.trivoo.website + - TRUSTED_PROXIES=127.0.0.1,172.17.0.0/16 + + # 内存保护上限(防止高并发下拖垮同机代理服务) + mem_limit: 800m +EOF +``` + +### 4. 启动容器与状态检查 +```bash +cd /opt/new-api +docker compose up -d +docker ps +``` +回显中显示 `new-api` 状态为 `Up` 且端口为 `127.0.0.1:3000->3000/tcp` 即代表容器启动成功。 + +--- + +## 五、第四阶段:Nginx 反向代理与 SSL 证书自动化 + +### 1. 安装 Nginx 与 Certbot 证书套件 +```bash +apt update && apt install -y nginx certbot python3-certbot-nginx +``` + +### 2. 写入 Nginx 站点配置 +创建反向代理配置文件 `/etc/nginx/sites-available/api.trivoo.website`: +```bash +cat > /etc/nginx/sites-available/api.trivoo.website <<'EOF' +map $http_upgrade $connection_upgrade { + default upgrade; + '' close; +} + +server { + listen 80; + server_name api.trivoo.website; + + # 允许大文件上传(如语音转录、多模态图片) + client_max_body_size 100m; + + location / { + proxy_pass http://127.0.0.1:3000; + 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; + + # WebSocket 协议支持(Realtime / Responses 升级通道) + proxy_set_header Upgrade $http_upgrade; + proxy_set_header Connection $connection_upgrade; + + # 核心:关闭缓冲以支持打字机流式响应(SSE) + proxy_buffering off; + proxy_cache off; + proxy_read_timeout 1800s; + proxy_send_timeout 1800s; + } +} +EOF +``` + +### 3. 启用站点并检查语法 +```bash +ln -sf /etc/nginx/sites-available/api.trivoo.website /etc/nginx/sites-enabled/ +nginx -t && systemctl reload nginx +``` +*(必须看到 `syntax is ok` 与 `test is successful`)* + +### 4. 一键自动签发 Let's Encrypt 证书并启用 HTTPS +```bash +certbot --nginx -d api.trivoo.website --non-interactive --agree-tos -m admin@trivoo.website --redirect +``` +执行完毕后出现: +`Congratulations! You have successfully enabled HTTPS on https://api.trivoo.website` +此时证书已自动安装,并已创建 systemd 自动续期定时器。 + +--- + +## 六、第五阶段:New API 初始化与渠道配置 + +### 1. 首次访问与系统向导 +浏览器访问:`https://api.trivoo.website` +1. **数据库检查**:自动检测出 SQLite,直接点击「下一步」; +2. **管理员账户**:设定管理员用户名和高强度密码; +3. **完成初始化**:进入控制台主界面。 + +### 2. 接入官方渠道(以 DeepSeek 官方为例) +1. 左侧菜单栏点击 **「渠道」** -> 右上角 **「创建渠道」**; +2. **类型**:选择 `DeepSeek`; +3. **API 密钥**:填入 DeepSeek 官方以 `sk-` 开头的 API Key; +4. **模型**:点击快捷操作中的 **「填入相关模型」**,框内自动出现 `deepseek-chat` 与 `deepseek-reasoner` 标签; +5. 点击最底部 **「提交」**; +6. 在渠道列表中点击该卡片右上角的 **仪表盘图标(测速)**,出现绿色延迟(如 `554ms`)代表渠道通信成功。 + +### 3. 接入第三方自定义渠道(以 `apikey.fan` 聚合服务为例) +1. 点击 **「创建渠道」** -> 类型选 **`高级自定义`**(或 OpenAI 兼容); +2. **API 地址**:填入服务商的基础网关地址(如 `https://api.apikey.fan`); +3. **API 密钥**:填入该服务商提供的密钥; +4. **模型**:手动输入该上游支持的具体模型名(如 `gpt-5.6-terra`),**按回车确认生成标签**; +5. 点击提交并点击测试图标,验证连通性。 + +### 4. 生成调用令牌(分发密钥) +1. 左侧菜单栏点击 **「常规」 -> 「API 密钥」**(或「令牌」); +2. 点击右上角 **「创建密钥」**; +3. 设定名称(如 `default-token`),额度设为无限或指定额度; +4. 提交后在列表中点击 **「复制」**,获取专属于该网关的 `sk-xxxx` 令牌。 + +--- + +## 七、第六阶段:客户端接入与高频踩坑排错手册 + +### 1. 客户端标准配置示例 + +在任何支持第三方 API 的客户端(如 Cline、NextChat、Cherry Studio、Chatbox 等)中配置: + +- **接口地址 / Base URL**:`https://api.trivoo.website/v1` +- **API Key**:填入后台生成的 `sk-xxxx` 令牌 +- **模型名称**:填入渠道中已有的有效模型(如 `deepseek-chat` 或 `gpt-5.6-terra`) + +--- + +### 2. 实战高频报错与精准排错对照 + +#### ❌ 错误 1:`404 Invalid URL (POST /v1/v1/messages)` +* **现象**:客户端报错 404,请求路径出现重复的 `/v1/v1`。 +* **原因**:部分遵循 Anthropic / Claude 协议的客户端(如某些版本的 Cline),内部会自动为地址补全 `/v1/messages`。如果你在配置的 Base URL 中包含了 `/v1`,拼接后就会变成 `/v1/v1/messages`。 +* **解决方案**:将客户端的 API 地址末尾的 `/v1` 删掉,改为 `https://api.trivoo.website`。 + +#### ❌ 错误 2:`503 No available channel for model xxx under group default` +* **现象**:客户端发起调用,返回 `model_not_found`。 +* **原因**:客户端发送的模型请求名称(例如 `gpt-5.6-terra`),在 New API 的所有可用渠道模型列表中都不存在。 +* **解决方案**: + - **方案 A(改客户端)**:将客户端的模型名称改为渠道真实支持的名字(如 `deepseek-chat`); + - **方案 B(改网关重定向)**:在 New API 对应渠道编辑页中,点击「设置模型重定向」,将外部请求的 `gpt-5.6-terra` 重定向映射到后端的 `deepseek-chat`。 + +#### ❌ 错误 3:`Permission denied` / `No such file or directory` +* **现象**:在服务器终端执行 Docker 或 Nginx 配置命令时报错。 +* **原因**:新开的 SSH 会话默认处于普通用户 `ubuntu` 权限。 +* **解决方案**:执行命令前务必先输入 `sudo -i` 切换到 `root` 账户。 + +#### ❌ 错误 4:Spaceship 登录报 `Invalid username or password` +* **现象**:明明输入了正确邮箱和密码,却无法登录 Spaceship。 +* **原因**:Spaceship 强制要求在第一栏输入当初注册时设置的 **Username(用户名,如 `Beyond`)**,不支持直接使用邮箱登录。 +* **解决方案**:在注册邮件中查找用户名,使用纯用户名登录。 + +--- + +## 八、第七阶段:日常运维、安全加固与一键清理 + +### 1. 生产环境安全加固(必做) +* **关闭公开注册**: + 进入后台 `https://api.trivoo.website` -> **「系统设置」 -> 「登录注册」** -> 将 **「允许新用户注册」彻底关闭**。 + *(防止域名暴露在公网后被爬虫扫描并注册账号白嫖接口额度)* +* **SSL 自动续期确认**: + Certbot 已经注册了 systemd 定时任务,可通过以下命令测试自动续期机制: + ```bash + certbot renew --dry-run + ``` + +### 2. 日常启停与重启 +```bash +# 暂停 New API 网关(保留所有数据,释放 CPU/内存占用) +cd /opt/new-api && docker compose stop && systemctl stop nginx + +# 重新启动 New API 网关 +cd /opt/new-api && docker compose start && systemctl start nginx + +# 查看实时运行日志 +cd /opt/new-api && docker compose logs -f --tail=100 new-api +``` + +### 3. 一键卸载与彻底清理(恢复纯净服务器) +如果后续需要腾空服务器,执行以下步骤可在 1 分钟内完全清理痕迹,且**完全不影响服务器原有的代理与 SSH 服务**: + +```bash +# 1. 停止并销毁容器及持久化目录 +cd /opt/new-api && docker compose down +rm -rf /opt/new-api + +# 2. 卸载 Nginx 站点配置 +rm -f /etc/nginx/sites-enabled/api.trivoo.website /etc/nginx/sites-available/api.trivoo.website +systemctl reload nginx + +# 3. 删除 Let's Encrypt 证书记录(可选) +certbot delete --cert-name api.trivoo.website +``` +同时登录 Spaceship 域名控制台,将 `api.trivoo.website` 的 A 记录直接点击删除即可。 diff --git a/cpa-deploy/00-需求与实现流程总览.md b/cpa-deploy/00-需求与实现流程总览.md new file mode 100644 index 0000000..630fe81 --- /dev/null +++ b/cpa-deploy/00-需求与实现流程总览.md @@ -0,0 +1,152 @@ +# 需求与实现流程总览 —— Gemini Pro 变 API 给 Claude Code 用 + +> 项目代号:CPA 上线 +> 整理日期:2026-11-04 +> 配套文件:`01-部署操作手册.md`(照着做的分步手册)、`deploy-cpa.sh`(部署脚本)、`tunnel.bat`(SSH 隧道) + +--- + +## 一、需求描述(原始诉求) + +**你的原话:** + +> 目的是想用 gemini 的 pro 账号,通过 API 的方式给 claude 调用。要在乌班图系统上搭建,不在本地电脑。 + +**翻译成大白话:** + +你有一个 Google 账号(国内账号),已经/即将激活 **Google AI Pro 订阅**(Gemini Pro)。你不满足于在网页里跟它聊天,而是要把它**变成一个标准 API 服务**,让你本地电脑上的 **Claude Code**(以及任何支持填 API 的工具)随时调用——把 Gemini Pro 当成 Claude Code 的"发动机"。 + +**约束条件:** + +| # | 约束 | 说明 | +|---|---|---| +| 1 | 部署在乌班图 | 新加坡腾讯云服务器(Ubuntu 24.04,43.156.118.130),不在本地 Windows | +| 2 | 你动手我指挥 | 所有操作你自己执行(OrcaTerm + tunnel.bat),我出手册和脚本,防止搞乱 | +| 3 | 不破坏现状 | 服务器上已在跑的服务(New API、Nginx、Xray)一个都不能动 | +| 4 | 不暴露公网 | 新增服务的端口全部只绑服务器回环地址(127.0.0.1) | + +**一个待验证的疑虑:** 国内 Google 账号能否挂进反代?——理论上 CPA 登录看的是出口 IP(新加坡),不看账号注册地;Pro 订阅的模型权限要登录后实测才算数。不行的备选方案:换渠道(AI Studio ↔ 反重力)或换账号。 + +--- + +## 二、为什么是这个方案(背景逻辑) + +### 2.1 你的账号困局 + +Gemini Pro 是**订阅制**(包月),官方 API 是**按量计费**(另一笔钱)。订阅里的额度没有官方 API 入口——这就是"反代"存在的意义:**用你的订阅账号伪装成官方客户端,硬造出一个 API 来**。 + +### 2.2 工具选型:CPA(CLIProxyAPI) + +朋友(茨米)推荐、社区最主流的"账号→API"反代,官方资料齐全: + +- 官方镜像:`eceasy/cli-proxy-api:latest`(Docker Hub) +- 支持渠道:Gemini / AI Studio / **反重力(Antigravity)** / Claude / Codex / Grok / Kimi… +- 管理面板:`http://localhost:8317/management.html`(官方 Web UI) +- 反重力渠道对 Google AI Pro(非试用)订阅开放 **Claude Sonnet/Opus (thinking)** 模型——一个 Pro 账号同时供 Gemini 和 Claude 模型,正好喂 Claude Code + +### 2.3 复用你已有的资产 + +你 10 月已经上线了 New API 网关(api.trivoo.website,Docker + Nginx + HTTPS)。CPA 不替代它,而是**作为新渠道挂进去**——所有客户端继续只认这一个域名、这一把钥匙。 + +--- + +## 三、最终架构 + +``` +┌─ 你的 Windows 电脑 ────────────────────────────────────────────┐ +│ │ +│ Claude Code / Cherry Studio / 任何 OpenAI·Anthropic 客户端 │ +└────────────────────────┬───────────────────────────────────────┘ + │ HTTPS 443(已有域名+证书,无需新开端口) + ▼ +┌─ 新加坡服务器 Ubuntu 24.04 ─────────────────────────────────────┐ +│ │ +│ Nginx 反代(已有) │ +│ │ 127.0.0.1:3000 │ +│ ▼ │ +│ New API 容器(已有)──── 第2层:网关分发、令牌、记账 │ +│ │ 容器内网 ai-net: http://cli-proxy-api:8317 │ +│ ▼ │ +│ CPA 容器(本次新增)─── 第1层:账号→API、协议转换、账号池 │ +│ │ OAuth 凭证(/opt/cpa/auths/) │ +│ ▼ │ +│ Google(Gemini 模型 + 反重力渠道的 Claude 模型) │ +│ │ +│ ※ CPA 全部端口只绑 127.0.0.1,公网不可达 │ +│ ※ 远程管理/登录走 SSH 隧道(tunnel.bat) │ +└────────────────────────────────────────────────────────────────┘ +``` + +**新增内容只有两样:** `/opt/cpa` 目录 + `cli-proxy-api` 容器。四条命令可彻底卸载。 + +--- + +## 四、实现流程(6 步) + +| 步骤 | 在哪 | 做什么 | 用什么 | ✅ 过关标准 | +|---|---|---|---|---| +| ① 开隧道 | 本地 | 双击 `tunnel.bat` 建立到服务器的加密通道 | tunnel.bat | 窗口保持开着即可 | +| ② 部署 CPA | 服务器 | 上传并执行 `deploy-cpa.sh`:建目录、生成密钥、启容器、自检 | OrcaTerm | 输出 `cli-proxy-api Up`;无钥匙 401 / 有钥匙 200;打印两把钥匙 | +| ③ 登录账号 | 本地浏览器 | 管理面板里 OAuth 登录 Google 账号(反重力/AI Studio 渠道) | 隧道 + management.html | 凭证文件出现;`/v1/models` 列表非空 | +| ④ 挂渠道 | 浏览器 | New API 后台加 Claude 类型渠道,指向 CPA | api.trivoo.website | 渠道测速出绿色延迟 | +| ⑤ 配客户端 | 本地 | Claude Code 的 settings.json(或 CCS 加供应商)指向你的网关 | 编辑器 | — | +| ⑥ 全链路验证 | 本地 | curl 打一发 + Claude Code 实际对话 | PowerShell | 返回正常文本;New API 日志可见调用 | + +> 详细操作、逐条命令、常见问题排错:见 `01-部署操作手册.md`。 + +### 两把钥匙(第②步生成,存于服务器 /opt/cpa/KEYS.txt) + +| 钥匙 | 用在哪 | +|---|---| +| MGMT_KEY | 第③步登录管理面板 | +| CPA_API_KEY(sk-cpa-开头) | 第④步 New API 渠道的密钥 | + +### Claude Code 最终配置(第⑤步) + +```json +{ + "env": { + "ANTHROPIC_AUTH_TOKEN": "sk-你的NewAPI令牌", + "ANTHROPIC_BASE_URL": "https://api.trivoo.website", + "API_TIMEOUT_MS": "600000", + "CLAUDE_CODE_ENABLE_GATEWAY_MODEL_DISCOVERY": "1" + }, + "model": "渠道里配置的模型名" +} +``` + +--- + +## 五、安全与边界设计 + +| 设计 | 说明 | +|---|---| +| 端口全回环 | CPA 的 6 个端口(8317 API/面板 + 5 个 OAuth 回调)全部 `127.0.0.1` 绑定,腾讯云防火墙**不用加任何规则** | +| 远程管理走隧道 | 管理面板只允许 localhost 访问(`allow-remote: false`),本地浏览器经 SSH 隧道进入 | +| 隔离现有服务 | 不改 new-api/nginx/xray 任何配置文件;new-api 只是"运行时接入"共享网络,一条命令可拆 | +| 凭证本地落盘 | Google OAuth 凭证存在服务器 `/opt/cpa/auths/`(权限 600),不经过任何第三方 | +| 可完整回滚 | 手册末尾"彻底卸载"四条命令恢复原样 | + +## 六、风险知情 + +| 风险 | 说明 | 对策 | +|---|---|---| +| 国内账号疑虑 | Pro 订阅的模型权限可能因账号区域受限 | 登录后实测;不行换渠道/换号 | +| 违反 Google ToS | 反代属于非官方客户端使用,理论上有账号风险 | 只挂自己的账号、不放对外服务、用量克制 | +| 上游收紧 | 反重力/CPA 属猫鼠游戏,工具可能失效(前车之鉴:workbuddy2api 2026-10-21 停维护) | 接受它可能随时需要维护;好在部署可完全卸载 | +| 合规红线 | 对公众提供未备案生成式 AI 服务违规 | 仅自用;New API 已关闭公开注册(你已做过) | + +## 七、当前状态与下一步 + +- ✅ 调研完成(反代原理/生态/选型 → 见 `..\反代研究笔记.md`) +- ✅ 部署包就绪(本目录 3 个文件) +- ⏳ **→ 你现在做:OrcaTerm 上传 `deploy-cpa.sh` → `sudo bash ~/deploy-cpa.sh` → 输出贴给 AI 检查** +- ⬜ 后续:③ 登录账号 → ④ 挂渠道 → ⑤⑥ 配置与验证 + +## 八、参考资料 + +- CPA 仓库:https://github.com/router-for-me/CLIProxyAPI +- CPA 中文文档:https://help.router-for.me/cn/ +- 反重力(Antigravity)模型可用性:https://antigravity.google/docs/models/ +- 你的前置文档:《NewAPI搭建与上线完整实战指南》(Obsidian) +- 背景研究:《反代研究笔记.md》(F:\AI\docker\) diff --git a/cpa-deploy/01-部署操作手册.md b/cpa-deploy/01-部署操作手册.md new file mode 100644 index 0000000..d93531d --- /dev/null +++ b/cpa-deploy/01-部署操作手册.md @@ -0,0 +1,174 @@ +# CPA 部署操作手册(你动手版) + +> 目标链路:`Claude Code → https://api.trivoo.website (New API) → cli-proxy-api (CPA) → 你的 Google AI Pro 账号(Gemini / 反重力 Claude 模型)` +> 环境:腾讯云新加坡 Ubuntu 24.04(43.156.118.130),New API 已在运行 +> 原则:**服务器上只新增 /opt/cpa,不动你现有的 new-api / nginx / xray** + +--- + +## 总流程(6 步) + +| 步骤 | 在哪做 | 干什么 | 大约耗时 | +|---|---|---|---| +| ① | 本地电脑 | 双击 `tunnel.bat` 开 SSH 隧道 | 10 秒 | +| ② | 本地一条命令 | 把部署脚本送进服务器执行 | 2-3 分钟 | +| ③ | 本地浏览器 | 管理面板里 OAuth 登录 Google 账号 | 3 分钟 | +| ④ | 浏览器 | New API 后台加一个渠道 | 1 分钟 | +| ⑤ | 本地 | 配 Claude Code / CCS | 2 分钟 | +| ⑥ | 本地 | 全链路验证 | 1 分钟 | + +每步都有 ✅ 检查点,过了再走下一步,不会乱。 + +--- + +## ① 开隧道(本地) + +双击 `F:\AI\docker\cpa-deploy\tunnel.bat`,出现提示后**保持窗口开着**(关掉窗口 = 隧道断开)。 + +它的作用:把你本地的 8317/8085/1455/54545/51121/11451 端口接到服务器上。 +- 8317 = 管理面板 +- 51121 等其余端口 = Google OAuth 授权时的回调端口(**必须通**,否则登录卡在最后一步) + +✅ 检查点:浏览器打开 `http://localhost:8317/management.html`,能加载出页面(此时可能还是部署前,打不开就先做第②步)。 + +> 卡住不动 = SSH 没连上,先在 PowerShell 里手动 `ssh ubuntu@43.156.118.130` 确认能登录。 + +--- + +## ② 执行部署脚本(本地 PowerShell 一条命令) + +打开 PowerShell,原样粘贴执行: + +```powershell +(Get-Content F:\AI\docker\cpa-deploy\deploy-cpa.sh) -join "`n" | ssh ubuntu@43.156.118.130 "sudo bash -s" +``` + +脚本做的事(幂等,重复跑安全):建 `/opt/cpa` → 生成随机密钥写入 config.yaml → 写 docker-compose.yml → 建 `ai-net` 网络并把 new-api 挂进来 → 启动 `cli-proxy-api` 容器 → 自检 → **打印两把钥匙**。 + +✅ 检查点(看输出): +1. `cli-proxy-api | Up ...` 且端口全是 `127.0.0.1:xxxx->xxxx`(只有回环,公网摸不到) +2. `no key (expect 401)` → HTTP 401;`with key (expect 200)` → HTTP 200 +3. 末尾打印 `MGMT_KEY` 和 `CPA_API_KEY`(sk-cpa- 开头)——**复制存好**,忘了随时在服务器上 `sudo cat /opt/cpa/KEYS.txt` + +--- + +## ③ OAuth 登录 Google 账号(本地浏览器) + +1. 确认 ① 的隧道窗口开着,浏览器访问 `http://localhost:8317/management.html` + (首次访问 CPA 会自动从 GitHub 下载面板,转几秒到十几秒属正常) +2. 连接信息:服务地址填 `http://localhost:8317`,管理密钥填 **MGMT_KEY** +3. 在面板里找「凭证 / Auth 管理」类的登录入口,选你要挂的渠道: + - **Antigravity(反重力)**:Google AI Pro 订阅的主战场——Gemini 模型 + Claude Sonnet/Opus (thinking) 都从这里出 + - **AI Studio / Gemini**:Gemini 模型的另一条渠道 +4. 点登录 → 弹出 Google 授权页 → 选中你的 Pro 账号 → 允许 + → 浏览器会跳 `localhost:51121/...`,隧道把它送回服务器 → 面板里出现凭证文件 = 成功 + +**备用方案**(面板上找不到登录入口时用命令行): + +```powershell +ssh ubuntu@43.156.118.130 +sudo docker exec -it cli-proxy-api /CLIProxyAPI --antigravity-login --no-browser +``` + +它会打印一条授权 URL,复制到本地浏览器打开授权即可(回调靠隧道)。 +查看所有支持的登录命令:`sudo docker exec -it cli-proxy-api /CLIProxyAPI --help` + +✅ 检查点(服务器上执行,看到凭证文件 + 模型列表非空): + +```powershell +ssh ubuntu@43.156.118.130 "sudo ls /opt/cpa/auths && sudo docker exec cli-proxy-api sh -c 'wget -qO- http://127.0.0.1:8317/v1/models --header \"Authorization: Bearer $(sudo grep -oE \"sk-cpa-[0-9a-f]+\" /opt/cpa/config.yaml | head -1)\" | head -c 600'" +``` + +> 国内账号疑虑:OAuth 走的是 AI Studio/反重力渠道,看的是**出口 IP(新加坡)**,不是账号注册地。如果某个模型 403/配额异常,换渠道再试或确认订阅生效。 + +--- + +## ④ New API 加渠道(浏览器后台) + +打开 `https://api.trivoo.website` → 渠道 → 创建渠道: + +| 字段 | 填什么 | +|---|---| +| 类型 | **Claude**(保 Anthropic 协议端到端,Claude Code 的 thinking/工具调用不丢) | +| 名称 | `cpa-antigravity`(随意) | +| 代理 / Base URL | `http://cli-proxy-api:8317`(容器内网直连,不走公网) | +| 密钥 | **CPA_API_KEY**(sk-cpa- 开头那把) | +| 模型 | 从上一步 ✅ 检查点输出的模型列表里抄(逐个回车成标签) | + +提交后点渠道卡片右上角**测速图标**。 + +✅ 检查点:出现绿色延迟数字 = New API → CPA → Google 全通了。 + +--- + +## ⑤ 配 Claude Code(本地) + +编辑 `C:\Users\<你>\.claude\settings.json`(用 CCS 的话就在 CCS 里加一个供应商,值一样——茨米说的"当成 codex 那样加"就是这个): + +```json +{ + "env": { + "ANTHROPIC_AUTH_TOKEN": "sk-你在NewAPI建的令牌", + "ANTHROPIC_BASE_URL": "https://api.trivoo.website", + "API_TIMEOUT_MS": "600000", + "CLAUDE_CODE_ENABLE_GATEWAY_MODEL_DISCOVERY": "1" + }, + "model": "渠道里填的某个模型名" +} +``` + +> 没有现成令牌就去 New API 后台「API 密钥」建一个(你自己的指南里写过这步)。 + +--- + +## ⑥ 全链路验证(本地 PowerShell) + +```powershell +curl.exe -s https://api.trivoo.website/v1/messages ` + -H "x-api-key: sk-你的NewAPI令牌" ` + -H "anthropic-version: 2023-06-01" ` + -H "content-type: application/json" ` + -d '{\"model\":\"渠道里的模型名\",\"max_tokens\":64,\"messages\":[{\"role\":\"user\",\"content\":\"用一句话打个招呼\"}]}' +``` + +✅ 检查点:返回 JSON 里有 `"content":[{"type":"text"...` = **全链路打通** 🎉 +然后开 Claude Code 随便聊两句,New API 后台「日志」里能看到这条调用。 + +--- + +## 日常运维速查(服务器上) + +```bash +cd /opt/cpa +docker compose logs -f --tail=50 # 看 CPA 日志 +docker compose restart # 重启 CPA +docker compose down # 停止(数据在 ./auths ./config.yaml,不丢) +sudo cat /opt/cpa/KEYS.txt # 查两把钥匙 +sudo ls /opt/cpa/auths # 看已登录的账号凭证 +``` + +**两个注意**: +1. 只有第③步(OAuth 登录)和用管理面板时才需要开隧道,平时 CPA 自己在服务器上跑,不需要 tunnel.bat +2. 如果你以后 `docker compose up -d --force-recreate` 重建了 new-api 容器,要补一句把网络接回去: + `sudo docker network connect ai-net new-api` + +## 彻底卸载(恢复原样) + +```bash +cd /opt/cpa && docker compose down +sudo docker network disconnect ai-net new-api || true +sudo docker network rm ai-net +sudo rm -rf /opt/cpa +``` + +不影响 new-api / nginx / xray / 域名证书的任何东西。 + +## 常见问题 + +| 症状 | 原因/解法 | +|---|---| +| 面板打不开 | tunnel.bat 窗口被关了;或第②步没成功,`docker ps` 看 cli-proxy-api 是否 Up | +| Google 授权后跳转的 localhost 页面打不开/连接被拒 | 隧道没转发对应回调端口(重开 tunnel.bat,它含全部 6 个端口) | +| `/v1/models` 是空的 `[]` | 账号没登录成功,看 `/opt/cpa/auths` 有没有文件,重做第③步 | +| 渠道测试 503/no available channel | 模型名没抄对:渠道里填的名字必须和 `/v1/models` 输出完全一致 | +| 某模型 429/403 | 配额或订阅问题:换渠道(AI Studio ↔ 反重力)试,确认 Pro 订阅生效中 | diff --git a/cpa-deploy/02-两天流程复盘-大白话版.md b/cpa-deploy/02-两天流程复盘-大白话版.md new file mode 100644 index 0000000..9600116 --- /dev/null +++ b/cpa-deploy/02-两天流程复盘-大白话版.md @@ -0,0 +1,271 @@ +# 两天流程复盘 · 大白话版 + +> 目的:把 2026-11-04 ~ 11-05 这两天做的事,用**不懂技术也能看懂**的方式讲清楚。 +> 读完你应该能回答:我搭了什么?每一块是干嘛的?哪些是 AI 替我做的?出问题我该看哪里? + +--- + +## 〇、先用一个比喻把整件事说清 + +把这件事想象成**"把一张只能在自家店里刷的会员卡,改造成任何 ATM 都能取钱的银行卡"**: + +| 现实世界 | 我们的系统 | +|---|---| +| 你的 Google AI Pro 会员卡 | Google 订阅账号(有额度,但只能在 Google 自己店里用) | +| **改装刷卡机** | **CPA** —— 让这张会员卡能在任何地方被"读" | +| **自家开的银行柜台** | **New API** —— 统一对外、记账、发副卡给你各个工具 | +| 银行门口的正式管道 | 你的域名 `api.trivoo.website`(HTTPS 加密) | +| 你家里的水龙头 | Codex / Claude Code(只会用标准接口) | +| 临时挖的运钞暗道 | `tunnel.bat`(SSH 隧道,只在需要时打开) | + +一句话总结:**你花钱买的 Google 订阅,被改造成了"标准 API",现在你的编程工具能直接白嫖它。** + +--- + +## 一、起点 vs 终点 + +### 起点(11月4日之前) +- ✅ 有一台腾讯云新加坡服务器(Ubuntu 24.04,43.156.118.130) +- ✅ 上面已经跑着 New API 网关(域名 `api.trivoo.website`,能调 DeepSeek 等) +- ❌ 有一个 Google AI Pro 订阅,**但只能在网页上用,编程工具调不了** + +### 终点(11月5日之后) +- ✅ 同一个域名、同一把钥匙,**现在多了 Google 的 Gemini / Claude 模型可用** +- ✅ Codex、Claude Code 换一下配置就能用上 +- ✅ 全部跑在你自己的服务器上,数据不经过任何第三方 + +--- + +## 二、7 个关键名词,一句话一个 + +| 名词 | 一句话解释 | 生活比喻 | +|---|---|---| +| **反代** | 用你的账号凭证,伪装成官方客户端去调上游,对外输出标准 API | 改装刷卡机 | +| **CPA**(CLIProxyAPI) | 一个开源软件,专门干上面这件事(支持 Google/Claude/Codex/Grok/Kimi/Meta 等) | 那台改装机的品牌型号 | +| **New API** | 一个网关软件:统一入口、发钥匙、记账、看日志 | 银行柜台 | +| **Docker / 容器** | 把软件连它的环境一起打包成"盒子",跑起来互不干扰 | 一个个集装箱 | +| **SSH 隧道** | 在你电脑和服务器之间临时架一条加密通道,让本地能访问服务器内部服务 | 运钞暗道 | +| **OAuth** | "用 Google 账号授权",**不交出密码**,只给一张有期限的通行证 | 刷脸进店,不给家里钥匙 | +| **API Key / 令牌** | 一串密码字符串,证明"你有权调用" | 银行卡 + 密码 | + +--- + +## 三、三把钥匙别搞混(最容易糊的地方) + +你的系统里现在有**三把不同的钥匙**,用途完全不同: + +| 钥匙 | 长什么样 | 谁用它 | 用来干什么 | +|---|---|---|---| +| **① New API 令牌** | `sk-xxxxxx` | 你的 Codex / ccswitch | 客户端 → 连你的银行柜台(New API) | +| **② CPA_API_KEY** | `sk-cpa-xxxxxx` | New API | 银行柜台 → 连改装机(CPA) | +| **③ MGMT_KEY** | 一串随机字符 | 你本人(浏览器) | 登录 CPA 管理面板,改配置、看凭证 | + +**打款路径就是**: +``` +Codex(拿①)→ New API(拿②)→ CPA → Google(用 OAuth 通行证) +``` + +① 和 ② 都存在服务器上(`/opt/cpa/KEYS.txt` 里是 ② 和 ③),① 在 New API 后台建。 + +--- + +## 四、这两天实际发生了什么(时间线) + +### 【第 1 天 · 11月4日】搞清楚 + 做准备 + +| 时间 | 发生了什么 | +|---|---| +| 上午 | 你贴了和茨米的聊天记录,我帮你按时间重排整理 | +| 上午 | 明确"反代"是什么、和 CPA 什么关系、三层生态(账号层 / 网关层 / 中转站层) | +| 上午 | 你问"反代和 CPA 是不是同一个东西"——结论:反代是**概念**,CPA 是**软件** | +| 中午 | 读了你自己的《NewAPI 实战指南》,把你的现状对号入座 | +| 下午 | **明确目标**:Gemini Pro 账号 → API → 给 Claude Code 用,装在乌班图(新加坡服务器) | +| 下午 | 我先做了一版"我远程全自动部署"方案,**你拒绝了权限**(很对,服务器是你的) | +| 傍晚 | 改成"我出脚本、你动手"模式 | +| 傍晚 | 查官方文档,确认 CPA 的镜像、端口、面板地址、登录命令 | +| 晚上 | **产出部署包**:`deploy-cpa.sh`(部署脚本)+ `tunnel.bat`(隧道)+ `01-部署操作手册.md` | + +### 【第 2 天 · 11月5日】部署 + 踩坑 + 跑通 + +| 时间 | 发生了什么 | 结果 | +|---|---|---| +| 08:31 | 你要操作步骤,我给了完整 6 步 | — | +| 08:47 | 你跑完脚本,打开面板 | ❌ 报 403 | +| 08:50 | 我诊断:`allow-remote: false` 把管理 API 关了 | 给你两条命令改掉 | +| 09:10 | 改完重启,面板登录成功 | ✅ | +| 09:26 | OAuth 登录 Google 账号(Antigravity 渠道) | ✅ 凭证落盘,模型列表出来 | +| 10:12 | New API 加渠道、拉模型、测速 | ✅ 全链路通 | +| 10:52 | 你确认跑通,我做了复盘对比 | ✅ | +| 11:05 | 你想试 Meta Muse | 查文档确认支持 | +| 11:19 | 走到 Meta 绑卡页面:**要按 token 付费,无免费层** | ❌ 放弃 | +| 11:41 | 检查 Meta 账号有没有社交资产(担心封号连坐) | 干净,但已无必要 | + +--- + +## 五、"AI 帮你做的" 到底做了什么(消除黑箱感) + +你说"有些都是 AI 帮我实现"——下面把它们全部拆开,白纸黑字,随时可查: + +### 1️⃣ `deploy-cpa.sh`(部署脚本)做了 7 件事 + +| 段落 | 干了什么 | +|---|---| +| [1] 预检 | 确认是 root 权限、列出当前容器 | +| [2] 建目录 | 新建 `/opt/cpa/`(含 auths=存凭证 / logs=日志 / plugins=插件) | +| [3] 生成配置 | 用 `openssl rand` 随机生成两把钥匙,写进 `config.yaml` + `KEYS.txt` | +| [4] 写 compose | 定义"用哪个镜像、开哪些端口、挂哪些目录" | +| [5] 建网络 | 建 `ai-net` 内网,把已有的 new-api 容器拉进来 | +| [6] 启动 | `docker compose up -d` 把容器跑起来 | +| [7] 自检 | 不带钥匙应得 401、带钥匙应得 200、测容器互通、打印钥匙 | + +**它没做的事(很重要)**:没碰你的 new-api 文件、没碰 nginx、没碰 Xray、没在防火墙开任何端口。 + +### 2️⃣ `tunnel.bat`(隧道)就是一条命令 + +```bat +ssh -N -L 8317:127.0.0.1:8317 ... ubuntu@43.156.118.130 +``` + +拆开看: +- `ssh` = 连到服务器 +- `-N` = 只做端口转发,不执行远程命令 +- `-L 8317:127.0.0.1:8317` = "把我本地的 8317 端口,接到服务器的 8317 端口" + +**为什么要它**:CPA 的面板和授权回调端口**只对服务器自己开放**(安全设计),你本地浏览器想访问,就得有这么一条通道。就像银行金库不对大街开门,但给你留了条内部通道。 + +### 3️⃣ 那两条排障命令 + +```bash +sed -i 's/allow-remote: false/allow-remote: true/' /opt/cpa/config.yaml # 改一个开关 +docker compose restart # 重启生效 +``` + +为什么必须改:原本关掉远程管理是出于安全,但请求经过 Docker 内部转发后,CPA 把来源 IP 看成内网地址,误判为"远程访问"而拦截。因为端口本来就绑死 `127.0.0.1`(公网根本进不来),所以打开这个开关**不降低安全性**。 + +### 4️⃣ New API 里点的那几下 + +你在界面里做的操作,本质是往数据库里写了一条记录: +> "有一个叫 `CPA-Gemini-OpenAI` 的上游,地址是 `http://cli-proxy-api:8317`,钥匙是 `sk-cpa-xxx`,它支持这些模型:gemini-3-flash…" + +以后任何客户端拿着 New API 的令牌来,New API 就按这条记录转发给 CPA。 + +--- + +## 六、现在的系统长什么样(数据怎么流) + +``` +【你的 Windows 电脑】 + Codex / Claude Code / ccswitch + │ ① 用 New API 令牌(sk-xxx) + │ ② HTTPS 加密 + ▼ +【腾讯云新加坡服务器 · Ubuntu 24.04】 + ┌─────────────────────────────────────────┐ + │ Nginx(已有):管 HTTPS 证书、转发 │ + │ ▼ │ + │ New API 容器(已有):发钥匙、记账、看日志 │ + │ │ 用 CPA_API_KEY(sk-cpa-xxx) │ + │ │ 走 Docker 内部网络 ai-net │ + │ ▼ │ + │ CPA 容器(新装):账号→API 转换 │ + │ │ OAuth 通行证(存在 auths/ 里) │ + └────────┼────────────────────────────────┘ + ▼ + Google(Gemini 模型 + 反重力渠道的 Claude 模型) +``` + +**一次请求的完整旅程**(跟着数据走一遍): + +1. 你在 Codex 里输入一句话 +2. Codex 拿 New API 令牌,把请求发到 `https://api.trivoo.website` +3. Nginx 解密 HTTPS,转给 New API 容器 +4. New API 查令牌 → 合法 → 查模型 → 找到 `CPA-Gemini-OpenAI` 渠道 +5. New API 拿 CPA_API_KEY,通过内网发给 CPA +6. CPA 从 `auths/` 里挑一个 Google 凭证,把 OpenAI 格式的请求翻译成 Google 能懂的格式 +7. Google 返回结果,CPA 再翻译回标准格式,原路返回 +8. Codex 显示回答;同时 New API 记了一笔账(模型、token、耗时) + +--- + +## 七、为什么这么设计(每个决定的理由) + +| 决定 | 理由 | +|---|---| +| 为什么不装在你本地电脑 | ① Google 对中国大陆 IP 有风控 ② 你的电脑不会 24 小时开机 ③ 服务器出口是新加坡,天然绕开限制 | +| 为什么端口只绑 `127.0.0.1` | 让服务"只有服务器自己能用",公网谁都摸不到,连防火墙规则都不用改 | +| 为什么用隧道而不是把面板开放到公网 | 面板能改配置、看凭证,等于系统总闸,绝不能暴露 | +| 为什么还要过一层 New API | 统一入口(所有工具记一个地址)、记账、看日志、方便以后加别的上游 | +| 为什么不直连 CPA 就完事 | 直连也行(少一跳、延迟低),但需要一直开着隧道;两条路可以并存 | +| 为什么要两把钥匙 | 分离权限:管理钥匙只给你本人,API 钥匙只给程序,泄一个不牵连另一个 | + +--- + +## 八、日常你自己能做的事(速查) + +在 OrcaTerm 里(或 SSH 上去): + +```bash +# 看 CPA 活着没 +sudo docker ps | grep cli-proxy-api + +# 看 CPA 日志(实时) +cd /opt/cpa && sudo docker compose logs -f --tail=50 + +# 重启 CPA(改完配置必须重启) +cd /opt/cpa && sudo docker compose restart + +# 看两把钥匙 +sudo cat /opt/cpa/KEYS.txt + +# 看已登录的账号凭证 +sudo ls /opt/cpa/auths + +# 看 CPA 当前提供哪些模型 +curl -s http://127.0.0.1:8317/v1/models -H "Authorization: Bearer $(sudo grep -oE 'sk-cpa-[0-9a-f]+' /opt/cpa/config.yaml | head -1)" +``` + +**铁律两条**: +1. 改了 `/opt/cpa/config.yaml` → 一定要 `docker compose restart` +2. 如果哪天重建了 new-api 容器 → 补一句 `sudo docker network connect ai-net new-api` + +--- + +## 九、出问题看哪里(排错路线图) + +| 现象 | 先看这里 | +|---|---| +| Codex 报 404 | 模型名对不对(去 New API 渠道里重新拉列表) | +| 报 401 | 令牌对不对(Codex 里的 sk-xxx / New API 里的 sk-cpa-xxx) | +| 报 429 | Google 限流,等几分钟,不是坏了 | +| 面板打不开 | tunnel.bat 窗口是不是关了 | +| New API 渠道测试失败 | `docker logs --tail=50 cli-proxy-api` 看 CPA 说什么 | +| 模型列表是空的 | `sudo ls /opt/cpa/auths` 有没有凭证,没有就重新 OAuth 登录 | +| 全部都不对 | 从上往下查:容器活着吗 → 面板能进吗 → 凭证在吗 → 渠道测速过吗 | + +--- + +## 十、术语中英对照(以后搜索用) + +| 中文 | 英文 | 说明 | +|---|---|---| +| 反代 | reverse proxy | 转发/转换请求的中间服务 | +| 上游 | upstream | 最终提供模型的一方(这里是 Google) | +| 渠道 | channel | New API 里的一条上游配置 | +| 凭证 / 认证文件 | auth / auth file | OAuth 登录后存下来的通行证 | +| 令牌 | token / API key | 调用凭证 | +| 管理密钥 | management key | 管理面板登录用 | +| 限流 | rate limit / 429 | 请求太快的临时拒绝 | +| 容器 | container | Docker 里的运行单元 | + +--- + +## 十一、最后一句话总结 + +**你这两天做的事情,本质是给自己的 AI 工具链加了一条"免费高速通道"**: + +- 过去:Google 订阅只能在网页用 → 浪费 +- 现在:同一个订阅变身 API → Codex / Claude Code 都能用 +- 全程:数据在你自己的服务器上跑,不经过任何第三方中转 +- 成本:只花服务器钱(本来就在付),模型额度用的是你已付费的订阅 + +**唯一的代价**:这是一条"非官方"路径(属于灰色地带),上游随时可能调整。所以随时记住——**这套东西是可拆的、可放弃的**,不会绑架你。 diff --git a/cpa-deploy/deploy-cpa.sh b/cpa-deploy/deploy-cpa.sh new file mode 100644 index 0000000..3ab69c2 --- /dev/null +++ b/cpa-deploy/deploy-cpa.sh @@ -0,0 +1,129 @@ +#!/usr/bin/env bash +# ========================================================== +# CPA (CLIProxyAPI) one-click deploy script +# Target : Tencent SG server ubuntu@43.156.118.130 +# Effect : create /opt/cpa + start cli-proxy-api container +# existing new-api / nginx / xray are NOT modified +# (only a runtime docker network attach for new-api) +# Idempotent: safe to run multiple times. +# Run as root: sudo bash deploy-cpa.sh +# ========================================================== +set -euo pipefail + +step() { echo ""; echo "========== [$1] $2 =========="; } + +step 1 "Pre-check" +[ "$(id -u)" -eq 0 ] || { echo "ERROR: run as root (sudo bash)"; exit 1; } +docker ps --format ' {{.Names}} | {{.Status}}' + +step 2 "Create /opt/cpa" +mkdir -p /opt/cpa/auths /opt/cpa/logs /opt/cpa/plugins +cd /opt/cpa + +step 3 "Generate config.yaml (keep existing if present)" +if [ -f config.yaml ]; then + echo " config.yaml exists, keep it" +else + CPA_API_KEY="sk-cpa-$(openssl rand -hex 16)" + MGMT_KEY="$(openssl rand -hex 16)" + cat > config.yaml < KEYS.txt < docker-compose.yml <<'EOF' +services: + cli-proxy-api: + image: eceasy/cli-proxy-api:latest + container_name: cli-proxy-api + restart: unless-stopped + ports: + # all bound to server loopback only -> NOT reachable from public internet + # 8317 = API + management panel, others = OAuth callback ports per provider + - "127.0.0.1:8317:8317" + - "127.0.0.1:8085:8085" + - "127.0.0.1:1455:1455" + - "127.0.0.1:54545:54545" + - "127.0.0.1:51121:51121" # Antigravity OAuth callback + - "127.0.0.1:11451:11451" + volumes: + - ./config.yaml:/CLIProxyAPI/config.yaml + - ./auths:/root/.cli-proxy-api + - ./logs:/CLIProxyAPI/logs + - ./plugins:/CLIProxyAPI/plugins + networks: + - ai-net + +networks: + ai-net: + external: true +EOF +echo " done" + +step 5 "Docker network ai-net (shared with new-api)" +docker network inspect ai-net >/dev/null 2>&1 || docker network create ai-net +docker network connect ai-net new-api 2>/dev/null && echo " new-api joined ai-net" || echo " new-api already in ai-net (or not running)" + +step 6 "Start container" +docker compose up -d +sleep 6 +docker ps --filter name=cli-proxy-api --format ' {{.Names}} | {{.Status}} | {{.Ports}}' + +step 7 "Verify" +CPA_API_KEY=$(grep -oE 'sk-cpa-[0-9a-f]+' config.yaml | head -1 || true) +[ -n "$CPA_API_KEY" ] || { echo "ERROR: api key not found in config.yaml"; exit 1; } +echo "-- no key (expect 401):" +curl -s -o /dev/null -w ' HTTP %{http_code}\n' http://127.0.0.1:8317/v1/models +echo "-- with key (expect 200; model list may be empty before OAuth login):" +curl -s -w '\n HTTP %{http_code}\n' http://127.0.0.1:8317/v1/models -H "Authorization: Bearer ${CPA_API_KEY}" | head -c 400 +echo "" +echo "-- new-api container -> cli-proxy-api connectivity:" +if docker exec new-api sh -c 'command -v curl' >/dev/null 2>&1; then + docker exec new-api sh -c "curl -s -o /dev/null -w '%{http_code}' --max-time 5 http://cli-proxy-api:8317/v1/models" | sed 's/^/ HTTP /' + echo " (any HTTP code = network OK)" +elif docker exec new-api sh -c 'command -v wget' >/dev/null 2>&1; then + docker exec new-api sh -c "wget -S -q -O /dev/null http://cli-proxy-api:8317/v1/models 2>&1 | head -1" | sed 's/^/ /' +else + echo " no curl/wget inside new-api, skip (use New API channel test later)" +fi + +echo "" +echo "==========================================================" +echo " DEPLOY DONE. Secrets (also saved at /opt/cpa/KEYS.txt):" +echo "==========================================================" +cat KEYS.txt +echo "" +echo "Next: open tunnel.bat locally, then visit" +echo " http://localhost:8317/management.html" diff --git a/cpa-deploy/tunnel.bat b/cpa-deploy/tunnel.bat new file mode 100644 index 0000000..f2f12b0 --- /dev/null +++ b/cpa-deploy/tunnel.bat @@ -0,0 +1,21 @@ +@echo off +title CPA Tunnel - keep this window OPEN +echo ============================================================ +echo SSH tunnel: local ports ^(8317 8085 1455 54545 51121 11451^) +echo ---------------^> Singapore server 127.0.0.1 +echo. +echo Panel URL : http://localhost:8317/management.html +echo Note : window must STAY OPEN while using panel / OAuth +echo Disconnect : just close this window +echo ============================================================ +ssh -N ^ + -L 8317:127.0.0.1:8317 ^ + -L 8085:127.0.0.1:8085 ^ + -L 1455:127.0.0.1:1455 ^ + -L 54545:127.0.0.1:54545 ^ + -L 51121:127.0.0.1:51121 ^ + -L 11451:127.0.0.1:11451 ^ + ubuntu@43.156.118.130 +echo. +echo Tunnel closed. +pause diff --git a/install-claude-deepseek.sh b/install-claude-deepseek.sh new file mode 100644 index 0000000..e3b97c2 --- /dev/null +++ b/install-claude-deepseek.sh @@ -0,0 +1,58 @@ +#!/usr/bin/env bash +# ============================================ +# Claude Code + DeepSeek API 一键安装脚本 +# 适用: Ubuntu 20.04 / 22.04 / 24.04 +# 用法: 把本文件拷到 Ubuntu 家目录, 执行: +# chmod +x install-claude-deepseek.sh && ./install-claude-deepseek.sh +# ============================================ + +set -e + +echo "==> [1/4] 安装基础依赖 (会要求输入 sudo 密码)" +sudo apt update +sudo apt install -y curl git ca-certificates + +echo "==> [2/4] 安装 Node.js 20 (通过 nvm)" +export NVM_NODEJS_ORG_MIRROR="https://npmmirror.com/mirrors/node" # 国内加速, 海外网络可删除此行 +if [ ! -s "$HOME/.nvm/nvm.sh" ]; then + curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/master/install.sh | bash +fi +export NVM_DIR="$HOME/.nvm" +# shellcheck disable=SC1091 +. "$NVM_DIR/nvm.sh" +nvm install 20 +nvm alias default 20 +echo "Node 版本: $(node -v)" + +echo "==> [3/4] 安装 Claude Code" +npm install -g @anthropic-ai/claude-code +claude --version + +echo "==> [4/4] 配置 DeepSeek API" +read -rp "粘贴你的 DeepSeek API Key (sk- 开头, 回车确认): " DSEEK_KEY +if [ -z "$DSEEK_KEY" ]; then + echo "未输入 Key, 请稍后手动编辑 ~/.bashrc 添加配置"; exit 1 +fi + +# 先清除旧配置行, 避免重复写入 (可重复运行本脚本) +sed -i '/ANTHROPIC_BASE_URL/d;/ANTHROPIC_AUTH_TOKEN/d;/ANTHROPIC_MODEL/d;/ANTHROPIC_SMALL_FAST_MODEL/d' ~/.bashrc +cat >> ~/.bashrc << EOF +export ANTHROPIC_BASE_URL=https://api.deepseek.com/anthropic +export ANTHROPIC_AUTH_TOKEN=$DSEEK_KEY +export ANTHROPIC_MODEL=deepseek-chat +export ANTHROPIC_SMALL_FAST_MODEL=deepseek-chat +EOF + +# 当前终端立即生效 +export ANTHROPIC_BASE_URL=https://api.deepseek.com/anthropic +export ANTHROPIC_AUTH_TOKEN="$DSEEK_KEY" +export ANTHROPIC_MODEL=deepseek-chat +export ANTHROPIC_SMALL_FAST_MODEL=deepseek-chat + +echo "" +echo "=========================================" +echo "✅ 安装完成! 接下来:" +echo " 1. 重开一个终端 (或执行: source ~/.bashrc)" +echo " 2. 进入项目目录, 运行: claude" +echo " 3. 在 claude 里输入 /model 确认显示 deepseek-chat" +echo "=========================================" diff --git a/new-api/docker-compose.yml b/new-api/docker-compose.yml new file mode 100644 index 0000000..67489a8 --- /dev/null +++ b/new-api/docker-compose.yml @@ -0,0 +1,58 @@ +# ============================================================ +# New API —— 腾讯云新加坡轻量服务器 · 同机部署版(SQLite 单容器) +# +# 服务器:43.156.118.130 / Ubuntu 24.04 LTS / 2核2G / 40G +# 共存服务:Xray + Shadowsocks(端口 8388,互不干扰,勿动) +# +# 部署目录:/opt/new-api +# /opt/new-api/docker-compose.yml ← 本文件 +# /opt/new-api/.env ← 存放 SESSION_SECRET(权限 600) +# /opt/new-api/data/ ← SQLite 数据库 + 上传文件 +# /opt/new-api/logs/ ← 应用日志 +# +# 启动:docker compose up -d +# 日志:docker compose logs -f new-api +# ============================================================ + +services: + new-api: + image: calciumion/new-api:latest + container_name: new-api + restart: unless-stopped + command: --log-dir /app/logs + + # 只绑回环地址:外部只能经 Nginx(443) 访问, + # 无法绕过 HTTPS 直连 3000 端口(Docker 会绕过 ufw,这一点很关键) + ports: + - "127.0.0.1:3000:3000" + + volumes: + - ./data:/data + - ./logs:/app/logs + + environment: + - TZ=Asia/Shanghai + - ERROR_LOG_ENABLED=true + - BATCH_UPDATE_ENABLED=true + - NODE_NAME=new-api-sg-1 + - STREAMING_TIMEOUT=300 + + # ---------- 会话与安全 ---------- + # SESSION_SECRET 从同目录 .env 读取,值由 `openssl rand -hex 32` 生成。 + # 缺失时 Compose 会直接报错停下,不会用空密钥静默启动。 + - "SESSION_SECRET=${SESSION_SECRET:?未设置 SESSION_SECRET,请检查 /opt/new-api/.env}" + - SESSION_COOKIE_SECURE=true # 必须 true,配合 HTTPS + - SESSION_COOKIE_TRUSTED_URL=https://api.trivoo.online + + # Nginx 跑在宿主机,容器看到的是 Docker 网桥网关地址 + - TRUSTED_PROXIES=127.0.0.1,172.17.0.0/16 + + # 保护梯子:给容器设内存上限,防止 New API 吃光 2GB 把 Xray 一起拖垮 + mem_limit: 800m + + healthcheck: + test: ["CMD-SHELL", 'wget -qO- http://localhost:3000/api/status | grep -qE "success[[:space:]]*:[[:space:]]*true" || exit 1'] + interval: 30s + timeout: 10s + retries: 3 + start_period: 40s diff --git a/new-api/nginx-api.trivoo.online.conf b/new-api/nginx-api.trivoo.online.conf new file mode 100644 index 0000000..c35e844 --- /dev/null +++ b/new-api/nginx-api.trivoo.online.conf @@ -0,0 +1,51 @@ +# ============================================================ +# Nginx 站点配置 —— api.trivoo.online 反向代理到 New API +# +# 目标路径:/etc/nginx/sites-available/api.trivoo.online +# 启用:ln -s /etc/nginx/sites-available/api.trivoo.online \ +# /etc/nginx/sites-enabled/ +# nginx -t && systemctl reload nginx +# +# 先以 HTTP 建站跑通,再执行 sudo certbot --nginx +# certbot 会自动把本文件改写成含 443 + 跳转的版本 +# ============================================================ + +map $http_upgrade $connection_upgrade { + default upgrade; + '' close; +} + +server { + listen 80; + listen [::]:80; + server_name api.trivoo.online; + + # 音频转录 / 图片编辑等大文件上传(Nginx 默认仅 1m,会 413) + client_max_body_size 100m; + + location / { + proxy_pass http://127.0.0.1:3000; + 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; + + # WebSocket —— /v1/realtime 与 /v1/responses 需要 + proxy_set_header Upgrade $http_upgrade; + proxy_set_header Connection $connection_upgrade; + + # 流式响应(SSE)必须关闭缓冲,否则会被攒着一次性吐出 + proxy_buffering off; + proxy_cache off; + proxy_request_buffering off; + + # 非流式请求要等上游生成完才返回响应头,超时给足 + proxy_read_timeout 1800s; + proxy_send_timeout 1800s; + send_timeout 1800s; + + chunked_transfer_encoding on; + } +} diff --git a/反代研究笔记.md b/反代研究笔记.md new file mode 100644 index 0000000..8ddeea9 --- /dev/null +++ b/反代研究笔记.md @@ -0,0 +1,204 @@ +# AI API 反代(反向代理)研究笔记 + +> 整理日期:2026-11-04 +> 资料来源:CLIProxyAPI / new-api / sub2api / one-api / workbuddy2api-panel 官方 README(一手抓取) +> 目标:搞清楚"反代"到底是什么、CPA / new-api / sub2api / workbuddy2api 各是什么角色、"20x 这类中转站"的真相 + +--- + +## 0. 一句话理解 + +**反代 = 自己跑一个程序,拿着你"网页版/订阅版账号"的登录凭证,伪装成官方客户端去调上游接口,对外暴露成一个标准 OpenAI 兼容 API。** + +客户端(Cherry Studio、ChatBox、Claude Code……)只认标准 API,根本不知道背后是白嫖的网页/订阅账号。 + +--- + +## 1. 先分清两种"反代" + +| | 传统反代(Nginx/Caddy) | AI 圈说的反代 | +|---|---|---| +| 干什么 | 转发 HTTP 请求、隐藏源站、负载均衡 | **把账号变成 API**(协议转换 + 账号池) | +| 谁在用 | 运维 | 白嫖党 / 中转站站长 | +| 难点 | 配置 | 逆向上游协议 + 对抗风控 | + +底层都是"代理转发",但 AI 圈反代的核心价值是**协议转换**:上游根本没有开放 API(或 API 按 token 收钱),反代硬是用你的网页/订阅账号造出一个 API 来。 + +--- + +## 2. 动机:为什么要反代 + +- **Gemini**:网页版 / AI Studio 免费,官方 API 按 token 计费 → 账号反代 = 免费用 +- **Claude / GPT 订阅**:Claude Pro、ChatGPT Plus 包月,API 另收费 → 订阅反代成 API,包月费摊进 API 调用 +- **CodeBuddy(WorkBuddy)**:只有客户端、没有开放 API → workbuddy2api 硬造一个 +- **统一格式**:背后无论哪家,客户端只写一套 OpenAI 格式 + +--- + +## 3. 原理拆解:一次请求的完整旅程 + +以 CPA(CLIProxyAPI)+ Gemini 为例: + +``` +你的电脑 +┌──────────────────────────────────────────────────────┐ +│ 客户端 (Cherry Studio 等) │ +│ │ ① POST /v1/chat/completions │ +│ │ Authorization: Bearer sk-你自己设的key │ +│ ▼ │ +│ 反代网关 (CPA, 本地 127.0.0.1:8317) │ +│ ② 验 key → ③ 账号池选号 → ④ 协议转换 │ +│ │ ⑤ 用该账号的 OAuth token,伪装成 Gemini CLI │ +└────┼─────────────────────────────────────────────────┘ + ▼ (出站走代理 / 外国 IP) + Google 内部接口 + │ ⑥ SSE 流式返回 + ▼ + 网关把流转成 OpenAI 格式 → 客户端收到标准响应 +``` + +四个关键部件: + +1. **凭证(auths)**:OAuth 登录拿到的 accessToken / refreshToken,存本地文件(`auths/*.json`),程序自动刷新。这就是"你的账号"本体。 +2. **协议转换**:OpenAI `chat/completions` ↔ 上游私有格式(Gemini internal、Claude Messages、CodeBuddy SSE……)双向翻译,流式 SSE 逐帧转换。 +3. **账号池治理**(工程量最大的部分): + - 轮询 / 加权选号(快过期额度优先消耗) + - 429 限流 → 软冷却 + 指数退避;402 余额耗尽 → 硬冷却到次日 + - 熔断、会话粘性(同一会话固定同号,保证多轮上下文不跳号) +4. **自签发 key**:网关对外发自己的 `sk-xxx`,客户端拿它调用,真实凭证永远不离开你的机器。 + +--- + +## 4. 为什么必须外国 IP + +- Google / OpenAI / Anthropic 对中国大陆 IP 有地区限制或风控,**OAuth 登录这一步就过不去** +- 即使登录成功,国内 IP 直连调用风控打分高 → 容易封号 +- 所以两条路:本地部署 + 网关出站挂梯子;或直接部署在国外服务器 + +--- + +## 5. 生态地图:三层结构 + +``` +第 1 层:账号 → API(协议转换层) + CLIProxyAPI、sub2api、workbuddy2api + 输入:OAuth 账号 / 订阅 / API key + 输出:OpenAI 兼容 API + │ + ▼ +第 2 层:网关 / 分发(管理层) + one-api、new-api + 输入:各种"渠道"(官方 key、反代端点、中转站 key) + 输出:统一 API + 用户 / 额度 / 计费 / 负载均衡 + │ + ▼ +第 3 层:商业中转站(别人替你搭好的第 1+2 层) + PackyCode、APIKEY.FUN……(CPA README 赞助商列表一大排) + 直接卖 key 给你 —— 之前用的 20x 就是这类 +``` + +**20x 的真相**:站长在自己服务器上跑账号池(批量注册/收购的账号)+ 网关,把白嫖额度包装成 key 卖给你。所以价格能压到官方一折以下——因为上游根本不是官方 API。这也解释了朋友那句"不然哪里有那么多 api 可以用"。 + +典型自建组合:**CPA(白嫖账号)→ new-api(统一分发、记用量)→ 各客户端** + +同类思路的其他出口:MCP(chat-on-steroids、MCPod 把网页版 GPT 接成 MCP 工具)——同一套逆向,换个协议出口而已。 + +--- + +## 6. 五个工具横评 + +| 工具 | 定位 | 吃什么账号 | 吐什么 | 部署 | 状态 | +|---|---|---|---|---|---| +| **CLIProxyAPI (CPA)** | 账号→API | Gemini / Codex / Claude / Grok / Kimi / Meta 等的 OAuth 或 key | OpenAI / Claude / Gemini / Codex / Grok 全兼容 | 单文件 / Docker / **桌面版 EasyCLIProxyAPI** | ✅ 活跃,中文文档 help.router-for.me | +| **sub2api** | 账号→API + 计费分发 | Claude / Codex / Grok / Antigravity 等订阅号 | OpenAI / Anthropic 兼容 + 用户/额度/支付系统 | Docker Compose(Go + Vue + PG + Redis) | ✅ 活跃,README 顶部明确警告 ToS 风险 | +| **workbuddy2api-panel** | 账号→API | 腾讯 CodeBuddy / WorkBuddy | OpenAI 兼容 | Docker / Windows 单文件 exe | ⚠️ **2026-10-21 已停止维护** | +| **one-api** | 网关分发 | 各种官方 API key 渠道 | OpenAI 格式统一出口 | Docker,初始 root/123456 | ✅ 老牌"祖师爷"(MIT) | +| **new-api** | 网关分发 | 渠道(可挂反代端点/中转站 key) | OpenAI / Claude / Gemini + 用户/计费/插件市场 | Docker 一条命令起 | ✅ 活跃(one-api 二开,功能更多) | + +选型直觉: + +- 只想**用自己账号白嫖 Gemini/Claude** → CPA(新手直接上桌面版) +- 想**管一堆渠道、分发给团队** → new-api +- 想**搞订阅账号池运营**(站长向)→ sub2api +- workbuddy2api → 别再投入时间(见下节) + +--- + +## 7. 重要情报:workbuddy2api 已死 + +朋友 10/17 还在推荐它,但 **10/21 官方宣布停止维护**,README 给出三个原因: + +1. **上游已开始禁用反代**——WorkBuddy 对非官方客户端的识别与拦截正在收紧(通道校验、账号限制),反代通道存活周期不可控 +2. 个人精力有限,无力长期跟进协议变化与风控对抗 +3. 非法转卖泛滥(批量小号、卡密售卖),与项目初衷相悖 + +这件事本身就是最好的教材:**反代是猫鼠游戏,上游一收紧,工具随时死**。sub2api 的 README 同样把"ToS 风险、封号自负"写在最顶上。 + +--- + +## 8. 风险清单(研究归研究,心里要有数) + +| 风险 | 说明 | +|---|---| +| 封号 | 违反上游 ToS 是明确的;轻则限流重则封号(WorkBuddy 已动手) | +| 随时失效 | 上游改协议 / 收紧风控 → 工具停更(活例:workbuddy2api) | +| 中转站不可信 | 你的**全部对话内容和 key** 都过别人服务器;跑路、泄露、掺水(偷换便宜模型)都常见 | +| 法律合规 | one-api README 特别提醒《生成式AI服务管理暂行办法》:国内对公众提供未备案生成式 AI 服务违规。自用没问题,**别搞成对外服务** | +| 凭证安全 | auths/ 里是明文 token;来路不明的"收费版/卡密版"可能直接偷号 | + +--- + +## 9. 上手路线(Windows + F:\AI\docker + 梯子) + +**第一步(零门槛,跑通"账号→API"流程)** +装 EasyCLIProxyAPI(CPA 官方桌面客户端,图形界面、一键启停),OAuth 登录一个 Google 账号,本地就有 `127.0.0.1:8317/v1` 可调,用 curl 或 Cherry Studio 打一发。 + +**第二步(练 Docker,理解"分发层")** +`docker run` 起 new-api(不需要任何 AI 账号,纯看网关概念:渠道/令牌/负载均衡),再把第一步 CPA 的端点作为一个"渠道"挂进去——这正是聊天记录里"放在 CPA 里面用"的玩法:CPA 做上游,new-api 做分发。 + +**第三步(可选,网络进阶)** +整套 compose 化,跑通"本地容器 + 梯子出站":容器内访问宿主机代理用 `host.docker.internal:7890`(按梯子实际端口改),CPA 也在配置里支持出站代理。 + +不建议再花时间研究 workbuddy2api。 + +--- + +## 10. 参考链接 + +- CLIProxyAPI(CPA):https://github.com/router-for-me/CLIProxyAPI (中文文档 https://help.router-for.me/cn/ ) +- CPA 桌面客户端:https://github.com/router-for-me/EasyCLIProxyAPI +- new-api:https://github.com/QuantumNous/new-api (文档 https://docs.newapi.ai ) +- one-api:https://github.com/songquanpeng/one-api +- sub2api:https://github.com/Wei-Shaw/sub2api +- workbuddy2api-panel(已停维护):https://github.com/linguo2625469/workbuddy2api-panel +- MCP 方向:https://github.com/totec448-spec/chat-on-steroids 、https://github.com/fb0sh/MCPod + +--- + +## 11. 结合我自己的 NewAPI 实战架构再理解一遍 + +> 参照:《NewAPI搭建与上线完整实战指南》(F:\AI\Obsidian\工具相关\) +> 实战环境:腾讯云新加坡 2C2G + Xray 共存,域名 api.trivoo.website + +已上线的栈,按三层模型对号入座: + +``` +Cline / Cherry Studio + │ HTTPS 443 + ▼ +Nginx 反向代理 ← 「字面意义的反代」:转发 + TLS + 隐藏后端(指南第五阶段) + │ 127.0.0.1:3000 + ▼ +New API 容器 ← 第2层 网关分发:渠道/令牌/计费/负载均衡 + ├─→ 渠道1:DeepSeek 官方 API (正规军,按量付费) + └─→ 渠道2:apikey.fan ← 第3层 商业中转站(背后是站长搭的第1层账号池) +``` + +四条结论: + +1. **同一套架构里同时存在两种"反代"**:Nginx(字面意义的反向代理)+ New API(广义的转发/中继,源码模块就叫 relay)。而 AI 圈黑话里的"反代"特指**第 1 层:账号→API 协议转换**。 +2. **反代是概念,CPA 是软件**。"反代和 CPA 是不是一回事" ≈ "数据库和 MySQL 是不是一回事"。CPA 是黑话意义上"反代"的最主流实现之一。 +3. 现状 = 自建第 2 层(new-api)+ 买第 3 层(apikey.fan 渠道)。补上 CPA(第 1 层)即完整闭环:**账号 → CPA → 挂成 new-api 渠道 → api.trivoo.website 统一分发**。 +4. 新加坡服务器本身就是外国 IP,CPA 放这台机器上出站不需要梯子;唯一要浏览器的是 OAuth 授权那一步,常规做法是本地登录后把 `auths/*.json` 凭证传上服务器(或用支持远程 OAuth 的管理面板)。 + +一个佐证细节:apikey.fan 正好出现在 CPA 和 sub2api 官方 README 的赞助商列表里("价格低至官方原价的 7%")——第 3 层中转站的本质一眼见底。