Skip to content

部署三个 Cloudflare Worker 站

控制台、对等门户、首页都是 Git 关联的 Cloudflare Worker:push 到默认分支即自动 构建部署,本地不跑 wrangler deploy

授权界面不在此列,见 deploy-auth.md

日常部署

bash
npm run check          # i18n + 三个站的类型检查,必须全绿
npm run build          # 四个站全建,确认无构建错误
git push

push 之后按 watch paths 触发对应项目的构建。改了 ui/ 会同时触发三个——这是有意 的,共享库变更本来就该让三个站一起重建。

⚠️ 改了 ui/ 之后授权界面不会被触发,要手工重建投放。

三个项目的构建配置

三个 Worker 各自连同一个仓,靠构建配置区分(Cloudflare 官方支持 monorepo)。

controlpeeringhome
Worker 名dn42-control-webuidn42-peering-webuinatlan-io-home
Root directory仓根仓根仓根
Build commandnpm run build:controlnpm run build:peeringnpm run build:home
Deploy commandnpx wrangler deploy -c apps/control/wrangler.jsonc…apps/peering/wrangler.jsonc…apps/home/wrangler.jsonc
Build watch pathsapps/control/* + ui/*apps/peering/* + ui/*apps/home/* + ui/*

Root directory 必须是仓根——依赖装在根上。

wrangler.jsonc 是事实源

三份配置都必须保留在仓里。缺了它,wrangler deploy 会启动自动配置向导, 而那个向导在构建沙箱里把构建脚本改写成 wrangler types --check && vite build, 然后在一个从不存在的类型文件上失败(纯静态站没有 bindings)。

配置里几项容易被误删的:

配置出现在作用
workers_dev: false三份关掉 *.workers.dev 子域。实测过不关时 dn42-control-webui.<sub>.workers.dev 会原样发出登录页(CSP 头都在,确实是本 Worker)
assets.not_found_handling: "single-page-application"control / peeringSPA 回退。不要改用 _redirects——Workers 资产会把它判成重定向死循环
assets.run_worker_first: ["/*", "!/_app/*"]control文档过 Worker 拿 CSP nonce,内容哈希产物直供
main: ./worker/index.jscontrol盖 nonce 的薄壳 Worker
routes: [{pattern: "peering.natlan.io", custom_domain: true}]peering自定义域写在配置里,每次构建重新声明
ruleshome把 html / svg / geojson / bundle.js 当文本模块、jpg 当数据模块打包
observability三份这份文件是每次部署的事实源,面板上手动改的这几项会被 CI 覆盖

自定义域

三个域的绑定方式不统一:

  • peering.natlan.io 写在 wrangler.jsoncroutes 里,随每次构建重新声明。
  • console.natlan.ionatlan.io 由账号侧的 Workers 自定义域承载, 不在配置文件里。

首页裸域的绑定调用:

PUT /accounts/{account}/workers/domains
  { "zone_id": "…", "hostname": "natlan.io",
    "service": "natlan-io-home", "environment": "production" }

给一个已有外部 DNS 记录的主机名挂 Worker 自定义域会被 Cloudflare 拒绝 (Hostname … already has externally managed DNS records)。把「删 A 记录」与 「PUT domains」放进同一次 API 调用,可以把无 DNS 的空窗压到最小。

部署前必须确认的 zone 设置

控制台发 CSP,因此 natlan.io zone 上这两项必须是 off

设置为什么
Rocket Loader它会改写页面上的 <script> 标签并注入一个没有 nonce 的脚本,CSP 必挂
Auto Minify (HTML)它改写内联脚本字节。nonce 对此免疫,但历史上的哈希方案就是被它打掉的

详见 reference/csp.md

部署后验收

bash
# ① 站点可达且是本 Worker(CSP 头存在)
curl -sI https://console.natlan.io/ | grep -iE 'content-security-policy|cache-control'

# ② 逐请求 nonce 互不相同
for i in 1 2 3; do curl -sI https://console.natlan.io/ | grep -io "nonce-[a-f0-9]*"; done

# ③ workers.dev 子域已关闭
curl -s -o /dev/null -w "%{http_code}\n" https://dn42-control-webui.<sub>.workers.dev/

# ④ SPA 回退生效(子路由直接访问返回 200 而非 404)
curl -s -o /dev/null -w "%{http_code}\n" https://console.natlan.io/nodes
curl -s -o /dev/null -w "%{http_code}\n" https://peering.natlan.io/peerings

① 应看到 Cache-Control: no-store 与一条含 'nonce-<32 位十六进制>' 的 CSP。 ② 三行必须互不相同——相同说明响应被缓存了。④ 两条都必须是 200

首页另外确认三条静态路径与重定向:

bash
curl -s -o /dev/null -w "%{http_code}\n" https://natlan.io/fleet.js
curl -s -o /dev/null -w "%{http_code}\n" https://natlan.io/world-land.geojson
curl -s -o /dev/null -w "%{http_code} %{redirect_url}\n" https://natlan.io/nodes/hkg1

最后一条应当是 302 指向控制台。

手工部署(应急)

Git 关联失效时仍可本地部署:

bash
npm run build:control
npx wrangler deploy -c apps/control/wrangler.jsonc

首页同理。这是应急手段,正常流程不要用——本地部署绕过了 CI 的检查。