部署
反向代理
nginx、caddy、Cloudflare 隧道的完整配置,以及必须注意的四件事。
一键脚本装出来的 hub 只监听 127.0.0.1,公网访问不到——凭证不会在链路上明文传输,
也没有端口需要防火墙。把域名指过来是反向代理的活。
配好之后 hub 的参数一个都不用改。 面板用浏览器地址栏里的地址拼安装命令,
所以你改用 https://hub.example.com 进后台,就能添加节点并拿到 --server https://hub.example.com
的安装命令;会话 cookie 的 Secure 跟着请求的 X-Forwarded-Proto 走。
caddy
证书、X-Forwarded-Proto、WebSocket 都自动处理,一行就够:
hub.example.com {
reverse_proxy 127.0.0.1:28080
}caddyfilecaddy 默认不限请求体大小,所以下面那条 8 MiB 的注意事项对它不适用。
nginx
map $http_upgrade $connection_upgrade { default upgrade; '' close; }
server {
listen 443 ssl;
listen [::]:443 ssl;
server_name hub.example.com;
ssl_certificate /etc/letsencrypt/live/hub.example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/hub.example.com/privkey.pem;
location / {
proxy_pass http://127.0.0.1:28080;
proxy_http_version 1.1;
# 导入备份和上传主题是分片传的,单片 4 MiB,所以这个数只跟分片大小
# 有关,跟数据库多大无关。其余路径 hub 自己卡在 64 KiB。
client_max_body_size 8m;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
# WebSocket:/api/agent/ws 与 /api/ws 是长连接
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $connection_upgrade;
proxy_buffering off;
proxy_read_timeout 1h;
proxy_send_timeout 1h;
}
}nginx顺手把 80 端口跳到 443:
server {
listen 80;
listen [::]:80;
server_name hub.example.com;
return 301 https://$host$request_uri;
}nginxCloudflare 隧道
不用开任何入站端口,纯 IPv4 的机器也能拿到双栈入口——cloudflared 的隧道是出站建立的。
tunnel: <tunnel-id>
credentials-file: /root/.cloudflared/<tunnel-id>.json
ingress:
- hostname: hub.example.com
service: http://127.0.0.1:28080
- service: http_status:404yamlcloudflared tunnel create monitor
cloudflared tunnel route dns monitor hub.example.com
cloudflared service install # 或 cloudflared tunnel run monitorbash在边缘做了路径白名单的话,升级 hub 时记得同步。 新版本加的路由会被上一版的名单挡在外面, 而且 403 来自边缘,hub 侧一行日志都没有。面板用到的全部路径见架构与协议。
四件必须注意的事
1. 转发 WebSocket 头,关掉缓冲,把超时放大
/api/agent/ws(agent 上报)和 /api/ws(浏览器实时推送)都是长连接。
Upgrade / Connection 头没转发、或者读写超时留在默认的 60 秒,症状是节点周期性掉线又自己回来。
2. 请求体上限设 8 MiB,不用更大
导入备份和上传主题都是分片传的:单片 4 MiB,hub 侧单请求硬上限 8 MiB。 所以这个数不随数据库增长——256 MiB 的备份也只是 64 个 4 MiB 的请求。
nginx 默认的 client_max_body_size 1m 连一片都放不过去。被反代拒掉时 413 来自反代,
hub 这边一行日志都没有,所以面板收到 413 会直接把 client_max_body_size 念给你看。
Cloudflare 免费版 100 MB 的上传上限因此也不是天花板,单个请求离它差一个数量级。
3. 透传 X-Forwarded-Proto 和 X-Forwarded-For
- 没有
X-Forwarded-Proto,会话 cookie 拿不到Secure - 没有
X-Forwarded-For,登录限流会按代理地址计数——所有人共用一个桶
hub 取 X-Forwarded-For 的最后一跳,而且只在 peer 本身是本地地址时才采信。
文档里这两种反代都是追加而不是覆盖,所以链尾才是代理真正看到的地址。
本地反代前面再套一层 CDN 时,链尾是边缘的地址,所有访客共用一个限流桶。
那种部署得让边缘自己写客户端地址(Cloudflare 的 CF-Connecting-IP),再由本地反代覆盖
X-Forwarded-For:
proxy_set_header X-Forwarded-For $http_cf_connecting_ip;nginx4. 放行 POST / PUT / DELETE
面板的写操作用到这三个方法。有些默认只放行 GET / HEAD 的 WAF 规则会把整个后台变成只读。
验证
# 面板打得开,且是 https
curl -sI https://hub.example.com/admin | head -1
# WebSocket 能升级(应答 101)
curl -sI -o /dev/null -w '%{http_code}\n' \
-H 'Connection: Upgrade' -H 'Upgrade: websocket' \
-H 'Sec-WebSocket-Version: 13' -H 'Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==' \
https://hub.example.com/api/wsbash面板里能看到「添加节点」并生成不带 --insecure 的安装命令,就说明 TLS 和 X-Forwarded-Proto
都对了——这两件事面板自己会检查,你不用猜。