记一次搭建AI网关:New API+CLIproxyAPi

搭一套自己的 AI 网关:New API + CLIProxyAPI 部署记录

New API 与 CLIProxyAPI 部署记录封面
这套系统的目标很简单:客户端只记一个入口,敏感服务留在内网。

这几天把自己的服务器重新整理了一遍,顺手搭了一套统一的 AI 调用入口。起因并不复杂:平时会用到 DeepSeek、Gemini、Codex、Claude Code、Kimi、Grok 等不同来源的模型和账号能力,如果每个客户端都单独配置 Base URL、Key 和模型名,时间一久就会很乱。

后来我把思路收敛成一句话:公网只留下一个稳定入口,真正敏感的账号态服务全部放在内网。这样 Cherry Studio、Cursor、手机脚本都只需要连 New API;至于后面到底走官方 API Key,还是走 CLIProxyAPI 转出来的账号能力,都交给服务器处理。

文中的域名、IP、密钥和订阅地址都做了替换。实际部署时请换成自己的信息,也请不要把自己的 API Key、管理密钥、OAuth 邮箱、代理订阅和宝塔面板地址放进公开网络中,这一点非常重要。

整体结构

New API + CLIProxyAPI 架构图
New API 是门面;CLIProxyAPI 是后端能力层;Mihomo 只负责服务器侧网络出口。

最终结构分成五块:New API 做公网统一入口;CLIProxyAPI 把 CLI/OAuth 类账号能力转成 OpenAI-compatible API;Mihomo 给服务器侧服务提供代理出口;宝塔和 Nginx 负责域名、HTTPS、反向代理;SSH 隧道只负责打开内网管理端。

客户端
只配置一个 Base URL 和 New API 令牌
宝塔 Nginx
处理 HTTPS 证书与反向代理
New API
鉴权、渠道路由、模型映射和日志
CLIProxyAPI
把账号态资源包装成兼容 API
Mihomo
为服务器侧请求提供代理出口

域名和反向代理

我给这套网关单独准备了一个二级域名,例如 ai.example.com。DNS 里只需要加一条 A 记录,把它指向服务器公网 IP。这里容易混淆的一点是:DNS 只负责域名到 IP,不负责端口。真正把请求转到哪个服务,是 Nginx 反向代理的工作。

访问入口https://ai.example.com
客户端只记这个地址。
反向代理http://127.0.0.1:3001
New API 只监听服务器本机端口。
证书来源Let's Encrypt
由宝塔申请并自动续签。

New API 容器只绑定到服务器本机端口,公网不直接开放 3001。外部访问全部走宝塔站点的 HTTPS,这样证书、访问日志和反代规则都能在宝塔里统一看到。

部署 New API

New API 适合作为公网主入口。它负责令牌、渠道、模型映射、日志和额度这些“网关应该管的事”。我这里没有直接用服务器已有的 MySQL,而是让 New API 自己带 PostgreSQL 和 Redis。这样和原本的站点数据库互不影响,后续迁移也更清楚。

services:
  new-api:
    image: calciumion/new-api:latest
    container_name: new-api
    restart: unless-stopped
    ports:
      - "127.0.0.1:3001:3000"
    environment:
      SQL_DSN: postgres://newapi:${POSTGRES_PASSWORD}@new-api-postgres:5432/newapi
      REDIS_CONN_STRING: redis://new-api-redis:6379
      SESSION_SECRET: ${SESSION_SECRET}
    depends_on:
      - new-api-postgres
      - new-api-redis

  new-api-postgres:
    image: postgres:15
    restart: unless-stopped
    environment:
      POSTGRES_DB: newapi
      POSTGRES_USER: newapi
      POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}

  new-api-redis:
    image: redis:7-alpine
    restart: unless-stopped

启动后打开 http://127.0.0.1:3001/setup 完成初始化。先接 DeepSeek、OpenRouter、百炼这类官方 API Key 渠道,确认 New API 自身能正常工作,再继续往后接 CLIProxyAPI。

部署 Mihomo

服务器侧代理我选 Mihomo。原因很朴素:订阅兼容性好,容器部署简单,也有现成的 Web 面板。它不需要暴露公网,主要给 CLIProxyAPI 访问部分上游服务时使用。

services:
  mihomo:
    image: metacubex/mihomo:latest
    container_name: mihomo
    restart: unless-stopped
    volumes:
      - ./config:/root/.config/mihomo
    ports:
      - "127.0.0.1:9090:9090"
      - "127.0.0.1:7890:7890"

订阅地址和控制器密钥不要公开到外网中。实际维护时可以放到服务器本地配置文件,再通过脚本刷新订阅。Web 面板同样只通过 SSH 隧道打开。

部署 CLIProxyAPI

CLIProxyAPI 这层只做一件事:把 Codex、Claude Code、Gemini CLI、Kimi、Grok 等账号能力包装成兼容 API。它手里会保存认证文件和账号态,所以这层我只放在内网。

services:
  cli-proxy-api:
    image: ghcr.io/router-for-me/cli-proxy-api:v7.1.29
    container_name: cli-proxy-api
    restart: unless-stopped
    ports:
      - "127.0.0.1:8317:8317"
    environment:
      API_KEY: ${CPA_API_KEY}
      MANAGEMENT_KEY: ${CPA_MANAGEMENT_KEY}
      HTTP_PROXY: http://mihomo:7890
      HTTPS_PROXY: http://mihomo:7890
    volumes:
      - ./auths:/app/auths
      - ./data:/app/data

版本号建议固定到自己验证过的一版。升级前先看 release note,再拉新镜像;这种握着账号态的服务,不适合无脑追 latest

New API、CLIProxyAPI 和 Mihomo 管理入口截图拼版
管理页面可以截图记录,但发布时要确认没有露出真实域名、密钥、订阅或账号信息。

用 SSH 隧道打开管理端

管理端口我统一放进 SSH 配置。这样平时只要执行 ssh -N aliyun,本地就能打开对应面板;关闭 SSH 后,这些入口也自然关掉。

Host aliyun
  HostName your.server.ip
  User ecs-user
  LocalForward 3000 127.0.0.1:3000
  LocalForward 8317 127.0.0.1:8317
  LocalForward 9090 127.0.0.1:9090
启动隧道ssh -N aliyun
保持这个终端窗口不关闭。
New APIhttp://127.0.0.1:3001
本地管理入口。
CLIProxyAPIhttp://127.0.0.1:8317/management.html
只在本地打开管理页。
Mihomohttp://127.0.0.1:9090
本地查看代理面板。

把 CLIProxyAPI 接回 New API

这里有一个小细节:New API 在容器里运行时,容器里的 127.0.0.1 指的是 New API 自己,不是宿主机,也不是 CLIProxyAPI。更稳的做法是让两个容器加入同一个 Docker 网络,然后用服务名访问。

docker network connect cli-proxy-api_default new-api
渠道类型OpenAI-compatible
让 New API 按兼容接口调用。
Base URLhttp://cli-proxy-api:8317/v1
这里用 Docker 网络服务名,不写 127.0.0.1。
Keycpa-你的-api-key
使用 CLIProxyAPI 的 API Key,不要填管理密钥。
模型按 CLIProxyAPI 中的模型名填写
配置后再做一次真实请求验证。

配置完成后,不要只看模型列表。最可靠的验证方式,是从 New API 的公网地址发一次真实请求,让模型只回复 OK

curl https://ai.example.com/v1/chat/completions   -H "Authorization: Bearer sk-你的-newapi-token"   -H "Content-Type: application/json"   -d '{
    "model": "your-model-name",
    "messages": [
      {"role": "user", "content": "只回复 OK"}
    ]
  }'
New API 到 CLIProxyAPI 的请求链路图
能从公网 New API 入口拿到 OK,才说明完整链路跑通。

客户端怎么用

对客户端来说,最后只需要三样东西:New API 的 Base URL、New API 里生成的令牌、以及在 New API 里暴露出来的模型名。

Base URLhttps://ai.example.com/v1
所有客户端统一使用这个入口。
API KeyNew API 令牌
按设备或用途单独生成,便于限额和回收。
ModelNew API 里配置的模型名
客户端不用知道后端实际渠道。

我现在更喜欢这种方式:客户端只拿 New API 令牌,不直接接触上游账号,也不接触 CLIProxyAPI 的管理密钥。哪个设备能用哪些模型、哪个渠道优先、是否限额,都放在 New API 里管。

几个值得记下来的点

公网与内网安全边界图
真正敏感的是账号态、代理订阅和管理密钥;它们不应该成为公网服务的一部分。

第一,DNS 只管域名到 IP,端口转发交给 Nginx。很多 404 或跳到主站的问题,其实不是解析错了,而是宝塔站点或反向代理规则没匹配上。

第二,官方 API Key 和账号态资源最好分开管理。DeepSeek、OpenRouter 这类 Key 类服务直接进 New API;Codex、Gemini CLI、Claude Code 这类账号态资源先放 CLIProxyAPI,再由 New API 调用。

第三,容器网络要想清楚。跨容器访问时,优先用 Docker 网络里的服务名,不要把宿主机、本机回环地址和容器内部回环地址混在一起。

最后的状态

公网
https://ai.example.com/v1
给 Cherry Studio、Cursor、手机和脚本调用。
本地隧道
127.0.0.1:3001
New API 管理入口。
127.0.0.1:8317
CLIProxyAPI 管理入口。
127.0.0.1:9090
Mihomo 面板入口。
服务端
New API + PostgreSQL + Redis
负责统一网关和基础数据。
CLIProxyAPI + auths/data
保存账号态认证和转换服务。
Mihomo + 订阅配置
负责服务器侧代理出口。

折腾完以后,使用体验其实变简单了:所有客户端只认一个入口,服务端再慢慢扩渠道、调模型、做限额。后续如果要接更多账号、换代理出口,改的也都是后端,不用再到每台设备上逐个重配;多电脑、多终端的情况下会方便很多。

这篇先记录到这里,大家可以参考。

参考


本文部分内容使用AI生成,请注意甄别。

文末附加内容
暂无评论

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇