网络部署
部署 ZeroClaw 以接收入站流量:网关暴露、Webhook 通道、隧道,以及仅限局域网与面向公网的配置。树莓派和其他家庭网络主机是此场景下的首要目标。
当入站端口很重要时
| 模式 | 入站端口? | 备注 |
|---|---|---|
| Telegram(长轮询) | 不 | ZeroClaw 轮询 api.telegram.org,可在 NAT 后工作 |
| Matrix / Mattermost / Nextcloud Talk | 不 | 同步/WebSocket,仅出站 |
| Discord / Slack(Socket 模式) | 不 | 出站 WebSocket |
Signal(signal-cli-rest-api) | 不 | 本地主机容器 |
| Nostr / IMAP / MQTT | 不 | 所有出站 |
| Webhooks(GitHub、Slack Events API、WhatsApp、Nextcloud Talk 机器人、自定义) | 是 | 需要公共 POST 端点 |
| 从局域网配对网关 | 是(局域网范围) | 绑定到 0.0.0.0 或使用隧道 |
| Discord / Slack(HTTP 事件) | 是的 | 如果您不使用 Socket 模式 |
结论: 一个仅使用 Telegram 的机器人可以在消费级路由器后面的 Pi 上运行,无需任何端口转发。而任何基于 webhook 的方案都需要一个可访问的 URL,这正是隧道发挥作用的地方。
绑定网关
默认情况下,网关绑定到 127.0.0.1,其他设备无法访问。有三种方式可将其暴露出来:
选项 1:公共绑定(局域网)
这样局域网内的任何设备都可以访问 http://<pi-ip>:42617。但这对于需要从互联网访问的 webhook 没有帮助,因为路由器的公网 IP 并未转发到这台 Pi。
安全性: 由于绑定到 0.0.0.0 是一个重大的安全策略变更,因此需要设置 allow_public_bind = true。如果没有此配置,守护进程将拒绝启动。这是有意为之的设计。
选项 2:隧道(可从互联网访问)
然后重启守护进程,隧道通过配置以声明式方式进行管理,与网关一同启动。
隧道将公共 URL 转发到 127.0.0.1 上的网关。无需路由器配置,无需开放端口。将 tunnel.tunnel_provider 设置为受支持的值之一即可;每个值的工作方式类似:
| 提供者 | 设置摩擦力 | 成本 | 适用于 |
|---|---|---|---|
tailscale | 账户 + 客户端 | 免费层级 | 长期稳定的 URL |
cloudflare | 账户 + cloudflared + 令牌 | 免费 | 自定义域名 |
ngrok | 账户 + 代理 + 令牌 | 免费,但有使用限制 | 测试,短期 |
pinggy | SSH,无账户 | 免费层级 | 快速一次性 URL |
openvpn | 你自己的 OpenVPN 出口 | 自托管 | 现有 VPN 基础设施 |
custom | [tunnel.custom] 下的命令 | 依赖 | 还有其他事项吗 |
tunnel_provider = "none"(默认值)使网关保持本地运行,不使用隧道。各提供程序的 [tunnel.<provider>] 字段请参阅 配置参考。
选项 3:反向代理
在网关前运行 nginx / Caddy / Traefik。在此处终止 TLS,并代理到 localhost:42617。适用于:
- 具有真实公网 IP 的服务器
- 使用 Let’s Encrypt 的现有反向代理设置
- 在同一主机上托管多个服务
一个最小的 Caddy 配置:
agent.example.com {
reverse_proxy localhost:42617
}
网关保持绑定到 127.0.0.1,由代理负责监听。
通用网关 Webhook 身份验证
网关的 POST /webhook 和仅限 SOP 的 POST /sop/* 路由可以独立于配对而要求精确匹配的共享密钥标头:
[gateway]
webhook_secret = "replace-with-a-random-secret"
将该值作为 X-Webhook-Secret 发送。当 require_pairing = true 且设置了 webhook_secret 时,调用方必须同时发送配对的 bearer 令牌和 webhook 密钥。通用网关密钥与 [channels.webhook.<alias>].secret 有意分开;频道别名各自运行监听器,并改用正文 HMAC 验证。
网关配置写入会通过实时网关配置视图生效。直接编辑文件需要执行常规守护进程重新加载(或单独重启网关)。
远程守护进程重新加载
POST /admin/reload 会重新读取 config.toml 并就地重建每个子系统(PID 不变,停机时间不到一秒)。这是无需完全重启即可应用配置变更的受支持方式。默认情况下它只接受环回(loopback)调用方,因此来自其他机器的远程仪表板或 curl 会收到 403 Forbidden。
允许经过身份验证的远程重新加载:
[gateway]
allow_remote_admin = true # off by default
require_pairing = true # required for remote reload (also the default)
启用此选项后,非环回(loopback)调用方只有在同时通过配对认证(Authorization: Bearer <token>)的情况下才能访问 /admin/reload。环回调用方(本地 CLI)始终被允许,且无需令牌。无论此标志如何设置,/admin/shutdown 和配对码端点都仅限于 localhost 访问。
由于远程访问是通过配对来强制实施的,因此除非 require_pairing 也已开启,否则 allow_remote_admin 不会生效:如果禁用了配对,远程调用方将无法通过身份验证,因此请求会被以 403 Forbidden 拒绝,而不是被匿名允许。这使得无法通过切换单个标志来暴露未经身份验证的远程重新加载。
安全提示: 除非你确实需要从其他主机重新加载,否则请保持 allow_remote_admin 处于关闭状态。请保持 require_pairing = true(默认值),这样就无法匿名触发重新加载。
树莓派部署
前置条件
- Raspberry Pi 3/4/5(或类似的单板计算机),搭载 Raspberry Pi OS 或 Alpine
- 网络连接(WiFi 或以太网)
- 可选:用于硬件集成的 USB 外围设备
安装
克隆并运行安装程序。在不带任何参数的情况下,它会进入交互式选择界面,你可以在其中选择构建类型以及要编译的功能特性,包括 GPIO/I2C/SPI 的硬件功能。在 Pi 上,它还会使用针对 Pi 调优的 cargo 配置文件;有关交换空间设置和各型号的构建矩阵,请参阅 Raspberry Pi setup。
Raspberry Pi OS
git clone https://github.com/zeroclaw-labs/zeroclaw.git
cd zeroclaw
./install.sh
Alpine
apk add curl rust cargo openssl-dev pkgconf git
git clone https://github.com/zeroclaw-labs/zeroclaw.git
cd zeroclaw
./install.sh
当你选择硬件功能时,通过 rppal 授予对 GPIO、I2C、SPI 的访问权限。标准服务单元已经将用户添加到 gpio、spi、i2c 组中。
检查清单
- 安装二进制文件(
./install.sh,在选择器中选择你需要的功能) - 运行
zeroclaw quickstart - 配置你的频道。Telegram 无需端口;webhook 需要隧道
- 安装服务:
zeroclaw service install && zeroclaw service start - 对于局域网访问:设置
[gateway] host = "0.0.0.0"和allow_public_bind = true - 对于 Webhook:配置
[tunnel]并指定一个提供商
Alpine Linux (OpenRC)
OpenRC 服务是系统范围的。以 root 用户身份安装:
sh
sudo zeroclaw service install
创建:
/etc/init.d/zeroclaw:init 脚本/etc/zeroclaw/:配置目录/var/log/zeroclaw/:日志文件
启用并启动:
sh
sudo rc-update add zeroclaw default
sudo rc-service zeroclaw start
sudo rc-service zeroclaw status
日志:
sh
sudo tail -f /var/log/zeroclaw/error.log
OpenRC 注意事项
- 服务以
zeroclaw:zeroclaw(最小权限)运行 - 仅限系统级:无用户级 OpenRC 服务
- 所有服务操作都需要
sudo
Telegram 轮询的注意事项
Telegram Bot API 的 getUpdates 对每个 bot token 只允许单一轮询器。你不能使用相同的 token 运行两个实例;第二个实例会收到 Conflict: terminated by other getUpdates request。
如果您看到此内容:
-
执行
ps aux | grep zeroclaw并确认只有一个守护进程在运行 -
检查是否有一个来自开发会话的
cargo run --bin zeroclaw -- channel start telegram进程仍在运行 -
如果已过期,重置 Telegram 的投票会话:
sh
curl -X POST "https://api.telegram.org/bot$TOKEN/close"
安全地暴露 Webhook
一个公开可访问的 Webhook URL 是攻击面。至少:
- HMAC 签名验证:在每个 webhook 通道上配置的
secret - 源 IP 白名单,适用于具有固定出口 IP 的服务(GitHub、AWS SNS)
- 速率限制:webhook 通道配置中的
rate_limit_per_sec
有关完整的配置选项,请参阅 Channels → Webhooks。