HaloRelay
FROM FIRST INSTALL TO NEXT RELEASE

从第一次部署,到每一次更新。

按角色准备服务器,先验证一条真实链路,再接入客户。命令在对应 Linux 服务器上执行;本介绍站与面板本体分开部署、独立发布。客户使用已核验的发行包;私有源码中的构建命令只供维护者使用,不在本介绍站目录运行。

ONE COMMAND TO BEGIN

一键安装与日常维护

新原生 Linux 服务器使用下面的已核验入口。先核对发布者提供的脚本 SHA256 与发行公钥指纹;安装脚本会选择面板或 Agent、识别架构并获取匹配的签名发行包。服务器不需要访问 GitHub。

复制一行,按提示安装

公网安装入口尚未就绪

等待发布域名和已核验的安装脚本摘要;暂不提供公网安装命令。

只有运营者配置真实 HTTPS 发布地址和 SHA256 后,上方按钮才启用。命令先下载到私有临时目录,只接受 HTTP 200 且不跟随跳转;SHA256 校验通过后运行。root 用户直接执行,其余用户使用 sudo。需要 Bash、curl、sha256sum;后续签名安装还需 Python 3、OpenSSL、systemd 等依赖。

安装入口无参数运行,交互选择 panel 或 agent,默认使用兼容的 latest。下载 Token 与 Agent Token 按提示隐藏输入;不要把秘密放在网页配置、URL 或命令历史。软件许可证在面板安装完成后登录管理页面激活,不在安装命令中激活。

装好后,输入 halo

sudo halo

sudo halo-manage 是同一维护入口。中文菜单提供状态、启停、更新、回退与卸载;在已安装组件的对应服务器执行。已经是 root 时可省略 sudo。

sudo halo update panel latest
sudo halo update agent 0.6.1
sudo halo rollback panel 0.6.0
sudo halo uninstall agent

升级版本可填 latest、指定 x.y.z,或省略版本使用 latest;版本必须真实存在、签名有效且兼容。回退只使用本机保留的兼容历史,不恢复旧数据库。卸载先显示计划,再要求在本机确认,默认保留数据、配置和证书。先迁移转发业务,再卸载入口、出口或面板。

现有 Docker 部署:当前法国服务器运行的是 0.6.0 私有 Docker 部署;原生 halo 不会直接接管其容器、目录或数据。继续使用该部署自己的 Compose 和固定镜像摘要更新;迁移到原生需单独备份、迁移及验收。发布域名尚未购买配置,上方无可执行公网命令,也尚未完成“官网复制 → 公网安装 → 升级回退”的端到端验收。

01 · 准备服务器

面板建议 2 核 / 2 GB / 20 GB SSD,Agent 小流量建议至少 1 核 / 1 GB。预留日志、备份及多个程序版本所需空间;这些是起步建议,吞吐和并发上限需要压测。

操作系统与依赖

  • Linux x64 或 arm64。新机优先以 Debian 13 或 Ubuntu 24.04 LTS 联调;Debian 12 与 Ubuntu 22.04 LTS 可按依赖核对。
  • Ubuntu 26.04 LTS 为候选兼容目标;Linux 发行版兼容性尚未逐项验收。macOS 程序不能安装到 Linux。
  • 手动面板需要 Node.js 24 LTS,Rust Agent 需要匹配架构与 libc 的程序。离线安装包可携带运行环境,无需目标机编译。
  • Docker 方式需要 Docker Engine 与 Compose v2。SQLite 默认;使用 MySQL 时选择 MySQL 8.4 LTS,并保留独立数据目录。
  • 签名初装需要 Bash、Python 3、OpenSSL(支持 Ed25519)、systemd 与系统 CA 证书;下载/校验工具按离线包准备。
  • nftables / iptables / realm、ICMP Ping 为可选能力,按目标系统安装对应工具与权限。

发行版生命周期:Debian · Ubuntu。

网络、域名与端口

面板用自己的 HTTPS 域名对外提供服务;9810 默认只监听回环地址,由反向代理转发。入口监听端口只按规则放行;出口 TLS 隧道端口只向入口开放。3X-UI 管理接口只向面板开放,落地业务端口优先只向你的出口开放。数据库不必开放公网端口。云安全组与本机防火墙需要分别核对。

02 · 安装控制面板

推荐 Docker 部署面板、systemd 部署 Agent。客户从维护者取得已核验的运行包或签名镜像,无需访问私有 GitHub 源码。商业发行包还需固定许可证服务、公钥与 HTTPS 面板域名,再在管理员界面激活;没有有效许可时管理界面可用,转发暂停。详见下方“商业域名授权”。标注“源码”的方式只供有仓库权限的维护者;首次安装拒绝覆盖已有目录,已有服务器按更新流程处理。

Docker 运行包:默认 SQLite

先导入维护者提供的镜像,核对 HALO_PANEL_IMAGE 为已提供的真实镜像。在面板运行包目录准备权限 600 的 .env,设置首次管理员密码(至少 12 位)、PANEL_URL 为真实 HTTPS 域名;使用反向代理提供证书。

docker compose up -d --no-build

包内 Compose 保留 panel-data 数据卷。首次管理员密码仅用于初始化,已存在数据库时不会覆盖旧账号。

Docker 运行包:MySQL 8.4

.env 另外设置 MYSQL_DATABASE、MYSQL_USER、MYSQL_PASSWORD 与一个不同的 MYSQL_ROOT_PASSWORD。数据库没有映射公网端口。

docker compose -f compose.yaml -f compose.mysql.yaml up -d --no-build

更新时保留 panel-data 与 mysql-data。不要通过删除数据卷解决升级问题。

维护者源码试运行:先在回环地址验证

仅在有权访问的私有面板源码目录运行。安装 Node.js 24 后,使用随源码提供的依赖包,无需 npm 联网;客户生产安装使用签名发行包和独立环境文件。

bash deploy/install-node-dependencies.sh
node --version
read -r -s -p '首次管理员密码(至少 12 位):' HALO_ADMIN_PASSWORD
export ADMIN_USERNAME=admin ADMIN_PASSWORD="$HALO_ADMIN_PASSWORD"
export HOST=127.0.0.1 PORT=9810 PANEL_URL=http://127.0.0.1:9810
node server/main.mjs

上面的交互命令使用 Bash。服务模板为 deploy/halo-panel.service,配置模板为 deploy/panel.env.example。公网 HTTPS 启用后修改 PANEL_URL 与安全 Cookie 设置。

离线部署与“一键”安装

先由联网 Linux 构建机制作与目标架构匹配的完整运行安装包,再把校验值与压缩包上传到目标机。校验后运行安装器,会创建服务目录和服务账号。没有签名 Linux 发布包时,页面不会展示一个伪造的公网安装地址。

sha256sum -c halo-forward-linux-offline.tar.gz.sha256
mkdir halo-offline
tar -xzf halo-forward-linux-offline.tar.gz -C halo-offline
sudo bash halo-offline/install-offline.sh

目标服务器不需要访问 GitHub。Docker 离线包还需目标机已有 Docker 与 Compose v2,导入镜像后按安装器输出的命令启动。升级与首次安装使用不同流程,首次离线安装器拒绝覆盖已有 /opt/halo-forward。

签名初装:从可信管理员接收并核对 install-release.sh 和公开验证证书,上传真实 Linux 组件包与 manifest.json 后,可执行下列安装命令。更新器的发布信任在本机初始化,不要用未核验的网络脚本直接安装。首次 Agent 的令牌、角色和出口证书仍需配置。
sudo bash ./install-release.sh --bundle ./halo-forward-panel-0.6.1-linux-x64.tar.gz --manifest ./manifest.json --public-key ./release-public.pem --component panel --manifest-url https://你的发布域名/releases/manifest.json

上例要求真实签名包已制作并上传;文件名、架构与域名须替换为实际值。安装器一次安装一个组件,已有部署不要重复覆盖。

03 · 部署入口与出口 Agent

分别添加服务器与接入令牌

  1. 在“服务器节点”创建入口和出口,分别填写真实地址与角色;每个节点使用独立 Agent Token。
  2. 上传目标 Linux 架构的 Rust Agent、systemd 模板与配置文件。令牌放在仅服务账号可读的文件中。
  3. 出口配置 TLS 证书、私钥、隧道监听地址和入口允许使用的密钥;入口配置对应的出口地址。
  4. 按安装包实际说明启动 Agent,验证心跳、角色与核心版本上报。入口与出口可以在同机分别配置,或使用双角色。
  5. 建立“入口 → TLS 隧道 → 出口 → 目标”的测试规则,使用真实 TCP / UDP 客户端连接,核对双向返回、用量与日志。

Agent 签名安装

在该 Agent 服务器准备匹配 Linux 架构的真实发布包、可信安装脚本、签名清单和发布公钥。以下以 x64 为例,版本、文件名与域名须换成实际发布资产:

sudo bash ./install-release.sh --bundle ./halo-forward-agent-0.6.1-linux-x64.tar.gz --manifest ./manifest.json --public-key ./release-public.pem --component agent --manifest-url https://你的发布域名/releases/manifest.json

安装器一次初始化一个组件,不覆盖已有 /opt/halo-forward。完成后编辑 /etc/halo-forward/agent.env,配置面板地址、该节点独立令牌、角色与证书;出口或双角色还须让服务启动命令带 --exit。令牌推荐由 AGENT_TOKEN_FILE 读取;不要写入命令历史。配置完成后启动系统服务:

sudo systemctl enable --now halo-agent.service
sudo systemctl status halo-agent.service
sudo journalctl -u halo-agent.service -n 100 --no-pager

核对心跳、真实核心版本与 software_license_lease_v1 许可能力,再测试业务连接。商业面板遇到缺少许可能力的旧 Agent 会暂停该节点转发,升级到 0.6.0 或兼容后续版本后再接入。已有同机面板部署时先按部署指南完成迁移或组件接入。

也可用 Docker 运行 Agent

提供 Linux 主机网络的 compose.agent.yaml 与 deploy/agent.docker.env.example。先准备真实 agent.env 和 agent-secrets 中的令牌 / 出口证书;镜像须已导入、下载,或在联网构建机通过 Dockerfile.agent 构建。

cp deploy/agent.docker.env.example agent.env
chmod 600 agent.env
# 编辑 agent.env,上传实际令牌/证书后执行
sudo chown -R 10001:10001 agent-secrets
sudo chmod 700 agent-secrets
sudo chmod 400 agent-secrets/*
docker compose -f compose.agent.yaml up -d --no-build

容器以 UID/GID 10001 运行,秘密文件只允许该身份读取。出口 / 双角色取消 Compose 的 command: ["--exit"] 注释,并填写 TUNNEL_CERT_FILE、TUNNEL_KEY_FILE 与 TUNNEL_LISTEN。Docker Agent 不运行 root 原生更新器,HALO_UPDATE_ENABLED=0;更新与回退通过签名镜像 SSH 命令重建容器。

TLS 服务器名称与 CA PEM 是什么?

TLS 服务器名称是入口拿来核对出口证书的名字,必须匹配出口证书的 SAN。它可以是你控制的出口域名,不能随便填写别人的域名。

出口证书 CA PEM是签发出口证书的可信 CA 公钥证书,文本通常以 BEGIN CERTIFICATE 开头。入口用它验证出口身份;出口证书私钥只留在出口服务器。使用私有 CA 时把 CA 的公开证书交给入口;不要复制出口私钥到面板字段。

04 · 接入多个 3X-UI 落地

最多接入 32 个独立 3X-UI 2.9.4 面板,每台分别填写根地址、管理账号、凭据与公网地址。不会把所有落地强制放到一台服务器。

  1. 在“授权与集成 → 多个 3X-UI 落地服务器”选择“添加落地服务器”。地址包含你自己的面板登录路径。
  2. 逐台测试连接,再点击某台服务器的“在此服务器创建落地”;创建窗口也可切换所属服务器。
  3. 选择客户、监听端口、REALITY 目标、上游地址、流量额度与期限。接口失败或超时时先核对上游结果,避免重复创建。
  4. 创建成功后可“复制节点”,或“创建入口规则”,让客户通过你的 Rust 入口连接落地。
  5. 按所属服务器筛选落地列表,检查入口链路、客户端握手及流量额度实际生效。

3X-UI / Xray 额度与 HaloRelay 套餐独立。限制落地端口只允许你的出口访问,才能让流量经过 HaloRelay 转发计费。HaloRelay 版本更新不会代替第三方 3X-UI 升级。

05 · 开通客户与套餐

  1. 创建邀请码,设置有效期、使用次数、可用节点与规则数量;邀请码仅显示一次,私下交给客户。
  2. 客户注册并登录后下单;管理员核实人工收款,确认订单并开通订阅。
  3. 在账号或套餐设置节点授权、端口与目标范围,选择单向 / 双向口径与倍率。
  4. 每条转发规则的操作按钮可查看 IP 数量、并发数、限速及访问日志。来源 IP 限制与账号单会话登录是两种独立设置。
  5. 单会话登录打开后,新登录使旧会话失效;多个标签页共享同一浏览器会话,不能用来识别物理设备。

06 · 探针、日志与异常提醒

“链路探测”查看最近时间窗口的延迟与可用性;TCP 显示建连失败率,只有 ICMP 显示网络丢包率。机器探针和规则计费统计口径不同。

在“授权与集成”创建公开探针链接,选择要展示的节点和失效时间。持链接的人无需登录,但看不到服务器 IP、客户规则和访问日志;随时可以撤销。

管理员配置 SMTP 或 Telegram 通道,管理员与客户在“我的账号与提醒”各自填写收件人并发送测试提醒。测试加入队列不等于已送达,应查看投递结果。

在“部署与设置”设置自动保留天数与日志上限,也可手动清理日志。清理不会重置累计计费。SQLite 整理可以回收空闲页;MySQL 统计更新不会缩小磁盘文件。

07 · 备份与恢复

管理员下载“数据库与外观备份”,另外保存 integration-key、Agent Token、隧道私钥、系统服务配置、DATA_DIR/releases、/etc/halo-forward/release.json 与发布公钥。通用业务数据库下载不包含发布源配置、缓存与更新任务。另独立保存许可配置 /etc/halo-forward/license.json 和 DATA_DIR/software-license/state.json;许可状态包含激活码与实例身份,普通业务数据库导出不能替代它。备份包含敏感数据,应保存在受控位置。

恢复时选择本面板导出的文件,输入当前管理员密码并确认。系统先保存恢复前的回滚副本,再替换数据库;完成后所有用户重新登录。跨机恢复需同时恢复集成密钥,或重新填写 SMTP、Telegram、3X-UI 凭据。

不要把程序回退和数据库恢复混为一谈。恢复旧备份会丢失备份之后的订单、规则和计费变化,必须事先确认时间点并保管当前副本。

08 · 发布、在线更新与回退

面板控制台、接口与资源随面板版本整体切换。此介绍站独立部署、独立更新,不包含在面板签名包中;Agent 与第三方 3X-UI 版本也独立维护。

先建立可信发布源与主机更新器

管理员在“版本与更新”配置真实 HTTPS 清单 URL、Ed25519 公钥与部署方式。服务器首次安装时固定发布信任;公钥须通过可信渠道核对,网页填写不能代替服务器上的主机信任。

控制面约每 15 分钟检查签名清单,网页每 10 秒刷新状态。检查只提示可用版本,不自动切换。原生更新器启用并获授权后可在线提交任务,也可复制 SSH 命令;Docker 使用签名镜像命令。halorelay.com 已购买,下载站规划为 dl.halorelay.com;必须先构建并上传资产、配置 HTTPS,示例地址不能直接用来安装。

sudo halofctl status
sudo halofctl capabilities

面板更新:先备份,再选择版本

下载数据库备份,另存集成密钥、配置、发布信任与证书。选择签名清单中兼容的新版本,在线提交或把命令复制到面板服务器 SSH。下例适用于已有较低版本且发布源包含 0.6.1 的原生面板:

sudo halofctl update panel 0.6.1

更新器先备份业务数据,再切换程序;健康检查失败会恢复旧程序。排队、下发与最终执行成功是不同状态。面板重启短暂断开,恢复后查看最终任务状态。Docker 面板使用页面生成的签名镜像摘要命令,固定 HALO_PANEL_IMAGE 后重新创建 Compose 容器并保留数据卷;不能使用原生 halofctl 替换容器。

Agent 更新:先一台,再逐台

复制命令到所选 Agent 对应服务器。原生 Agent 在线、更新器启用且获授权后可接受在线任务;Docker Agent 使用签名镜像 SSH 命令。先更新备用入口或出口,核对版本心跳及真实链路,再逐台更新:

sudo halofctl update agent 0.6.1

更新可能断开业务连接。无需改变核心时可只更新面板;有最低核心版本要求时按签名清单核对兼容性。普通组件更新不会自动改写固定 root 工具、发布公钥或服务器授权配置。

回退:保留旧程序并核对数据格式

在本机历史列表选择已保留、通过摘要校验且与当前数据格式兼容的版本。商业授权发行基线为 0.6.0,只回退到仍具备授权能力的已验证版本。下例用于未来本机当前版本高于 0.6.0 且已保留兼容的 0.6.0 资产;当前就在该版本时无需执行:

sudo halofctl rollback panel 0.6.0
sudo halofctl rollback agent 0.6.0

程序回退不会恢复旧数据库;数据格式不兼容时运行器拒绝切换,应按备份恢复方案处理。不能把回退到 0.6.0 以前的无授权旧版作为商业维护方案。旧 Agent 没有许可能力时,商业面板暂停向它下发转发规则,须升级后再接入。Docker 用保留的签名镜像摘要重建容器,保留 panel-data、mysql-data 和 Agent 秘密挂载。

09 · 卸载面板与 Agent

0.6.0 初装包含 halofctl 1.2.0。先查看计划,再在要卸载的那台 Linux 服务器执行。删除面板节点记录与卸载服务器程序是两件事。旧签名安装先按下节刷新已验证的固定 root 工具;工具因活动任务、安全检查或恢复记录拒绝时,独立脚本不会绕过。

原生面板:保留数据库、配置和同机 Agent

sudo halofctl uninstall panel --dry-run
sudo halofctl uninstall panel

停止并移除本机面板服务、current-panel 链接及全部历史面板程序。保留数据库、日志、账户、集成密钥、备份、panel.env、管理员密码、证书及同机 Agent;没有删除面板业务数据的 purge 选项。传统手动布局仅删除明确的 server、web、node_modules 和包清单,保留共享 runtime、tools、deploy 与 data。

保留 Agent 服务不等于业务不中断:控制面不可用后,Agent 默认在 90 秒控制租约到期时停止转发。迁移或卸载面板前准备并验证替代控制面。业务目录或配置的密钥位于待删程序内,或存在跨服务停机关系、自定义 unit 时,自动卸载拒绝;先核对并迁移配置。

原生 Agent:保留令牌、证书及面板数据

先停止向该入口或出口分配规则,验证备用节点,再到该 Agent 服务器执行:

sudo halofctl uninstall agent --dry-run
sudo halofctl uninstall agent

停止并移除 Agent 服务、current-agent 链接、历史 Agent 程序和旧式二进制。默认保留 Agent 配置、令牌和证书,不删除面板数据库;同机面板及其历史程序保留。远端面板节点记录不会自动删除,需另行撤销令牌并移除记录。

需要清理标准 Agent 配置时才使用:

sudo halofctl uninstall agent --purge-agent-config

只额外删除 /etc/halo-forward/agent.env、agent-token、agent-token.txt,不沿环境变量继续删除自定义令牌、共享 CA、证书或私钥。

中断恢复与共享更新器

卸载与升级共用锁,存在未完成更新或另一组件恢复日志时拒绝并发。卸载中断后重跑同一卸载命令恢复;运行器也可处理原生卸载恢复日志。撤销对应组件更新授权,取消晚到的该组件更新;同机另一组件程序、授权与任务保留。没有剩余组件时停用更新定时器,仍保留固定管理工具和发布信任。

归档只保存路径、摘要与执行元数据,未保存令牌、私钥或数据库,不是完整重装备份。重装须另行核验程序、配置和授权。

旧签名安装:手工刷新固定 root 工具到 1.2.0

程序升级与固定 root 工具维护分开。先用原签名运行器把本机已有的 panel 或 agent 更新到 0.6.0,核对包签名、SHA256、已安装文件及 root 所有权。不能用任意源码解压目录代替已验证发行资产。下列流程只适用于标准 /opt/halo-forward、/etc/halo-forward 和 /var/lib/halo-forward-update 布局。

  1. 记录 halo-updater.timer 原来的启用与运行状态,停止定时器:sudo systemctl stop halo-updater.timer。
  2. 确认 halo-updater.service 未运行、其他 SSH 没有 halofctl 进程,spool 内没有更新锁、pending_activation、卸载恢复日志或未完成任务。存在活动时停止维护,不替换文件。
  3. 把 updater/tools、updater/server、updater/deploy 及现有更新服务 / timer 模板备份到 root 0700 目录。保留 runtime、release.json、发布公钥、下载令牌和证书。
  4. 下面以已验证的 panel 为例;仅有 Agent 的服务器将 HALO_VERIFIED_COMPONENT 改为 agent。逐段检查结果;链接或版本不匹配、文件缺失或能力检查失败时停止,恢复旧工具及模板,daemon-reload 后按原状态恢复定时器。
HALO_VERIFIED_COMPONENT=panel
HALO_VERIFIED_PACKAGE=/opt/halo-forward/releases/0.6.0/$HALO_VERIFIED_COMPONENT
[ "$(readlink -f /opt/halo-forward/releases/current-$HALO_VERIFIED_COMPONENT)" = "$HALO_VERIFIED_PACKAGE" ] || { echo '当前组件不是已核验的0.6.0版本,请停止维护'; exit 1; }
sudo install -m 0644 -o root -g root "$HALO_VERIFIED_PACKAGE/tools/halofctl.mjs" "$HALO_VERIFIED_PACKAGE/tools/release-archive.mjs" "$HALO_VERIFIED_PACKAGE/tools/pre-update-backup.mjs" "$HALO_VERIFIED_PACKAGE/tools/agent-uninstall.py" /opt/halo-forward/updater/tools/
sudo install -m 0644 -o root -g root "$HALO_VERIFIED_PACKAGE/server/release-format.mjs" /opt/halo-forward/updater/server/
sudo install -m 0755 -o root -g root "$HALO_VERIFIED_PACKAGE/deploy/manage.sh" "$HALO_VERIFIED_PACKAGE/deploy/uninstall-agent.sh" "$HALO_VERIFIED_PACKAGE/deploy/uninstall-panel.sh" /opt/halo-forward/updater/deploy/
printf '%s\n' '#!/bin/sh' 'exec /bin/bash /opt/halo-forward/updater/deploy/manage.sh "$@"' | sudo tee /usr/local/bin/halo-manage >/dev/null
sudo chown root:root /usr/local/bin/halo-manage
sudo chmod 0755 /usr/local/bin/halo-manage
sudo install -m 0644 -o root -g root "$HALO_VERIFIED_PACKAGE/deploy/halo-updater.service" "$HALO_VERIFIED_PACKAGE/deploy/halo-updater.timer" /etc/systemd/system/
sudo systemctl daemon-reload
sudo halofctl capabilities

输出必须为 runner_version 1.2.0,且包含 agent_uninstall_v1 和 panel_uninstall_v1。确认后按维护前状态恢复定时器,再查看对应卸载计划。此流程只维护固定工具和服务模板,不改发布公钥、root 信任、业务令牌或证书。

传统手动安装:随包卸载脚本

没有 halofctl 的传统手动布局,在已核验完整运行包根目录保留同包 deploy 脚本与 tools/agent-uninstall.py,再执行:

sudo bash deploy/uninstall-panel.sh --dry-run
sudo bash deploy/uninstall-panel.sh
sudo bash deploy/uninstall-agent.sh --dry-run
sudo bash deploy/uninstall-agent.sh

只执行需移除的组件命令,不必同时卸载两者。版本目录安装必须使用可信更新器;旧签名工具缺能力时,脚本拒绝处理,先按上节维护。Linux 实机卸载仍需演练,本机测试不能替代生产验证。

Docker:仅移除指定容器,保留数据卷

在对应 Compose 目录执行。下面只停止面板,保留数据库容器、panel-data 和 mysql-data;先备份并准备业务迁移:

docker compose stop panel
docker compose rm -f panel

Agent 使用自己的 Compose 文件,保留配置、证书与令牌挂载:

docker compose -f compose.agent.yaml stop agent
docker compose -f compose.agent.yaml rm -f agent

MySQL 叠加部署需加实际部署时使用的 -f compose.yaml -f compose.mysql.yaml 参数。不要给 Docker 服务执行原生 halofctl 卸载,也不要添加删除数据卷的选项。

10 · 上线前检查实际结果

  1. 确认 HTTPS、管理员登录、邀请码注册与权限隔离。
  2. 测试真实入口 / 出口 TCP、UDP、正确和错误证书、客户节点握手。
  3. 验证 IP / 连接 / 速率 / 流量 / 到期限制,与面板账单口径核对。
  4. 从实际 Agent 网络验证探测、日志增长、邮件和 Telegram 投递。
  5. 演练面板与一台 Agent 的安装、更新、回退及保留数据卸载,再演练健康失败恢复和数据库备份恢复。
  6. 记录 CPU、内存、磁盘、并发与吞吐。当前单实例控制面尚未完成高可用验收。

Linux、Docker、真实 3X-UI 与签名发布安装链路需要在你的机器上联调。不要把当前本机测试通过写成云服务器已经部署成功。

11 · 私有双仓库与版本发布站

源码、客户运行包、公共教程分开保存

维护者私有源码仓库:halo798/halo-forward 与 halo798/halo-forward-site。两个仓库为 Private,保存开发源码与提交历史,访问需要维护者授权。本机独立保留源码包和加密备份;每次发布核对远程提交与版本标签,确认推送完成后再视为远程备份可用。

开发源码和提交历史保存在私有 Git 仓库,另留加密备份。客户取得运行发行包或镜像;自有 HTTPS 发布站或对象存储提供签名清单、安装包与保留的历史版本。介绍站仅发布 public/ 中的公开静态资源,不得上传私钥、账户、令牌、完整仓库或客户数据。

下载令牌只限制安装包访问。商业软件许可证由独立服务签发,绑定面板域名,一份授权管理多个 Agent;邀请码和客户套餐用于使用你运营的转发服务。发布签名私钥与许可签名私钥独立保存。Node 面板运行代码仍可读,私有仓库和剔除开发文件不能保证防止分析或复制。

维护者发布下一版

  1. 在对应私有仓库迭代源码、更新版本号与发布说明,完成测试后推送提交与版本标签。
  2. 在可信 Linux 构建机为 x64 / arm64 分别构建面板与 Rust Agent 运行资产,核对许可、签名、摘要和兼容要求。
  3. 先上传新资产,验证下载和摘要,再发布签名 manifest.json。保留旧版本,不以新内容覆盖同一版本摘要。
  4. 面板检查并提示新版本;管理员选择在线提交或复制命令到对应服务器 SSH,先灰度一台、验证结果,再逐台更新。
  5. 介绍站按自己的仓库及静态流程更新,不随面板覆盖;回退可恢复保留的旧静态目录或镜像。

构建机命令模板,不是公网安装地址

下列命令只在有私有源码权限的可信 Linux 构建机运行。首次生成 Ed25519 密钥,私钥权限 600,放在发布输出目录和 Git 仓库之外;后续版本沿用原发布身份,不在普通更新中重新生成密钥。

node tools/publish-release.mjs --init-key /可信构建机/halo-release-private.pem --public-key /可信构建机/halo-release-public.pem
RELEASE_PRIVATE_KEY=/可信构建机/halo-release-private.pem RELEASE_BASE_URL=https://你的发布域名/releases/ bash deploy/build-offline.sh release /可信构建机/publish

输出签名组件包、manifest.json、公开验证公钥与初装脚本。所有示例路径和域名须替换;目前没有可直接运行的公网安装入口。目标服务器可离线接收资产,无需访问 GitHub。

发布工具还生成公开 bootstrap.sh;输出 JSON 的 installation 包含 installerUrl、installerSha256 和 publicKeySha256。运营者核验上传结果后,把前两项写入独立介绍站 public/config.js,发行公钥指纹通过独立可信渠道交付。每次更换 bootstrap.sh,都须同步官网的 installerSha256;摘要不一致时安装停止,不自动接受变化。

Docker 镜像先真实构建并上传,取得 image:tag@sha256:摘要 后,发布器可追加 --docker-panel / --docker-agent 签名引用。发布器不代替镜像构建与上传;源码 ZIP 不是客户安装包。

独立介绍站如何部署?

介绍站源码包 halo-forward-site 与面板源码包 halo-forward 分开保存。本站无需数据库、Agent、客户账号或面板接口权限。修改 public/config.js 中的网站名、图标、背景外链、panelUrl 和 downloadUrl 后,可直接把 public/ 上传到静态网站空间。

本机预览或 Docker 运行

node server.mjs
# 或在介绍站源码目录运行
docker compose up -d --build

默认仅监听 127.0.0.1:9811;生产用自己的介绍站域名和 HTTPS 反向代理。面板的 DOCS_URL 配置指向该独立域名。文档站版本不与面板强制同步;面板升级不会修改本站。法国服务器已有 0.6.0 私有部署,正式生产域名与公网安装流程仍待配置验收。

13 · 自建公网下载站

独立运维服务位于面板项目 deploy/release-site,与静态介绍站和面板分开运行。需要 Node.js 24;建议下载与许可证小规模同机从 2 核 / 2 GB / 40 GB SSD 起步,按历史包和备份增长调整。已有法国服务器 0.6.0 私有部署,halorelay.com 已购买,官网、下载站和许可证服务规划部署在法国发布机,实际面板在另一台服务器安装;下面是待替换模板,不表示公网已上线。

准备发行文件与下载授权

在匹配架构的可信 Linux 构建机制作真实签名包,再上传已验证输出。公开目录只保存 manifest.json、release-public.pem、install-release.sh、脚本摘要与 Linux 程序包;发布私钥仅留构建机。源码 ZIP 不能冒充 Linux 安装包。下列 CLI 在面板项目根目录运行:

sudo install -d -m 0755 /srv/halo-releases/public
sudo install -d -m 0700 /srv/halo-releases/private
sudo node tools/release-access.mjs init --file /srv/halo-releases/private/access.json --public-dir /srv/halo-releases/public
sudo node tools/release-access.mjs issue --file /srv/halo-releases/private/access.json --public-dir /srv/halo-releases/public --name "客户面板下载" --days 30

令牌原文只在签发时显示一次,存私有密码管理器;下载站仅保存 SHA256。令牌到期 / 撤销在下次请求生效,已开始下载可能继续。先将真实发行文件放入 public/,再启动下载服务。公开文件包括 manifest.json、release-public.pem、install-release.sh 及其摘要、bootstrap.sh 及其摘要;程序包仍由下载服务按令牌鉴权,不改为公开静态目录。

Docker + Caddy 公网 HTTPS

sudo chown -R 10001:10001 /srv/halo-releases/private
sudo chmod 0700 /srv/halo-releases/private
sudo chmod 0600 /srv/halo-releases/private/access.json
cd deploy/release-site
cp .env.example .env
chmod 0600 .env
docker compose up -d --build
docker compose ps

检查 .env 的目录与 UID/GID,冲突时使用独立服务账号。修改同目录 Caddyfile.example 为真实下载域名,DNS 指向服务器,合并到已有 Caddy 配置并加载。主机 Caddy 反代回环 9820,不直接开放该端口;容器内 Caddy 须按实际网络修改上游。不要记录敏感请求头,不把服务改为暴露全部文件的静态目录。

清单、公钥和初装脚本公开;程序包要求 Bearer 鉴权且通过有效签名清单、大小与摘要检查。下载上限四个并发、512 MiB 快照预算、单包 256 MiB;留意内存与临时空间。防火墙只开放 SSH、HTTPS 和明确业务端口。

客户核验与更新凭据

通过 0.6.1 bootstrap 一键入口成功安装后,下载令牌已受保护地保存并配置到更新器,无需重复创建。下面只供低层安装或缺失凭据时补配;检查模式和失败安装不保存令牌。

先从独立可信渠道核对安装脚本 SHA256 与公钥 DER 指纹,再执行本地安装器。同站提供的脚本和摘要不能证明独立真实性。下载令牌存 0600 curl 配置文件,避免进入命令参数、URL 或历史;不携鉴权头自动跨站重定向。

sudo install -m 0600 /dev/null /etc/halo-forward/release-download-token
sudoedit /etc/halo-forward/release-download-token
sudoedit /etc/halo-forward/release.json

install 只用于初次创建,已有文件直接编辑,避免清空。保留 release.json 原有配置,新增 auth_token_file 指向此文件。固定更新器只向同源程序包发 Bearer;公开清单不需要下载令牌。status 只看本机状态,不证明网络已通过。

14 · 商业软件:绑定面板域名

一份许可证绑定一个完整面板域名,可管理多台 Agent,并限制 Agent / 规则数量。软件许可、下载令牌和客户套餐分别管理;发布签名私钥和许可签名私钥独立保存,介绍站不读取任何私有数据。

运营者初始化与签发

在许可证服务器、面板项目根目录运行,需要 Node.js 24。所有 example.com 地址都须替换。私有目录禁止放进 Git 或公网目录,客户只取得公开公钥与激活码:

sudo install -d -m 0700 /srv/halo-license/private
sudo node tools/license-admin.mjs init --dir /srv/halo-license/private --issuer-url https://license.example.com
sudo node tools/license-admin.mjs issue --dir /srv/halo-license/private --name "客户A" --domain panel.customer.example.com --days 365 --max-agents 10 --max-rules 1000

初始化返回独立公钥、指纹与客户配置模板。激活码只显示一次,数据库仅存哈希。域名不含协议、端口、路径、查询串或通配符;子域名是独立绑定值。客户 PANEL_URL 使用该域名的 HTTPS 地址。

独立许可服务 Docker 部署

sudo chown -R 10001:10001 /srv/halo-license/private
sudo chmod 0700 /srv/halo-license/private
cd deploy/license-site
cp .env.example .env
chmod 0600 .env
docker compose up -d --build
docker compose ps

核对目录和 UID/GID。同目录 Caddy 模板使用独立许可域名,HTTPS 反代主机 127.0.0.1:9830,不开放内部端口。服务没有公网发码管理 API,维护者在受信任 SSH 中维护许可。先保管私钥与一致性数据库备份再升级,不能在每次启动重新创建签发身份。

续期、撤销与改绑

在许可证服务 Compose 工作目录操作,编号、时间与域名必须换成真实值:

docker compose run --rm --no-deps license-site node tools/license-admin.mjs list --dir /private
docker compose run --rm --no-deps license-site node tools/license-admin.mjs renew --dir /private --id 从列表取得的UUID --until 2027-10-05T00:00:00.000Z
docker compose run --rm --no-deps license-site node tools/license-admin.mjs revoke --dir /private --id 从列表取得的UUID
docker compose run --rm --no-deps license-site node tools/license-admin.mjs rebind --dir /private --id 从列表取得的UUID --domain new-panel.customer.example.com

正常约 15 分钟刷新签名许可;网络不可达时旧租约最长有效 72 小时,并受许可证到期时间约束。撤销和改绑在联网刷新时生效,旧离线租约可能持续至窗口结束,不能承诺立即断开全部离线机器。错误状态不能无限延长旧许可。

客户面板激活

原生安装用 sudoedit 修改 /etc/halo-forward/panel.env 的 HTTPS PANEL_URL 与 SECURE_COOKIES=1。root 固定 /etc/halo-forward/license.json,权限 root:halo-forward 0640;使用初始化输出的 issuer_url 和 public_key_pem。这是许可公钥,不是发行公钥,客户不取得私钥:

sudo install -m 0640 -o root -g halo-forward /dev/null /etc/halo-forward/license.json
sudoedit /etc/halo-forward/license.json
sudo systemctl restart halo-panel.service

install 只用于新配置文件,已有文件直接编辑。进入管理员软件授权页面激活,核对域名、期限、Agent / 规则上限与最近刷新时间。商业发行包未配置、到期或失去有效租约时,管理界面可用,转发暂停;Agent 设置 HALO_LICENSE_REQUIRED=1,依赖面板许可与短期控制租约。

Docker 先在私有 license-private/ 目录创建 license.json,.env 的 HALO_LICENSE_PRIVATE_DIR 指向绝对目录,并叠加只读配置。MySQL 需再加实际 compose.mysql.yaml:

docker compose -f compose.yaml -f compose.license.yaml up -d --no-build --pull never

许可缓存 DATA_DIR/software-license/state.json 与配置独立备份,普通业务数据库备份不能替代它。同一 DATA_DIR 只运行一个面板进程,不启用多进程集群或多副本共享许可缓存。迁移机器或许可状态丢失时由运营者重新绑定实例;不要删除缓存尝试绕过绑定。服务器 root 可控制本地文件,运行代码仍可读,不能承诺许可可绝对防修改或逆向。

15 · 本机中文维护菜单

新原生签名初装提供固定命令 halo(别名 halo-manage)。安装、升级、回退、状态、启停与保留数据卸载均在同一入口完成。只有新服务器初装需要上方一键引导;已安装系统使用本机可信工具,不反复运行远程初装脚本覆盖部署。

sudo halo
sudo halo status
sudo halo update panel latest
sudo halo update agent 0.6.1
sudo halo rollback panel 0.6.0
sudo halo rollback agent 0.6.0
sudo halo stop agent
sudo halo start agent
sudo halo uninstall agent --dry-run
sudo halo uninstall agent

版本可用 latest、指定版本或省略版本;回退要求保留可信且兼容历史。商业授权发行基线为 0.6.0,不回退到缺许可能力的旧版。卸载先显示计划,再输入完整 uninstall panel 或 uninstall agent 进行本机确认,默认保留数据库、配置、证书和共享工具。卸载面板前先迁移业务,依赖它的 Agent 会受控制租约到期影响。

别名也可用 sudo halo-manage;传统手动布局没有签名运行器时,菜单拒绝在线更新与回退。旧签名安装先按维护条件刷新已验证的固定工具,再使用新增入口。现有 Docker 使用自己的 Compose 指定服务和签名镜像摘要,原生菜单不会自动接管法国 Docker 面板。

流程参考 ForwardX 快速开始 与 Zero Forwarder 文档,采用 HaloRelay 自己的脚本摘要、发行签名与数据保留流程,未执行第三方安装脚本。公网安装与 Linux 原生升级回退仍需实机验收。