Windows 下部署 New API 中转站全过程实录(含 6 个真实踩坑)
本文记录一次完整的 New API(QuantumNous/new-api)Windows 本地部署过程:从下载、校验、配置、启动,到接入 Claude Code 和 Codex CLI,以及过程中真实遇到的 6 个报错和它们的根因。所有结论都对应到具体的源码文件和行号,不是复述文档。
版本:v1.0.0-rc.25 | 系统:Windows 10 (19045) | 数据库:SQLite
一、先决定用哪种安装方式
New API 官方提供三条路,别一上来就选错:
| 方式 | 适用场景 | 代价 |
|---|---|---|
| Docker Compose | 生产、多节点、要 Redis/PostgreSQL | 需要装 Docker Desktop,Windows 上还要开 WSL2 |
| 源码编译 | 要改代码 | 需要 Go ≥ 1.25.1 + bun,前端资源要自己 build |
| 官方 Release 二进制 | 单机自用、快速验证 | 版本更新要手动换文件 |
我这台机器的实际情况是:没有 Docker,本机 Go 是 1.22.0/386,而 go.mod 第 4 行明确写着 go 1.25.1,也没有 bun。三条路里只有第三条能立刻走通,所以本文走官方二进制。
顺带说明,源码编译不是「装个 Go 就行」:前端产物是通过 embed 打进二进制的,缺了 bun 构建出来的 web/dist,编译出来的程序打开是白页。
如果你要走 Docker,仓库里的 docker-compose.yml 默认是 PostgreSQL + Redis 组合,端口映射 3000:3000,数据卷 ./data:/data、日志卷 ./logs:/app/logs。注意它里面 SQL_DSN 和 REDIS_CONN_STRING 的密码都是 123456,文件里自己都标了 ⚠️ IMPORTANT: Change all default passwords,上公网前必须改。
二、下载与校验
Release 页面:https://github.com/QuantumNous/new-api/releases
Windows 需要的是两个文件:
-
new-api-v1.0.0-rc.25.exe(约 115 MB,前端资源已内嵌) -
checksums-windows.txt(校验文件)
国内网络下载不动怎么办
直连 GitHub 大概率是 Recv failure: Connection was reset。我实测可用的是 ghfast.top 反代,把原地址整个拼在后面即可:
curl -L -o new-api.exe \ "https://ghfast.top/https://github.com/QuantumNous/new-api/releases/download/v1.0.0-rc.25/new-api-v1.0.0-rc.25.exe" curl -L -o checksums-windows.txt \ "https://ghfast.top/https://github.com/QuantumNous/new-api/releases/download/v1.0.0-rc.25/checksums-windows.txt"
同样的写法也适用于 git clone(https://ghfast.top/https://github.com/...)和 raw.githubusercontent.com 上的单个文件。另外补一句实测结论:api.github.com 是能直连的,所以「查版本号能通、下文件下不动」是正常现象,别以为是自己配置错了。
一定要校验哈希
120 MB 的文件走反代,中途被截断或者被替换你是看不出来的。PowerShell 自带工具:
Get-FileHash .\new-api.exe -Algorithm SHA256 | Format-List Get-Content .\checksums-windows.txt
两边比对一致再往下走。我这次拿到的是:
-
大小:
120,778,752字节
(这个值只对 v1.0.0-rc.25 的 Windows 版有效,你下别的版本对不上是正常的,以你自己那份 checksums-windows.txt 为准。)
三、配置 .env
在 exe 同目录建一个 .env。New API 用 godotenv 读它,所有配置项也都可以直接写成系统环境变量,两者等价。
# 会话与加密密钥,必须是随机值,且不要提交到 git SESSION_SECRET=<换成你自己生成的随机串> CRYPTO_SECRET=<换成你自己生成的随机串> # 留空即使用 SQLite,数据库文件路径见 SQLITE_PATH SQL_DSN= SQLITE_PATH=data/new-api.db?_busy_timeout=30000 TZ=Asia/Shanghai ERROR_LOG_ENABLED=true BATCH_UPDATE_ENABLED=true NODE_NAME=new-api-local
两个密钥用这条命令生成(每次执行都不同,跑两次分别填进去):
-join ((1..32) | ForEach-Object { '{0:x2}' -f (Get-Random -Max 256) })
几个字段的实际含义:
-
SESSION_SECRET:后台登录会话签名用。不设或者用固定值,多节点部署时会互相踢下线;单机也建议设,换机迁移时保持一致就不用重新登录。 -
CRYPTO_SECRET:数据库里敏感字段的加密密钥。这个丢了,已存的渠道密钥就解不开了,务必和data/一起备份。 -
SQL_DSN:留空走 SQLite,适合单机;要上 MySQL 就写user:pass@tcp(127.0.0.1:3306)/new-api,PostgreSQL 写postgresql://user:pass@host:5432/new-api。 -
SQLITE_PATH里的_busy_timeout=30000:SQLite 写锁等待 30 秒,并发稍高时能明显减少database is locked。 -
BATCH_UPDATE_ENABLED=true:额度、日志的写入合并成批,SQLite 下强烈建议开。
四、启动
先前台跑一次
第一次一定要前台启动,看着日志出问题好排查:
.\new-api.exe --port 3000 --log-dir .\logs
可用的命令行参数就四个(来自 common/init.go:19-22):
--port 监听端口,默认 3000 --log-dir 日志目录,默认 ./logs --version 打印版本后退出 --help 打印帮助后退出
端口的优先级是:环境变量 PORT > --port > 默认 3000(main.go:202-205)。所以 .env 里写了 PORT 会盖掉命令行参数,这点容易踩。
看到监听 3000 的日志后,浏览器打开 http://127.0.0.1:3000。
再改成后台常驻
这里有个坑:如果你是在终端里直接 .\new-api.exe 起的,那么关掉终端窗口、或者杀掉那个终端进程,New API 会一起死。要真正常驻,用 Start-Process 完全脱离父进程:
# start-newapi.ps1 Start-Process -FilePath 'F:\newapi\new-api.exe' ` -ArgumentList '--port', '3000', '--log-dir', 'F:\newapi\logs' ` -WorkingDirectory 'F:\newapi' ` -WindowStyle Hidden ` -RedirectStandardOutput 'F:\newapi\logs\console.log' ` -RedirectStandardError 'F:\newapi\logs\console.err.log'
powershell -NoProfile -ExecutionPolicy Bypass -File .\start-newapi.ps1
我实测验证过:这样启动后,把启动它的那个 PowerShell 会话整个杀掉,New API 进程仍然存活。
要开机自启,把上面这个 .ps1 挂到「任务计划程序」,触发器选「计算机启动时」、勾上「不管用户是否登录都要运行」即可。想更规范就用 NSSM 注册成 Windows 服务。
停止服务:
Get-Process new-api -ErrorAction SilentlyContinue | Stop-Process
五、初始化与基本配置
1. 创建管理员
rc.25 是引导式初始化,不是老 one-api 那套 root/123456。第一次访问会走 /api/setup(路由见 router/api-router.go:22-23),页面上直接让你设置管理员账号和密码,设完自动登录。
如果你打开发现直接是登录页而不是引导页,说明 data/new-api.db 里已经有管理员了——检查是不是复用了别人的 data 目录。
2. 添加渠道
「渠道」= 上游供应商。关键字段:
-
类型:如果上游本身也是一个 New API / One API 站点,选
New API(内部编号 60,见constant/channel.go:60)。这个类型是协议直通的,/v1/chat/completions、/v1/messages、/v1/responses都原样转发。 -
代理地址:上游站点根地址,例如
https://your-upstream.example.com,不要带/v1。 -
密钥:上游给你的 key。
-
模型:必须逐个列出上游实际支持的模型名,例如
claude-opus-5,claude-opus-5-thinking。这里没写的模型,客户端请求会直接 404/503。 -
分组:默认填
default。
配完点「测试」,能返回内容再往下走。
3. 创建令牌
「令牌」= 你发给客户端用的 key,格式是 sk- 开头。
必须注意分组要对得上:令牌的分组和渠道的分组不匹配,请求会被拒,报错是
No available channel for model xxx under group vip (distributor)
我这次就踩了:账号里有两个同名令牌,一个在 vip 组一个在 default 组,而所有渠道都只在 default 组,用错那个就是 503。看到 No available channel 先别怀疑渠道,先去核对分组。
六、客户端接入
Claude Code
Claude Code 认三个环境变量:
ANTHROPIC_BASE_URL=http://127.0.0.1:3000 ANTHROPIC_AUTH_TOKEN=sk-你的令牌 ANTHROPIC_MODEL=claude-opus-5
ANTHROPIC_BASE_URL 填根地址,不要加 /v1,Claude Code 自己会拼 /v1/messages。
还有一个高频坑:Claude Code 除了主模型,后台还会用 Haiku 跑标题生成之类的小任务。如果你的上游只有 4 个 opus 模型、没有 haiku,那默认的 haiku 模型名会打空,后台任务不断 5xx。解决办法是把它也指到你实际有的模型上:
ANTHROPIC_DEFAULT_HAIKU_MODEL=claude-opus-5 ANTHROPIC_DEFAULT_SONNET_MODEL=claude-opus-5 ANTHROPIC_DEFAULT_OPUS_MODEL=claude-opus-5
只有出现在 GET /v1/models 里的模型名才能用,模型名写错的表现同样是 503,很容易误判成中转站坏了。
用 cc-switch 管理多个供应商的话,上面这些就是它写进配置里的字段,在图形界面里填一遍即可,不用手改文件。
Codex CLI
~/.codex/config.toml:
model_provider = "custom" model = "gpt-5.6-sol" model_reasoning_effort = "high" disable_response_storage = true [model_providers.custom] name = "My Codex" base_url = "http://127.0.0.1:3000/v1" wire_api = "responses" requires_openai_auth = true
~/.codex/auth.json:
{ "OPENAI_API_KEY": "sk-你的令牌" }
三个细节:
-
Codex 这边的
base_url要带/v1,和 Claude Code 正好相反。 -
wire_api只能是"responses"。新版 Codex 已经移除了 chat 协议,填"chat"会直接启动失败:wire_api = "chat"is no longer supported(见 openai/codex discussions/7782)。 -
因此 model 必须选上游支持 Responses 协议的模型,这是本文最大的坑,见踩坑二。
七、六个真实踩坑
踩坑一:503 system memory overloaded
现象:
Unexpected status 503 Service Unavailable: system memory overloaded (current: 91.0%, threshold: 90%), url: http://localhost:3000/v1/responses
时好时坏,重启没用。
根因在 middleware/performance.go:SystemPerformanceCheck() 中间件会在每个请求上取一次系统负载,超阈值直接 503(内存那段是 :57-61)。默认阈值定义在 setting/performance_setting/config.go:36-39:CPU 90、内存 90、磁盘 95。我这台机器 15.65 GB 内存常态占用 91.2%(只剩 1.37 GB),采样每 5 秒一次,于是所有中转请求被间歇性拒绝。
有个细节值得注意:router/relay-router.go:71-72 的顺序是
relayV1Router.Use(middleware.SystemPerformanceCheck()) relayV1Router.Use(middleware.TokenAuth())
性能检查排在鉴权前面,意味着不带 key 也能触发这个 503。这既方便了排查(可以匿名探测),也说明这个检查是全局闸门,不是针对某个用户。
解决:后台「系统设置 → 性能设置」把内存阈值调高(我改成 96),或者填 0 关掉该项检查。改完不用重启——model/option.go:190-206 的 SyncOptions 每 60 秒轮询一次数据库并热更新,performance_setting 分支会调 UpdateAndSync() 同步到 common 包。
当然更根本的办法是关掉几个吃内存的程序。阈值调高只是让中转别在你还有 4% 内存的时候就自我熔断。
踩坑二:500 not implemented(Codex 专属)
现象:Codex 里刷
Reconnecting... 1/5 (13s • esc to interrupt) └ We're currently experiencing high demand, which may cause temporary errors
这句「high demand」是 Codex 对任何 5xx 的通用重试文案,跟上游忙不忙毫无关系。 别被它带跑,去看中转站的日志。
我在后台日志里看到的真相是:99 条错误,全部是同一个组合——
model=claude-opus-5, channel_id=2, request_path=/v1/responses, status_code=500, error_code=convert_request_failed, message=not implemented
而同一个 claude-opus-5 走 /v1/chat/completions 是 200。我用四个模型各打一发 /v1/responses 做了对照:
gpt-5.6-sol status=200 "PONG" gpt-5.5 status=200 "PONG" codex-auto-review status=200 "PONG" claude-opus-5 status=500 not implemented
结论:不是本地 New API 的问题,是上游不支持 Responses 协议。
怎么确定是上游而不是本地?三步:
-
本地
New API类型渠道的 Responses 转换是直通的,不可能失败:relay/channel/newapi/adaptor.go:66-68就是return request, nil。 -
上游的错误体会被原样搬运:
service/error.go:116-125解析上游 JSON 错误后调types.WithOpenAIError,而relaykit/types/error.go:317-335直接把上游 body 里的code当成error_code。所以日志里的convert_request_failed/not implemented是上游那台机器吐的字符串,不是本地生成的。 -
上游为什么吐这个?因为它给 Claude 模型配的是 Anthropic 类型渠道,而 Anthropic 适配器的 Responses 转换至今是个 TODO 桩——本地同一份代码就能看到,
relay/channel/claude/adaptor.go:115-118:
func (a *Adaptor) ConvertOpenAIResponsesRequest(...) (any, error) {
// TODO implement me
return nil, errors.New("not implemented")
}
解决办法只有两条:
-
换模型:Codex 的
model改成上游 OpenAI 类渠道下的模型(如gpt-5.6-sol),立刻可用。 -
换中转:找一个自己实现了 responses→claude 转换的中转层,Codex 指向它,这样才能在 Codex 里用 Claude 模型。
顺便说明一个我验证过的死路:New API 里没有 Responses 降级成 Chat 的通道。relay/ 下只有 chat_completions_via_responses.go(方向是 chat→responses),没有反方向;渠道设置里的 force_format 只管响应格式,不管协议转换。所以「在 New API 里让 Claude 走 Responses」是配不出来的,别浪费时间翻设置。
踩坑三:wire_api = "chat" 直接让 Codex 起不来
现象:
Error loading config.toml: `wire_api = "chat"` is no longer supported. How to fix: set `wire_api = "responses"` in your provider config.
新版 Codex 移除了 chat 协议。这意味着上面踩坑二不能通过「把 Codex 降级到 chat 协议」来绕开——虽然 claude-opus-5 在 /v1/chat/completions 上确实是通的(我实测过带 tools 的流式请求,200、6 个 SSE chunk、正常返回内容),但 Codex 已经不让你走那条路了。
如果你改完发现 Codex 起不来,把 wire_api 改回 "responses" 即可恢复。
踩坑四:cc-switch 会覆盖你手改的配置
~/.codex/config.toml 和 Claude Code 的配置如果是交给 cc-switch 管的,那么你手工改的内容在下次切换 provider 时可能被它整个重写(我这次就看到 base_url 和 name 都被它改过)。
要么全部在 cc-switch 界面里改,要么彻底不用它管这个文件。两边同时改,一定会出现「我明明改了却没生效」的灵异现象。
踩坑五:No available channel(分组不匹配)
No available channel for model claude-opus-5 under group vip (distributor)
模型名对、渠道也在线,但令牌的分组和渠道的分组不一致。前面第五节说过了,这里再强调一次,因为报错信息里 under group xxx 这半句非常容易被忽略。看到它就直接去比对令牌分组和渠道分组。
踩坑六:关掉终端服务就没了
Windows 上直接在终端里跑 exe,父进程一死子进程跟着走。用第四节的 Start-Process 方案,或者 NSSM 注册服务。判断是否真的脱离了很简单:把启动它的终端整个关掉,再 Get-Process new-api 看还在不在。
八、日常运维
日志在哪
-
logs\console.log/console.err.log:Start-Process重定向出来的标准输出,启动失败先看这个。 -
logs\目录下的运行日志:--log-dir指定的位置。 -
后台「日志」页:每条请求的模型、渠道、耗时、消耗,以及失败原因。排查请求类问题优先看这里,它比控制台日志结构化得多,能直接看到
request_path、status_code、error_code和上游 request id。
备份
SQLite 部署下,要备份的就两样:
-
data\目录(new-api.db,全部数据) -
.env(特别是CRYPTO_SECRET,丢了渠道密钥全部解不开)
备份前先停服务,避免拷到写入中途的 db 文件。
升级
-
停服务;
-
备份
data\和.env; -
下载新版 exe,校验 SHA256;
-
替换旧 exe(
.env和data\不动); -
启动,看
console.log里数据库迁移是否正常。
卸载
停进程,删目录即可。New API 不写注册表、不装服务(除非你自己用 NSSM 注册过——那要先 nssm remove)。
九、安全提醒(别跳过)
本文全程是 127.0.0.1 本机自用。如果你打算把它挂到公网,至少要做这几件事,否则等于把一个能刷别人余额的接口挂在互联网上:
-
改掉所有默认密码:包括管理员密码,以及走 Docker 时 compose 文件里 PostgreSQL/Redis 那些
123456。 -
SESSION_SECRET和CRYPTO_SECRET必须是随机值,不要抄本文或任何教程里的示例值。 -
加 HTTPS:前面套 Nginx / Caddy 反代,并把
SESSION_COOKIE_SECURE=true打开(同时按注释要求配SESSION_COOKIE_TRUSTED_URL)。 -
配
TRUSTED_PROXIES:不配的话它会信任回环和内网段并打告警;套了反代就把反代网段显式写上,否则日志里记的 IP 全是反代的。 -
关掉注册或者加邀请限制,别让人白嫖你的上游额度。
-
令牌按用途分开建,设额度上限和过期时间,出问题能单独吊销。
另外,中转站的合规性和上游服务条款有关,自建自用和对外提供服务是两回事,这点自己把握。
十、小结
整个过程里真正花时间的不是安装——下载、写 .env、启动加起来不到十分钟。时间全花在两类问题上:
-
一类是被通用错误文案带偏的,比如 Codex 那句「We're currently experiencing high demand」,看着像上游忙,实际是一个 100% 必然失败的协议不兼容;
-
一类是配置项之间的隐式约束,比如令牌分组要匹配渠道分组、模型名必须出现在
/v1/models里、Claude Code 的 base_url 不带/v1而 Codex 的要带、PORT环境变量会盖掉--port。
排查这类问题最有效的顺序是:先看后台「日志」页里的 request_path / status_code / error_code,再决定要不要去看代码。 客户端界面上的报错文案基本没有诊断价值。
环境信息:Windows 10 Home China 19045 | New API v1.0.0-rc.25 | SQLite | 本文所有源码行号对应该版本,不同版本可能有偏移。
免责声明:本文仅记录本机部署过程,涉及的上游服务商地址与密钥均已替换为占位符。请勿将文中示例密钥用于任何实际部署。

葡萄城是专业的软件开发技术和低代码平台提供商,聚焦软件开发技术,以“赋能开发者”为使命,致力于通过表格控件、低代码和BI等各类软件开发工具和服务,一站式满足开发者需求,帮助企业提升开发效率并创新开发模式。
更多推荐
所有评论(0)