为什么需要 Headroom?
直接使用 new-api 已经可以对外提供 OpenAI 兼容接口,但在生产环境中,我们通常希望增加一层智能代理层,获得以下能力:
- 请求优化与智能重试
- 常见请求缓存
- 速率限制与配额控制
- 详细监控(按路径、模型、Token 使用量、延迟、成本)
- 美观的 Dashboard 可视化
最终目标链路:
客户端
↓
Cloudflare Tunnel
↓
Nginx Proxy Manager
├── / → new-api:3000 (Web 管理界面)
└── /v1/ → headroom:8787 → new-api:3000 (所有 API 请求)
1. 核心原则:Docker 网络通信
这是整个部署中最容易出问题的地方。
必须遵守以下规则:
headroom、new-api、nginx-proxy-manager以及cloudflared必须加入同一个 Docker 网络(推荐使用 1Panel 的1panel-network)- 严禁在容器间使用
127.0.0.1通信! - 同网络内统一使用容器名访问:
http://headroom:8787http://new-api:3000
⚠️ 错误示例
这会导致容器无法互相访问。
✅ 正确写法
💡 原因:容器内的 127.0.0.1 只指向自己,不是宿主机或其他容器。2. 部署 Headroom
推荐使用 1Panel Docker 应用或 Compose 部署。
推荐生产配置(不映射宿主机端口)
services:
headroom:
image: ghcr.io/chopratejas/headroom:latest
container_name: headroom
restart: unless-stopped
networks:
- 1panel-network
environment:
HEADROOM_HOST: "0.0.0.0"
HEADROOM_PORT: "8787"
OPENAI_TARGET_API_URL: "http://new-api:3000"
HEADROOM_TELEMETRY: "off"
expose:
- "8787"
command: ["--host", "0.0.0.0", "--port", "8787"]
networks:
1panel-network:
external: true
需要局域网访问 Dashboard 时再加端口映射
ports:
- "18787:8787"
访问地址:http://服务器IP:18787/dashboard
⚠️ 重要提醒command字段不要写成["headroom", "proxy", ...],镜像入口已经自带headroom proxy,重复写入会导致启动失败。
3. Nginx Proxy Manager 配置
3.1 创建主 Proxy Host(保留 new-api Web UI)
| 设置项 | 推荐值 | 说明 |
|---|---|---|
| Domain Names | api.asaqe.site |
你的 API 域名 |
| Scheme | http |
- |
| Forward Hostname / IP | new-api |
容器名 |
| Forward Port | 3000 |
new-api 默认端口 |
| Websockets Support | 按需开启 | SSE 场景建议先关闭测试 |
| Access List | Public |
- |
这条规则负责处理根路径,让 new-api 的 Web 管理界面正常访问。
3.2 添加 Custom Location(让 API 请求走 Headroom)
在主 Proxy Host 中添加 Custom Location:
- Location:
/v1/ - Scheme:
http - Forward Hostname / IP:
headroom - Forward Port:
8787
配置完成后效果:
/→ new-api:3000(Web UI)/v1/chat/completions→ headroom:8787/v1/responses→ headroom:8787- 其他
/v1/*路径全部走 Headroom
3.3 Custom Location 高级配置(支持流式响应关键)
点击 Custom Location 右侧齿轮 → Advanced,粘贴以下内容:
proxy_http_version 1.1;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header Connection "";
proxy_buffering off;
proxy_request_buffering off;
proxy_cache off;
gzip off;
add_header X-Accel-Buffering no always;
proxy_connect_timeout 60s;
proxy_read_timeout 7200s;
proxy_send_timeout 7200s;
send_timeout 7200s;
client_body_timeout 7200s;
client_max_body_size 100m;
关键参数说明:
proxy_buffering off+X-Accel-Buffering no:防止 SSE 流式响应被缓冲- 超长超时(7200s):适应 Codex / Responses API 长思考场景
Connection "":避免错误添加upgrade头导致流式中断
⚠️ 注意
主 Proxy Host 的 Advanced 里不要手写location块,否则会和 NPM 自动生成的配置冲突。
4. Cloudflare Tunnel 配置(最容易踩坑的地方)
很多部署失败都是因为这里配置错误。
正确配置方式
在 Cloudflare Zero Trust → Tunnels → Public Hostnames 中添加:
- Hostname:
api.asaqe.site - Service Type:
HTTP - Service URL:
http://1Panel-nginx-proxy-manager-sddo:80
Additional application settings 推荐设置:
- HTTP Host Header:
api.asaqe.site - HTTP2 connection:
Off - Disable Chunked Encoding:
Off
为什么必须这样配置?
如果 Tunnel 直接指向http://new-api:3000,即使 NPM 配置了/v1/分流,请求也会完全绕过 NPM 和 Headroom。
正确链路必须是:
Cloudflare Tunnel → Nginx Proxy Manager → 按 Host + Path 分流 → Headroom / new-api
5. 验证部署是否真正生效
判断是否走 Headroom 的唯一可靠标准:查看 Headroom 的 /stats 接口,而不是响应头。
推荐监控命令
sudo docker exec headroom python -c "
import urllib.request, json
d = json.loads(urllib.request.urlopen('http://127.0.0.1:8787/stats').read())
print('api_requests =', d['summary']['api_requests'])
print('requests_total =', d['requests']['total'])
print('paths =', d['proxy_inbound']['by_path'])
print('models =', d['requests']['by_model'])
"
调用一次 API 后,正常应该看到类似输出:
api_requests = 1
requests_total = 1
paths = {'/v1/chat/completions': 1}
models = {'gpt-5.4': 1}
分层测试(按顺序执行)
① 测试 Headroom 自身健康
sudo docker exec headroom python -c "import urllib.request; print(urllib.request.urlopen('http://127.0.0.1:8787/health').read().decode())"
② 从 NPM 容器测试 Headroom
sudo docker exec 1Panel-nginx-proxy-manager-sddo node -e "
const http = require('http');
http.get('http://headroom:8787/health', r => {
console.log('STATUS', r.statusCode);
r.pipe(process.stdout);
}).on('error', e => console.error('ERROR', e.message));
"
③ 通过域名完整测试 + 验证计数
curl -i https://api.asaqe.site/v1/chat/completions \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "gpt-5.4",
"messages": [{"role": "user", "content": "请只回复 HEADROOM_OK"}]
}'
测试后再次运行 stats 命令,确认 api_requests 和路径计数增加。
6. 常见问题与解决方案
| 问题现象 | 根本原因 | 解决方案 |
|---|---|---|
Headroom 启动报错 extra arguments |
command 重复写了 headroom proxy |
改为 command: ["--host","0.0.0.0","--port","8787"] |
| 容器间无法通信 | 使用了 127.0.0.1 |
全部改用容器名(如 headroom) |
| 请求没有经过 Headroom | Cloudflare Tunnel 直接指向 new-api | 改为指向 NPM 的 80 端口 |
| SSE / Responses API 流式断流 | Nginx 缓冲或超时设置不当 | 使用本文提供的 Advanced 配置 |
| Dashboard 打不开 | 访问路径错误 | 必须访问 /dashboard 结尾 |
ports 格式错误 |
写了字符串而非 YAML 列表 | 正确写法:ports: ["18787:8787"] |
7. 安全加固建议
- Dashboard 不要裸露公网
- 建议创建独立子域名
headroom.asaqe.site - 使用 Cloudflare Access 或 NPM Access List 做身份验证
- 不要长期暴露
18787端口
- 建议创建独立子域名
- API Key 管理
- 测试 Key 用完立即删除
- 生产环境使用 new-api 的权限控制
- 域名分离推荐
api.asaqe.site:对外提供 API(公开)headroom.asaqe.site:仅 Dashboard(受保护)
8. 最终推荐架构
Cloudflare Tunnel
↓
Nginx Proxy Manager
├── api.asaqe.site /
│ → new-api:3000 (保留 Web UI)
│
├── api.asaqe.site /v1/
│ → headroom:8787 → new-api:3000 (智能代理层)
│
└── headroom.asaqe.site /
→ headroom:8787 (Dashboard,建议加访问控制)
客户端配置:
Base URL: https://api.asaqe.site/v1
API Key : new-api 中创建的 Key
Model : gpt-5.4(或其他已上线模型)
9. Python 调用示例
from openai import OpenAI
client = OpenAI(
base_url="https://api.asaqe.site/v1",
api_key="sk-你的new-api-key"
)
response = client.chat.completions.create(
model="gpt-5.4",
messages=[
{"role": "user", "content": "请用一句话介绍 Headroom 的作用。"}
],
)
print(response.choices[0].message.content)
总结
通过 Cloudflare Tunnel + Nginx Proxy Manager + Headroom 的组合,我们成功为 new-api 增加了一层强大且可观测的智能代理层。
希望这份完整经验总结能帮助到正在搭建自托管 AI API 服务的朋友。