first commit
This commit is contained in:
commit
47218488aa
10 files changed
+1438
No files matched your search
@@ -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\)
|
||||
@@ -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 订阅生效中 |
|
||||
@@ -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 都能用
|
||||
- 全程:数据在你自己的服务器上跑,不经过任何第三方中转
|
||||
- 成本:只花服务器钱(本来就在付),模型额度用的是你已付费的订阅
|
||||
|
||||
**唯一的代价**:这是一条"非官方"路径(属于灰色地带),上游随时可能调整。所以随时记住——**这套东西是可拆的、可放弃的**,不会绑架你。
|
||||
@@ -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 <<EOF
|
||||
config-version: 8
|
||||
|
||||
server:
|
||||
host: "" # bind all ifaces INSIDE container; exposure controlled by compose loopback binding
|
||||
port: 8317
|
||||
|
||||
management:
|
||||
allow-remote: false # panel reachable only via localhost / ssh tunnel
|
||||
secret-key: "${MGMT_KEY}"
|
||||
|
||||
access:
|
||||
api-keys:
|
||||
- "${CPA_API_KEY}" # used by New API channel
|
||||
|
||||
oauth:
|
||||
auth-dir: "~/.cli-proxy-api"
|
||||
|
||||
observability:
|
||||
usage:
|
||||
usage-statistics-enabled: true
|
||||
EOF
|
||||
chmod 600 config.yaml
|
||||
cat > KEYS.txt <<EOF
|
||||
# ============================================
|
||||
# CPA secrets (keep private)
|
||||
# Management panel key (MGMT_KEY):
|
||||
${MGMT_KEY}
|
||||
# API key for New API channel (CPA_API_KEY):
|
||||
${CPA_API_KEY}
|
||||
# ============================================
|
||||
EOF
|
||||
chmod 600 KEYS.txt
|
||||
echo " config.yaml + KEYS.txt generated"
|
||||
fi
|
||||
|
||||
step 4 "Write docker-compose.yml"
|
||||
cat > 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"
|
||||
@@ -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
|
||||
Reference in new issue
Block a user