Skip to content

部署联邦网关 ​

自建 Halo 联邦网关,让不在同一局域网的电脑也能组成数字人团队:用单个程序或 Docker 部署,配好 HTTPS,再在每台电脑的远程访问设置里填上网关地址。

网关装在你自己的服务器上,Halo 不能替你部署;AI 也改不了 远程访问 里的设置,填地址这一步要你自己点。

什么时候需要联邦网关 ​

跨电脑团队 默认走局域网:同事的电脑直接连到创建团队那台电脑的远程访问服务。只有成员分散在不同网络时,才需要联邦网关在中间转发。

你的情况用什么
所有电脑在同一个局域网(同一间办公室、同一个 Wi-Fi)打开 远程访问 就够了,不用网关
有成员在家、在另一个城市,或在另一个公司网络里部署联邦网关,并在电脑上填写它的地址
创建团队的电脑 IP 经常变,邀请链接老是失效部署联邦网关:经网关发出的邀请链接指向网关,不随这台电脑的 IP 变化

用了网关之后,发邀请的电脑不再需要开着远程访问服务,它会主动连到网关。

官方版没有内置网关

从官网下载的 Halo 不带默认网关地址,设置 › 远程访问 › 联邦网关 下面显示「如团队仅限局域网内使用,请留空。」,所以跨网络使用要自己部署一个。公司提供的 Halo 可能已经内置网关,这时会显示「正在使用内置网关」和它的地址,你不用再部署。

网关能看到什么 ​

联邦网关是一个独立的小服务,只做转发:每个团队在网关上对应一个「房间」,创建团队的电脑是房间的中心,其他电脑的消息经网关转给它。网关只读每条消息外层的路由信息,不解析里面的业务内容,也不写入磁盘。

项目网关的处理
团队内容(消息、任务、文件内容)经过网关转发,网关不解析、不写入磁盘。Halo 没有在网关这一层再加密内容,所以传输安全靠 HTTPS / WSS(见 配置 HTTPS)
每台电脑的身份每台电脑用自己的设备密钥(Ed25519)签名一次性挑战来证明身份。网关只认这个身份,没有自己的账号和密码
邀请链接里的令牌加入时会经过网关,但网关无法校验它,由团队里的电脑自己校验。网关也不能签发邀请
路由信息团队 ID、各电脑的身份、谁发给谁、连接来源 IP
地址目录创建团队的电脑会向网关登记自己的 Halo 地址(有的话)和显示名,带签名,90 秒内不刷新就过期
状态存储全部在内存里,不写磁盘。重启网关只丢失临时的转发状态,电脑会自动重连

诊断追踪会记录消息正文

网关配置里的 room.trace 默认是空(关闭)。填上某个团队 ID 或 * 后,网关会把该团队(或所有团队)每一帧连同正文写进日志,其中有成员的消息文字。只在排查某个问题时打开,查完立刻关掉。

邀请链接本身就是加入凭证:「任何拥有此链接的人都可以将数字人带入该团队。」网关能看到经过它的邀请令牌,所以网关应由你自己或你信任的管理员运行。Halo 整体的数据流向见 安全、隐私与数据流。

开始之前 ​

  • 一台所有成员电脑都能访问到的服务器(Linux 或 macOS),能开放一个端口,默认 3100
  • 构建工具二选一:Go 1.24 和 make(单个程序),或 Docker
  • 一个域名和 TLS 证书,例如 gateway.example.com;或者一个已有的反向代理(nginx、Caddy、Traefik)
  • Halo 的源码。网关的源码在 Halo 源码仓库的 gateway 目录里

源码在 GitHub 上的 Halo 仓库,切到与你的 Halo 版本一致的标签(例如 v3.0.4)再构建。

部署网关 ​

网关目前只支持中继模式(mode: relay)。配置里写 mode: authority 会直接报错,拒绝启动。

方式一:单个程序 ​

  1. 在服务器上进入源码的 gateway 目录,构建并启动:

    bash
    cd gateway
    make build
    ./dist/halo-gateway -listen :3100

    程序生成在 dist/halo-gateway,默认监听 :3100,同一个端口同时提供 HTTP 和 WebSocket。

  2. 需要给别的平台构建时,运行 make cross,会生成 linux-amd64、linux-arm64、darwin-arm64 三个版本,在 dist/ 下。

方式二:Docker ​

  1. 在 gateway 目录构建镜像并运行:

    bash
    cd gateway
    make docker VERSION=dev
    docker run -d --name halo-gateway -p 3100:3100 halo-gateway:dev

    make docker 会把镜像标记为 halo-gateway:<版本号>,不写 VERSION 时版本号取自 git 标签。写上 VERSION=dev,镜像名就和下一行的 halo-gateway:dev 对上。

  2. 镜像基于 distroless/static,以非 root 用户运行,对外暴露 3100 端口。

确认网关在运行 ​

在任意一台成员电脑上打开 http://gateway.example.com:3100/healthz(配好 HTTPS 后换成 https:// 地址)。返回 200 就说明网关在服务。

地址用途
GET /healthz存活检查,进程在服务时总是返回 200
GET /readyz就绪检查,关停排空时返回 503
GET /version构建信息(JSON)
GET /metricsPrometheus 格式的指标,没有登录保护,不想公开就在反向代理上拦掉
GET /wsHalo 电脑连接用的 WebSocket
GET /、GET /invite邀请落地页

收到 SIGTERM 或 SIGINT 时,网关先把 /readyz 切到 503,关闭所有连接后退出,最多等 10 秒。电脑会按退避策略自动重连,所以滚动重启是安全的。

修改配置 ​

配置按这个顺序生效:命令行参数 > HALO_GW_* 环境变量 > YAML 文件 > 默认值。YAML 文件可选,源码里的 config.example.yaml 列出了每一项和它的默认值,用 -config 指定:

bash
./halo-gateway -config /etc/halo/gateway.yaml
HALO_GW_LISTEN=:8443 HALO_GW_LOG_FORMAT=text ./halo-gateway
参数环境变量默认值作用
-listenHALO_GW_LISTEN:3100HTTP 和 WebSocket 的监听地址
-configHALO_GW_CONFIG—YAML 配置文件路径
-tls-cert / -tls-keyHALO_GW_TLS_CERT / HALO_GW_TLS_KEY—由网关直接提供 TLS
-log-levelHALO_GW_LOG_LEVELinfodebug、info、warn、error
-log-formatHALO_GW_LOG_FORMATjsonjson 或 text

只能在 YAML 里改的限制项(默认值):

配置项默认值含义
limits.maxFrameBytes8388608(8 MiB)单帧上限,超过就断开对方
limits.connPerIPRate / limits.connPerIPBurst10 / 20每个来源 IP 每秒新建连接数 / 突发上限
limits.sessionFrameRate500每个已认证连接每秒最多转发的帧数
room.hostRetention5m创建团队的电脑断开后,房间保留多久等它回来
room.admissionTimeout60s待加入的成员要在这段时间内被放行
directory.ttl90s地址目录条目不刷新就过期

配置 HTTPS ​

成员电脑通常要经过公网连到网关,团队内容在网关这一层没有额外加密,所以请给网关配上 HTTPS(WebSocket 随之变成 WSS)。网关不配证书时只提供普通 HTTP。有两种做法:

网关直接提供 TLS:在 YAML 里填 tls.cert 和 tls.key,或者用参数,然后开放端口。

bash
./dist/halo-gateway -listen :3100 -tls-cert <CERT_FILE> -tls-key <KEY_FILE>

<CERT_FILE> 和 <KEY_FILE> 换成你的证书和私钥文件路径。这时网关地址是 https://gateway.example.com:3100。

放在反向代理后面(nginx、Caddy、Traefik):在代理上终止 TLS,再用普通 HTTP 转给网关。代理要满足这几条:

要求原因
/ws 支持 WebSocket 升级Halo 电脑通过 /ws 连接网关
读取 / 空闲超时大于 90 秒连接靠每 30 秒一次的保活 ping 维持,超时太短会被代理断开
不缓冲、不把 WebSocket 消息限制在 8 MiB 以下网关默认的单帧上限是 8 MiB
调高 limits.connPerIPBurst,或改在代理上限流网关按 TCP 来源地址限流,在代理后面所有连接都来自代理的 IP

nginx 的示例写法(按你的站点调整):

nginx
location / {
    proxy_pass http://127.0.0.1:3100;
    proxy_http_version 1.1;
    proxy_set_header Upgrade $http_upgrade;
    proxy_set_header Connection "upgrade";
    proxy_read_timeout 120s;
}

这时网关地址是 https://gateway.example.com。

在每台电脑上填写网关地址 ​

仅桌面版 联邦网关这一栏在 远程访问 设置里,只在桌面版显示;即使远程访问没打开,这一栏也在。

哪些电脑要填:

  • 必须填:发出邀请的电脑,也就是创建团队的那台。它的邀请链接会改成指向网关。
  • 建议都填同一个地址:团队里每台电脑。这样谁都能用它创建团队、发出邀请。加入的电脑按邀请链接里的网关地址去连接。
  1. 打开 设置 › 远程访问,找到 联邦网关。说明文字是「通过网关服务器中继团队协作,让本地网络之外的成员也能加入。」
  2. 在输入框里填网关地址,例如 https://gateway.example.com。支持 http://、https://、ws://、wss://。
  3. 点 保存。按钮变成 已保存,就说明地址存好了。
  4. 重启 Halo。输入框下面写着「重启 Halo 后,网关更改才会应用于现有的团队连接。」

想换回只在局域网用:清空输入框,点 保存,再重启 Halo。

完成

在创建团队的电脑上打开团队的 团队设置 › 邀请,复制链接。链接以 https://gateway.example.com/?office= 开头,就说明邀请已经经过网关。

邀请链接跨网络也能用 ​

把这条链接发给不在同一网络的同事。对方在浏览器里打开,看到网关上的邀请页,点 在 Halo 中打开,就会回到 Halo 的 加入团队 窗口。加入的步骤和权限选择见 跨电脑团队的邀请链接。

填网关之前复制的旧链接仍是局域网地址,请重新打开 邀请 复制一次。

遇到问题 ​

邀请时提示「请在设置中开启远程访问,以便他人加入该团队。」 ​

这台电脑既没有填网关地址,也没打开远程访问。跨网络使用时,在这台电脑上按 填写网关地址 的步骤填好并重启 Halo。

复制的邀请链接还是局域网地址 ​

保存网关地址后没有重启,或者用的是之前复制的链接。重启 Halo,再从 团队设置 › 邀请 复制一次。

同事加入时看到「无法加入团队。请检查链接,并确认邀请你的人在线。」 ​

  1. 创建团队的电脑要开着 Halo,并且能连上网关。
  2. 在同事的网络里打开网关的 /healthz,确认能访问到网关。
  3. 确认同事用的是以网关地址开头的新链接。

提示「该团队要求所有成员将 Halo 更新至最新版本」 ​

团队里的电脑版本不一致。团队中也可能显示「(团队名)需要更新」或「正在等待(成员名)更新」。在每台电脑上打开 设置 › 关于 › 检查更新,把 Halo 升到同一个最新版本。

成员显示「离线」 ​

每台电脑每 2 秒报一次在线状态:6 秒没消息算暂时离开(「似乎暂时离开了——回复可能会有延迟」),13 秒没消息算离线。常见原因是对方关了 Halo、电脑睡眠、网络断开,或网关在重启。网关恢复后电脑会自动重连,团队里会提示「自动重新连接——工作从上次中断处继续。」创建团队的电脑离线时,其余在线电脑会自动接管团队记录,但那台电脑上的数字人要等它回来才能干活。

放在反向代理后面,连接隔一会儿就断 ​

检查代理是否支持 /ws 的 WebSocket 升级,读取 / 空闲超时是否大于 90 秒,见 配置 HTTPS。

很多电脑同时连接时被拒 ​

网关在代理后面时,所有连接看起来都来自代理的 IP,会触发按 IP 的限流。/metrics 里的 halo_gw_rate_limited_total 会增长。调高 limits.connPerIPBurst,或改在代理上限流。

下一步 ​

基于 MIT 协议开源 · Open source under the MIT license