别把 API Key 到处塞了:我用 NewAPI 搭了一个自用 AI 中转站
先说结论
NewAPI 不是一个“白嫖模型”的工具,也不是一个神秘代理。它更像我家里的“AI 前台”:所有 App 只认一个入口,前台负责转发到合法授权的上游模型,顺手做令牌、额度、分组、日志、模型限制和用量统计。对自用场景来说,最舒服的地方不是“多了一个网页”,而是终于不用把每个上游 Key 分散塞进十几个客户端。
本文会按我自己搭自用中转站的思路写:为什么需要它、容易误解在哪里、最小可用 Docker Compose 怎么跑、为什么我建议加持久化目录、Windows 11 / Ubuntu 26.04 / macOS 26 三套一键脚本怎么写,以及让 Agent 自动配置时应该给它什么边界。全文不放真实内网地址、完整主机名、私有域名和任何密钥。

图 1:AI 生成封面。NewAPI 的价值不是“替你造模型”,而是把模型入口、权限和账本收在一个地方。
一、问题背景:为什么我需要一个自用 AI 中转站
如果你只在一个聊天网页里用一个模型,确实不需要 NewAPI。问题是我现在的用法早就不是这样了:桌面客户端、命令行 Agent、代码编辑器、脚本任务、临时测试工具,每个地方都想调用模型;上游也不止一家,有的便宜,有的快,有的上下文长,有的适合写代码,有的适合轻量任务。
最开始的做法很直接:每个工具里各填一遍 API 地址和 Key。能用,但很快失控。
第一,密钥散落。某个配置文件、某个环境变量、某个旧脚本里到底还有没有 Key,时间一长自己都说不清。
第二,模型名不统一。A 工具叫 gpt-xxx,B 工具配置成另一个别名,后来上游模型下线,排查时要翻每个客户端。
第三,用量看不清。到底是哪个工具消耗多、哪个模型突然变贵、哪个 token 该限额,如果没有统一账本,只能靠猜。
第四,权限不好收。把上游 Key 直接给应用,就像把整串钥匙交给临时工。它可能只需要打开厨房门,但你给了它整栋楼的钥匙。
NewAPI 解决的正是这类“入口太散”的问题。官方 README 把它定位为“新一代大模型网关与 AI 资产管理系统”,支持多语言 UI、数据看板、令牌分组、模型限制、用量和成本管理,也能兼容 OpenAI、Claude、Gemini 等不同接口格式。我的理解更朴素:它就是一个可自建的模型总前台。

图 2:真实截图,来源于 New API 官方文档安装页。官方把 Docker Compose 放在部署方式里,适合长期运行的自建服务。
二、问题表现:你以为只是“转发请求”,实际是“管钥匙和账本”
很多人第一次听“中转站”,会以为它只是一个反向代理:客户端发请求,它照搬到上游,再把结果照搬回来。如果只做到这一步,Nginx 都能凑合,没必要专门上 NewAPI。
NewAPI 真正有价值的地方在中间层:
- 渠道管理:不同上游可以作为不同 channel,按模型、权重、状态进行管理。
- 令牌管理:给不同工具发不同 token,限制额度、模型范围和可用分组。
- 用量记录:知道谁在什么时候调用了什么模型,排查异常消耗时不用盲猜。
- 兼容入口:让客户端尽量按熟悉的 OpenAI 风格调用,也能接入其他格式。
- 运营配置:自用时是家庭账本,小团队时就是预算和权限边界。
打个小学生也能懂的比方:上游 Key 是“食堂后厨钥匙”,NewAPI 是“饭卡系统”。学生不该直接拿后厨钥匙去开冰箱,而是刷自己的饭卡。饭卡里有余额、能买哪些窗口、今天刷了几次,系统都知道。某张饭卡丢了,挂失这一张就行,不用把整个食堂的锁都换掉。
图 3:NewAPI 更像饭卡系统。客户端只拿自己的 token,上游 Key 留在网关侧集中管理。
三、问题分析:自用部署最容易踩的 5 个坑
我看 NewAPI 部署时,最容易犯的错不是命令写错,而是把“能打开网页”误认为“部署完成”。
坑 1:不挂载数据目录。 用户给出的最小 Compose 可以启动服务,但如果没有 ./data:/data,后续容器重建时就容易把 SQLite 数据、上传文件或本地状态弄丢。自用也要持久化,因为配置 channel 和 token 是有成本的。
坑 2:上来就用 latest。 官方示例为了通用,常用 calciumion/new-api:latest。我自己更偏向固定一个明确 tag,比如本文使用用户给出的 calciumion/new-api:v1.0.0-rc.19-i18nfix.2。固定版本的好处是:今天能跑,明天重建还是同一套行为;等你想升级,再主动换 tag。
坑 3:把上游 Key 写进博客、脚本或聊天记录。 文章里只能写占位符,真实 Key 应该通过 Web UI、密钥管理器或本机安全输入进入系统。尤其是让 Agent 帮你配置时,不要让它读取 .env 里的真实值,也不要让它把 sk- 内容打印出来。
坑 4:没有初始化后的验证。 容器状态 Up 只是说明进程还活着,不代表你能登录、不代表 channel 可用、不代表 token 能调用模型。至少要看容器日志、访问状态接口、登录后台、添加一个授权 channel、创建一个低额度 token,再用客户端发一次最小请求。
坑 5:把自用网关误当公开服务。 如果你要对公众提供生成式 AI 服务或 API 转售服务,就不是“家里跑个容器”这么简单。官方 README 也明确提醒,需要自行处理备案、许可、内容安全、实名、日志留存、税务和上游授权等合规要求。本文只讨论合法授权下的自用和小范围内部场景。

图 4:真实截图,来源于官方 Docker Compose 部署页。部署不是只复制 YAML,还要会看日志和状态。
四、如何解决:先跑最小可用,再补上持久化和验证
用户给出的 Compose 是最小可用形态:
services:
new-api:
image: calciumion/new-api:v1.0.0-rc.19-i18nfix.2
container_name: new-api
restart: always
ports:
- "3000:3000"
environment:
TZ: "Asia/Shanghai"
这段可以启动,但我建议自用时至少加一个数据卷:
services:
new-api:
image: calciumion/new-api:v1.0.0-rc.19-i18nfix.2
container_name: new-api
restart: always
ports:
- "3000:3000"
environment:
TZ: "Asia/Shanghai"
SESSION_SECRET: "${SESSION_SECRET}"
volumes:
- ./data:/data
SESSION_SECRET 不要手写固定示例值,脚本里生成。./data:/data 是自用部署的底线。它就像把笔记本放进书包:容器可以重建,书包里的数据不能跟着丢。
如果后续要更稳,可以再引入 PostgreSQL/MySQL 和 Redis。官方 Docker Compose 配置指南里给了包含数据库和 Redis 的生产示例,也说明了 SQL_DSN、REDIS_CONN_STRING、SESSION_SECRET、NODE_TYPE、SYNC_FREQUENCY 等环境变量的用途。我的建议是:第一天先用最小版跑通;当你已经有多个用户、多个渠道、明确备份方案,再升级到数据库版。

图 5:真实截图,来源于官方配置指南。长期运行时,要关注数据卷、数据库、Redis、健康检查和默认密码。
五、一键脚本:Windows 11 / Ubuntu 26.04 / macOS 26
下面三套脚本的目标一致:
- 检查 Docker 和 Docker Compose 是否可用;
- 创建部署目录;
- 生成随机
SESSION_SECRET; - 写入
docker-compose.yml和.env; - 启动 NewAPI;
- 做本机状态检查;
- 不安装第三方工具,不写入真实上游 Key,不暴露内网地址。
注意:脚本本身不调用任何额外 SaaS;但 Docker 拉取镜像仍需要你当前机器能访问配置好的镜像源。脚本里的访问地址只使用 localhost 和占位域名。
Windows 11:PowerShell
保存为 install-newapi-windows.ps1,右键用 PowerShell 运行:
$ErrorActionPreference = "Stop"
$Root = Join-Path $HOME "newapi"
$Image = "calciumion/new-api:v1.0.0-rc.19-i18nfix.2"
$Port = "3000"
function Need-Cmd($Name) {
if (-not (Get-Command $Name -ErrorAction SilentlyContinue)) {
throw "Missing command: $Name. Please install Docker Desktop first."
}
}
Need-Cmd docker
docker compose version | Out-Null
New-Item -ItemType Directory -Force -Path $Root | Out-Null
New-Item -ItemType Directory -Force -Path (Join-Path $Root "data") | Out-Null
$SecretBytes = New-Object byte[] 32
[Security.Cryptography.RandomNumberGenerator]::Fill($SecretBytes)
$SessionSecret = [Convert]::ToBase64String($SecretBytes)
@"
SESSION_SECRET=$SessionSecret
"@ | Set-Content -Encoding UTF8 (Join-Path $Root ".env")
@"
services:
new-api:
image: $Image
container_name: new-api
restart: always
ports:
- "$Port`:3000"
environment:
TZ: "Asia/Shanghai"
SESSION_SECRET: "`${SESSION_SECRET}"
volumes:
- ./data:/data
"@ | Set-Content -Encoding UTF8 (Join-Path $Root "docker-compose.yml")
Push-Location $Root
docker compose up -d
Start-Sleep -Seconds 8
docker compose ps
try {
$r = Invoke-WebRequest -UseBasicParsing "http://localhost:$Port/api/status" -TimeoutSec 8
Write-Host "Status endpoint HTTP:" $r.StatusCode
} catch {
Write-Host "Container started. If status check failed, open http://localhost:$Port and check docker compose logs."
}
Pop-Location
Write-Host "NewAPI files are in $Root"
Write-Host "Open http://localhost:$Port for first-time initialization."
Ubuntu 26.04:Bash
保存为 install-newapi-ubuntu.sh,执行 bash install-newapi-ubuntu.sh:
#!/usr/bin/env bash
set -euo pipefail
ROOT="${HOME}/newapi"
IMAGE="calciumion/new-api:v1.0.0-rc.19-i18nfix.2"
PORT="${NEWAPI_PORT:-3000}"
need_cmd() {
command -v "$1" >/dev/null 2>&1 || {
echo "Missing command: $1. Please install Docker Engine and Docker Compose plugin first." >&2
exit 1
}
}
need_cmd docker
docker compose version >/dev/null
mkdir -p "${ROOT}/data"
SESSION_SECRET="$(openssl rand -base64 32 2>/dev/null || head -c 32 /dev/urandom | base64)"
cat > "${ROOT}/.env" <<EOF
SESSION_SECRET=${SESSION_SECRET}
EOF
chmod 600 "${ROOT}/.env"
cat > "${ROOT}/docker-compose.yml" <<EOF
services:
new-api:
image: ${IMAGE}
container_name: new-api
restart: always
ports:
- "${PORT}:3000"
environment:
TZ: "Asia/Shanghai"
SESSION_SECRET: "\${SESSION_SECRET}"
volumes:
- ./data:/data
EOF
cd "${ROOT}"
docker compose up -d
sleep 8
docker compose ps
if command -v curl >/dev/null 2>&1; then
curl -fsS "http://localhost:${PORT}/api/status" || true
echo
fi
echo "NewAPI files are in ${ROOT}"
echo "Open http://localhost:${PORT} for first-time initialization."
macOS 26:Zsh
保存为 install-newapi-macos.zsh,执行 zsh install-newapi-macos.zsh:
#!/usr/bin/env zsh
set -euo pipefail
ROOT="${HOME}/newapi"
IMAGE="calciumion/new-api:v1.0.0-rc.19-i18nfix.2"
PORT="${NEWAPI_PORT:-3000}"
need_cmd() {
if ! command -v "$1" >/dev/null 2>&1; then
echo "Missing command: $1. Please install Docker Desktop or a compatible Docker runtime first." >&2
exit 1
fi
}
need_cmd docker
docker compose version >/dev/null
mkdir -p "${ROOT}/data"
SESSION_SECRET="$(openssl rand -base64 32)"
cat > "${ROOT}/.env" <<EOF
SESSION_SECRET=${SESSION_SECRET}
EOF
chmod 600 "${ROOT}/.env"
cat > "${ROOT}/docker-compose.yml" <<EOF
services:
new-api:
image: ${IMAGE}
container_name: new-api
restart: always
ports:
- "${PORT}:3000"
environment:
TZ: "Asia/Shanghai"
SESSION_SECRET: "\${SESSION_SECRET}"
volumes:
- ./data:/data
EOF
cd "${ROOT}"
docker compose up -d
sleep 8
docker compose ps
curl -fsS "http://localhost:${PORT}/api/status" || true
echo
echo "NewAPI files are in ${ROOT}"
echo "Open http://localhost:${PORT} for first-time initialization."
六、人工自动执行:跑完脚本之后还要做什么
脚本只负责把服务跑起来。初始化和上游配置建议人工做,因为这里会接触真实账号、真实上游 Key 和合规边界。
我的顺序是:
- 打开
http://localhost:3000,按页面提示创建管理员账号; - 进入后台后先改默认配置,开启必要的登录保护;
- 新增一个合法授权的上游 channel,只填你自己拥有权限的上游;
- 用 channel 测试功能确认上游可用;
- 创建一个低额度 token,限制可调用模型;
- 在一个客户端里只配置 NewAPI 的 base URL 和这个低额度 token;
- 发一次最小请求,确认日志里能看到调用记录;
- 备份
~/newapi/data,并至少做一次恢复演练。
这一套流程看起来比“复制一段 compose”麻烦,但它能避免很多后患。尤其是第 5 步,低额度 token 是安全阀。某个客户端配置错、脚本死循环、模型名误写,最多烧掉这个 token 的额度,而不是拖着上游主 Key 一起出事。
图 6:容器启动只是第 3 步。真正可靠的自用中转站,要闭环到 token、验证和备份。
七、Agent 自动配置:给它边界,不要给它裸 Key
如果你想让 Codex、Claude、OpenClaw、HermesAgent 这类 Agent 帮你自动配置,可以直接给下面这段提示词。重点是让 Agent 做“文件和服务编排”,不要让它读取或打印真实密钥。
请在当前机器部署一个自用 NewAPI 服务,要求:
1. 只使用 Docker Compose,不安装额外第三方服务。
2. 使用镜像 calciumion/new-api:v1.0.0-rc.19-i18nfix.2。
3. 部署目录为用户主目录下的 newapi,必须挂载 ./data:/data。
4. 自动生成 SESSION_SECRET,写入 .env,权限尽量收紧。
5. 只暴露本机 3000 端口,不写入任何真实内网地址、主机名、私有域名或 API Key。
6. 启动后执行 docker compose ps、docker compose logs --tail=80 new-api,并检查 http://localhost:3000/api/status。
7. 如果需要上游模型 Key,只给我明确的人工输入位置,不要读取、显示或记录真实 Key。
8. 完成后输出部署目录、验证结果、下一步人工初始化清单。
让 Agent 做这类事时,我会额外加三条硬约束:
- 不让它读
.env:它可以创建占位或生成随机 session secret,但不能把密钥内容回显到对话里。 - 不让它改反向代理:除非我明确给出域名和证书路径,否则先只跑
localhost。 - 不让它创建公开注册入口:自用站点先默认关闭开放注册,用户和 token 都由管理员发放。
Agent 很像执行力很强的实习生。你让它“把店开起来”,它可能连门牌、收银台、仓库都一起动;你让它“只把货架摆好,钥匙我自己拿”,风险就小得多。
八、验证:不要相信“应该能用”
官方 API 文档里可以看到 NewAPI 提供 OpenAI Chat Completions 兼容格式,路径是 /v1/chat/completions。这意味着很多客户端可以把 NewAPI 当成 OpenAI 风格入口来接。但真正验证时,不要第一步就拿复杂 Agent 流程测试,先做最小闭环。
验证清单如下:
cd ~/newapi
docker compose ps
docker compose logs --tail=80 new-api
curl -fsS http://localhost:3000/api/status
后台初始化后,再做应用层验证:
- channel 测试成功;
- token 限额和模型范围正确;
- 客户端 base URL 指向你的 NewAPI 入口;
- 客户端只拿 NewAPI token,不拿上游 Key;
- 日志里能看到本次请求;
- 禁用 token 后,客户端请求会失败;
- 备份 data 目录后,能在测试目录恢复。
验证这件事像收快递。短信说“已签收”不算,你要打开门看包裹真的在门口,还要拆开确认里面不是空盒子。

图 7:真实截图,来源于官方 API 文档。接入客户端前,先确认你要用的是哪种兼容格式。
九、问题根因:中转站真正解决的是“控制面分散”
回头看,NewAPI 解决的根因不是“我需要一个代理地址”,而是“AI 使用的控制面太分散”。
没有 NewAPI 时,控制面散在每个客户端里:哪个模型能用、额度多少、Key 在哪里、请求日志在哪里、失败该看谁。每个客户端都像一个小账本,小账本多了就会乱。
有 NewAPI 后,控制面集中到网关:客户端只负责调用,管理员负责 channel、token、额度、日志、模型范围和备份。这种结构不一定更简单,但更可控。
所以我建议的自用原则是:
- 能本地闭环就不要先公网暴露;
- 能发低额度 token 就不要发上游主 Key;
- 能固定镜像版本就不要盲目 latest;
- 能先 SQLite 跑通就不要第一天引入复杂集群;
- 能验证日志和请求就不要只看容器 Up。
十、Q&A
Q1:NewAPI 是不是越权调用模型?
不是。它只是网关。你必须合法取得上游模型、账号、Key 和接口权限,并遵守上游条款。没有授权的上游,它不能凭空变出模型。
Q2:我能不能把它公开给别人用?
技术上可以,责任上很重。公开服务涉及内容安全、实名、日志留存、支付、税务、备案、上游授权等问题。本文只建议自用或小范围内部授权使用。
Q3:SQLite 够不够?
个人自用、少量 token、少量 channel,SQLite 很方便。多人团队、重负载、集群或更严格备份恢复要求,建议看官方生产 Compose,使用数据库和 Redis。
Q4:为什么不用 latest?
latest 适合快速体验,不适合“今天部署、半年后重建仍要一样”的服务。固定 tag 能降低不可预期变化。升级时再主动改 tag、备份、验证。
Q5:脚本为什么不自动配置上游 Key?
因为 Key 是最高风险信息。脚本可以部署框架,真实上游 Key 应该由你在 Web UI 或安全输入流程里填,不应该出现在博客、聊天记录、终端历史或 Agent 输出里。
Q6:我应该怎么备份?
最小部署至少备份 ~/newapi/data、docker-compose.yml 和 .env。注意 .env 可能包含 session secret,要加密保存。备份不是压缩完就结束,至少要在测试目录恢复一次。
参考资料
- New API GitHub 仓库:https://github.com/QuantumNous/new-api
- New API 官方安装文档:https://www.newapi.ai/en/docs/installation
- Docker Compose 部署文档:https://www.newapi.ai/en/docs/installation/deployment-methods/docker-compose-installation
- Docker Compose 配置指南:https://www.newapi.ai/en/docs/installation/config-maintenance/docker-compose-yml
- 功能介绍:https://www.newapi.ai/en/docs/guide/wiki/basic-concepts/features-introduction
- API 文档:https://www.newapi.ai/en/docs/api