signal online Asaqe Lee --:--:-- UTC reading mode
02 Asaqe.
System Record / Infrastructure Stack 6 min read headroom-new-api-nginx-proxy-manager-bu-shu-wan-zheng-zhi-nan

Headroom + new-api + Nginx Proxy Manager 部署完整指南

用 Cloudflare Tunnel 和 NPM 把 Headroom 接到 new-api,给 OpenAI 兼容接口补上代理、监控和流式优化。

Headroom + new-api + Nginx Proxy Manager 部署完整指南

为什么需要 Headroom?

直接使用 new-api 已经可以对外提供 OpenAI 兼容接口,但在生产环境中,我们通常希望增加一层智能代理层,获得以下能力:

  • 请求优化与智能重试
  • 常见请求缓存
  • 速率限制与配额控制
  • 详细监控(按路径、模型、Token 使用量、延迟、成本)
  • 美观的 Dashboard 可视化

最终目标链路

客户端
  ↓
Cloudflare Tunnel
  ↓
Nginx Proxy Manager
  ├── /          → new-api:3000  (Web 管理界面)
  └── /v1/       → headroom:8787 → new-api:3000  (所有 API 请求)

1. 核心原则:Docker 网络通信

这是整个部署中最容易出问题的地方。

必须遵守以下规则

  • headroomnew-apinginx-proxy-manager 以及 cloudflared 必须加入同一个 Docker 网络(推荐使用 1Panel 的 1panel-network
  • 严禁在容器间使用 127.0.0.1 通信!
  • 同网络内统一使用容器名访问:
    • http://headroom:8787
    • http://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/
  • Schemehttp
  • Forward Hostname / IPheadroom
  • Forward Port8787

配置完成后效果:

  • / → 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 中添加:

  • Hostnameapi.asaqe.site
  • Service TypeHTTP
  • Service URLhttp://1Panel-nginx-proxy-manager-sddo:80

Additional application settings 推荐设置:

  • HTTP Host Headerapi.asaqe.site
  • HTTP2 connectionOff
  • Disable Chunked EncodingOff

为什么必须这样配置?

如果 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. 安全加固建议

  1. Dashboard 不要裸露公网
    • 建议创建独立子域名 headroom.asaqe.site
    • 使用 Cloudflare Access 或 NPM Access List 做身份验证
    • 不要长期暴露 18787 端口
  2. API Key 管理
    • 测试 Key 用完立即删除
    • 生产环境使用 new-api 的权限控制
  3. 域名分离推荐
    • 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 服务的朋友。