前言
前面我已经把 Nexterm 部署到了 Hugging Face Spaces。但 HF 免费版有一个明显限制:不能直接绑定自定义域名。
最开始的需求很简单,只是想把:
ssh.007666.xyz |
反代到:
jiaknama-nexterm.hf.space |
这个用一个 Cloudflare Worker 就能解决。但很快就出现了新的问题:如果我以后还有很多 Space,每个 Space 都创建一个 Worker,会很麻烦。
所以最后做成了一个通用管理器:
任意子域名 *.007666.xyz |
这样以后新增 Space,只需要在管理页面里加一条映射,不需要再写 Worker。

目标
这个工具要解决几个问题:
- 一个 Worker 管理多个 HF Space 反代。
- 支持
*.007666.xyz这种通配子域名。 - 提供 Web 面板,能增删改查映射。
- 提供 API,方便脚本调用。
- 提供 OpenAPI,让 AI 工具也能调用。
- 保留 WebSocket 支持,避免 Nexterm 终端连接出问题。
最后的管理入口是:
https://spaces.007666.xyz |
反代入口示例是:
https://ssh.007666.xyz -> https://jiaknama-nexterm.hf.space |
整体结构
整个方案只用了 Cloudflare 的几个基础能力:
Cloudflare DNS:配置通配 CNAME。Cloudflare Worker:处理请求转发。Cloudflare KV:保存域名映射。Worker Routes:把子域名流量交给 Worker。
结构大概是这样:
浏览器访问 app.007666.xyz |
KV 里保存的映射类似这样:
{ |
从单用途 Worker 到通用网关
一开始 Worker 里是写死上游域名的:
const UPSTREAM_HOST = "jiaknama-nexterm.hf.space"; |
这适合单个服务,但不适合多个 Space。通用化以后,Worker 不再写死上游,而是根据当前访问的 Host 去 KV 查询。
核心思路是:
const host = url.hostname.toLowerCase(); |
这样 ssh.007666.xyz、demo.007666.xyz、api.007666.xyz 都可以走同一个 Worker。

反代逻辑
普通 HTTP 请求的处理大概分为几步。
1. 改写上游地址
const upstreamUrl = new URL(request.url); |
路径和查询参数不变,只替换域名。
2. 改写请求头
headers.set("Host", mapping.upstream); |
这样上游 HF Space 收到请求时,更像是用户直接访问 *.hf.space。
3. 处理重定向
有些应用会返回 Location: https://xxx.hf.space/...。如果不处理,浏览器会跳回 HF 原始域名。
所以响应里要把 Location 改回自定义域名:
const location = responseHeaders.get("Location"); |
4. 保留 WebSocket
Nexterm 这类终端工具会用 WebSocket。如果 Worker 把 WebSocket 当普通响应处理,终端连接可能会异常。
所以遇到升级请求时,直接返回上游响应:
if ((request.headers.get("Upgrade") || "").toLowerCase() === "websocket") { |
管理面板
管理面板放在:
https://spaces.007666.xyz |
它支持这些操作:
- 新增映射。
- 编辑映射。
- 查看单条映射 JSON。
- 删除映射。
- 测试上游 Space 是否可访问。
- 复制 cURL 调用示例。
登录方式很简单:管理员口令保存在 KV 的 config:adminToken 里。页面登录后会写一个 HttpOnly Cookie,同时前端也可以用同一个口令作为 Bearer Token 调 API。
这里没有做复杂账号系统,因为使用场景比较轻:这是一个个人反代管理面板,不是多用户平台。
API 设计
为了让脚本和 AI 都能调用,我把面板后端整理成标准 REST API。
认证方式:
Authorization: Bearer <ADMIN_TOKEN> |
也支持:
X-API-Key: <ADMIN_TOKEN> |
接口列表:
GET /api/mappings |
新增映射示例:
curl -X POST "https://spaces.007666.xyz/api/mappings" \ |
更新映射示例:
curl -X PATCH "https://spaces.007666.xyz/api/mappings/demo.007666.xyz" \ |
测试上游:
curl "https://spaces.007666.xyz/api/mappings/demo.007666.xyz/probe" \ |
支持 AI 调用
为了让 AI Agent 或支持 Actions 的工具能直接调用,我加了两个入口。
OpenAPI 地址:
https://spaces.007666.xyz/openapi.json |
AI Plugin Manifest:
https://spaces.007666.xyz/.well-known/ai-plugin.json |
还有一个给人看的动作说明:
https://spaces.007666.xyz/api/ai/actions |
这样 AI 工具只要拿到 OpenAPI 和管理员口令,就可以执行类似:
- 查询当前有哪些映射。
- 新增一个 Space 绑定。
- 修改某个绑定。
- 删除不需要的绑定。
- 测试某个上游是否可访问。

这里要注意:AI 能调用不代表应该完全放权。管理员口令权限很高,最好只放在可信 Agent 的密钥管理里,不要写进提示词。
部署方式
这次没有使用本地 Wrangler 登录部署,而是直接走 Cloudflare REST API。原因是手头已有 Cloudflare API 凭据,用 API 部署更直接。
部署脚本做了这些事:
- 查找
007666.xyz对应的 Zone。 - 创建或复用 KV namespace。
- 上传 Worker 模块。
- 写入默认映射。
- 创建通配 DNS。
- 配置 Worker Routes。
- 保留已有管理员口令,避免升级时把自己锁在门外。
通配 DNS 类似:
*.007666.xyz CNAME jiaknama-nexterm.hf.space |
Worker Route 类似:
*.007666.xyz/* |
这里的 CNAME 目标其实只是为了让 DNS 记录成立,真正转发目标由 Worker 从 KV 中决定。
安全注意事项
这类工具很方便,但也有几个需要注意的点。
1. 不要长期使用 Global API Key
Cloudflare Global API Key 权限太大。临时用来部署可以,但长期最好换成 scoped API Token。
推荐最小权限大概是:
- Zone DNS 编辑。
- Workers Scripts 编辑。
- Workers Routes 编辑。
- KV Storage 编辑。
2. 管理口令不要写进代码
管理员口令应该放在 KV 或 Secret 里,不要写进 Worker 源码。
部署脚本也要避免每次重新生成口令,否则重新部署一次就可能登录不上。
3. Public Space 仍然是公开服务
Cloudflare 反代只是换了访问域名,不等于给 HF Space 自动加权限。
如果 Space 本身是公开的,那别人知道反代域名后也能访问。真正敏感的应用应该自己做登录鉴权。
4. AI 调用要限制 Token 暴露
OpenAPI 是公开描述,没问题。真正有权限的是 Bearer Token。
不要把管理员口令贴在公开对话、公开仓库或前端代码里。
总结
这个通用反代管理器解决的是一个很具体的问题:我有很多 Hugging Face Space,但不想每个 Space 都单独创建 Worker。
最后的方案是:
通配 DNS + 单个 Worker + KV 映射 + 管理面板 + REST API + OpenAPI |
现在新增一个 Space 绑定,只需要做一件事:打开 spaces.007666.xyz,添加一条 绑定域名 -> hf.space 域名 的映射。
后续如果继续增强,我可能会考虑:
- 支持自定义根域名,而不只限于
*.007666.xyz。 - 给每条映射加启用/禁用开关。
- 增加访问日志或最近探测状态。
- 给 AI 调用单独生成低权限 Token,而不是复用管理员口令。