Files

6.0 KiB
Raw Permalink Blame History

Northflank 部署 xray / hysteria2(docker-for-ladder)

配套镜像仓库:xyonium/docker-for-ladder (容器内 start.sh <hy2配置路径> <xray配置路径> <cloudflared token>,两个配置文件以 Northflank secret group 的 files 形式挂载)。

协议可行性结论(2026-09 调研)

Northflank 普通 service 端口的公网入口是强制边缘 ingress:TLS 在平台边缘终结, 容器内进程只收到明文 HTTP/1.1 或 H2。这就是"前面必须有个自己的 CDN 反代"的真相—— 不是可选项,是架构本身。

协议 普通端口 付费 L4 Load Balancer
VLESS+REALITY ❌ 不可行(TLS 被边缘终结,xray 看不到 ClientHello;TCP 端口不能公开) ✅ 可行(L4 纯 TCP 直通、不终结 TLS;REALITY 不需要自己有证书)
Hysteria2(UDP/QUIC) ❌ 不可行(UDP 不能公开) ✅ 可行(UDP 类型 L4 LB;证书用 DNS-01 或自签,HTTP-01 不可行)
XHTTP / WS / gRPC ✅ 可行(免费层即可,官方明确支持 WS/gRPC over HTTP(S)) 不需要

L4 LB 注意:team 级付费资源(metered billing);每个 LB 最多 100 端口,30000-32767 保留不可用;更新配置会重新供给、公网 IP 可能变化(自备域名 A 记录跟进); 代理流量计 egress($0.06/GB)。

依据:

xray:XHTTP(唯一免费路径,推荐配置)

xray-config.template.json 按 vpsetup 最优实践编写,与 VPS 版的关键差异:

  • security: "none":TLS 由 Northflank 边缘终结,容器内必须明文 HTTP,不要再开 TLS/REALITY
  • listen: 0.0.0.0:平台 router 要连进来,不能绑 127.0.0.1
  • 客户端 flow 必须留空:xtls-rprx-vision 依赖裸 TCP,HTTP 传输下不可用
  • XHTTP mode: auto + extra xPadding(queryInHeader/tokenish):服务端 extra 必须与 客户端链接的 extra= 参数逐字节一致(vpsetup commit 4e4d0f4 的部署形态; 服务端单方面加 padding 会让所有客户端 400——commit 15d91b2 的教训)

占位符替换:__XRAY_UUID__(xray uuid 生成,固定下来不要重启重新生成)、 __XHTTP_PATH__(随机长串,不含斜杠)、__XPADDING_HEADER__/__XPADDING_KEY__ (如 X-a1b2 / _c3d4)。容器内监听端口(模板 8443)必须与 service 端口配置里 public 端口的 internalPort 一致;公网入口只保留这一个 public HTTP 端口即可—— 实测旧 template 把 REALITY inbound 挂在 private 443 上(private + 边缘终结 TLS, 双重失效),优化时已连同该端口一并移除。

客户端链接模板(path 和 extra 都要 URL-encode):

vless://__XRAY_UUID__@__PUBLIC_DOMAIN__:443?encryption=none&security=tls&sni=__PUBLIC_DOMAIN__&fp=chrome&type=xhttp&path=%2F__XHTTP_PATH__&mode=auto&extra=%7B%22xPaddingObfsMode%22%3Atrue%2C%22xPaddingMethod%22%3A%22tokenish%22%2C%22xPaddingPlacement%22%3A%22queryInHeader%22%2C%22xPaddingHeader%22%3A%22__XPADDING_HEADER__%22%2C%22xPaddingKey%22%3A%22__XPADDING_KEY__%22%7D#nf-xhttp

__PUBLIC_DOMAIN__ 是 Northflank 给端口分配的 *.code.run 域名或自定义域名 (可在 service 端口页查看)。客户端侧:ALPN 用 http/1.1 最稳;XHTTP 的 H3 模式 不可用(边缘无 UDP);若给 subdomain 开了 Northflank CDN(Fastly),客户端↔Fastly 可 H3,Fastly↔源站仍 H2。

WS 兼容:WS 已被 xray 官方弃用(26.x 启动即告警)。如必须兼容旧 WS 客户端, 在配置里加一个 WS inbound(network: "ws" + wsSettings.path),并在 Northflank service 上加第二个端口映射(独立 internalPort)。新客户端一律用 XHTTP。

hysteria2(可选,需 UDP L4 LB)

hysteria-config.template.yaml:占位符 __HY2_DOMAIN__ __EMAIL__ __CF_API_TOKEN__ __HY2_PASSWORD__。注意容器里 ACME 只能走 DNS-01 (80/443 归边缘),或用自签 + 客户端 insecure=1。不开 UDP L4 LB 时 hy2 端口 公网不可达,但配置留着无害(start.sh 会正常拉起,仅项目内网可见)。

healthcheck:写进 template,不要在 service 级加

service 级的 health check 会在下次 template 同步时被覆盖。正确做法: team → templates → scilad → edit as code,找到 erepr-docker-for-ladder 的 DeploymentService 节点,在其 spec 里加(字段约束见 OpenAPI:protocol 枚举 HTTP/CMD/TCP, periodSeconds 最小 10):

"healthChecks": [
  {
    "protocol": "TCP",
    "type": "livenessProbe",
    "port": 8443,
    "initialDelaySeconds": 15,
    "periodSeconds": 30,
    "timeoutSeconds": 5,
    "failureThreshold": 3
  }
]

为什么用 TCP 不用 HTTP:xray 的 XHTTP 端口对未认证 GET 返回非 2xx(实测 404), HTTP 探针会误判失败;TCP 探针只验证"端口在监听",与代理协议无关。 hy2 的 UDP 端口无法被探测(Northflank 无 UDP 探针)——也不需要:start.sh 用 wait -n 等所有后台进程,任一进程(xray/hysteria/cloudflared)退出容器即退出, 平台自动重启,进程级守护已由入口脚本覆盖。

其他注意事项

  • egress 计费:代理流量即出站流量,$0.06/GB,免费层也不例外
  • secret group 里 secrets.files 挂配置文件;uuid/密码等敏感值建议放模板 argumentOverrides(${fn.randomSecret(...)} 生成后固定,重跑不换)而非模板正文
  • 镜像里还有 cloudflared(start.sh 第 3 参):可作为 CF Tunnel 备用入口, 同样只承载 HTTP(S),REALITY/hy2 依然不行