本文记录一次完整的 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_DSNREDIS_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 clonehttps://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-你的令牌" }

三个细节:

  1. Codex 这边的 base_url 要带 /v1,和 Claude Code 正好相反。

  2. wire_api 只能是 "responses"。新版 Codex 已经移除了 chat 协议,填 "chat" 会直接启动失败:wire_api = "chat" is no longer supported(见 openai/codex discussions/7782)。

  3. 因此 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.goSystemPerformanceCheck() 中间件会在每个请求上取一次系统负载,超阈值直接 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-206SyncOptions 每 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 协议。

怎么确定是上游而不是本地?三步:

  1. 本地 New API 类型渠道的 Responses 转换是直通的,不可能失败:relay/channel/newapi/adaptor.go:66-68 就是 return request, nil

  2. 上游的错误体会被原样搬运service/error.go:116-125 解析上游 JSON 错误后调 types.WithOpenAIError,而 relaykit/types/error.go:317-335 直接把上游 body 里的 code 当成 error_code。所以日志里的 convert_request_failed / not implemented 是上游那台机器吐的字符串,不是本地生成的。

  3. 上游为什么吐这个?因为它给 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_urlname 都被它改过)。

要么全部在 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.logStart-Process 重定向出来的标准输出,启动失败先看这个。

  • logs\ 目录下的运行日志:--log-dir 指定的位置。

  • 后台「日志」页:每条请求的模型、渠道、耗时、消耗,以及失败原因。排查请求类问题优先看这里,它比控制台日志结构化得多,能直接看到 request_pathstatus_codeerror_code 和上游 request id。

备份

SQLite 部署下,要备份的就两样:

  • data\ 目录(new-api.db,全部数据)

  • .env(特别是 CRYPTO_SECRET,丢了渠道密钥全部解不开)

备份前先停服务,避免拷到写入中途的 db 文件。

升级

  1. 停服务;

  2. 备份 data\.env

  3. 下载新版 exe,校验 SHA256;

  4. 替换旧 exe(.envdata\ 不动);

  5. 启动,看 console.log 里数据库迁移是否正常。

卸载

停进程,删目录即可。New API 不写注册表、不装服务(除非你自己用 NSSM 注册过——那要先 nssm remove)。

九、安全提醒(别跳过)

本文全程是 127.0.0.1 本机自用。如果你打算把它挂到公网,至少要做这几件事,否则等于把一个能刷别人余额的接口挂在互联网上:

  1. 改掉所有默认密码:包括管理员密码,以及走 Docker 时 compose 文件里 PostgreSQL/Redis 那些 123456

  2. SESSION_SECRETCRYPTO_SECRET 必须是随机值,不要抄本文或任何教程里的示例值。

  3. 加 HTTPS:前面套 Nginx / Caddy 反代,并把 SESSION_COOKIE_SECURE=true 打开(同时按注释要求配 SESSION_COOKIE_TRUSTED_URL)。

  4. TRUSTED_PROXIES:不配的话它会信任回环和内网段并打告警;套了反代就把反代网段显式写上,否则日志里记的 IP 全是反代的。

  5. 关掉注册或者加邀请限制,别让人白嫖你的上游额度。

  6. 令牌按用途分开建,设额度上限和过期时间,出问题能单独吊销。

另外,中转站的合规性和上游服务条款有关,自建自用和对外提供服务是两回事,这点自己把握。

十、小结

整个过程里真正花时间的不是安装——下载、写 .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 | 本文所有源码行号对应该版本,不同版本可能有偏移。

免责声明:本文仅记录本机部署过程,涉及的上游服务商地址与密钥均已替换为占位符。请勿将文中示例密钥用于任何实际部署。

Logo

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

更多推荐