前言
折腾了整整一晚上,终于成功将 Mac mini 节点连接到远程 OpenClaw Gateway。中间踩了无数坑,写下这篇完整教程,确保后续设备能一次成功。
问题背景
OpenClaw 是一个自托管的 AI 助手网关系统,支持多节点分布式部署。但在实际配置中遇到以下挑战:
- Gateway 默认绑定 loopback - 只能本地访问
- Tailscale DNS 解析问题 - 部分设备无法解析 MagicDNS
- 配对机制 - 首次连接需要服务器批准,但请求在断开后被删除
解决方案架构
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
| ┌─────────────────────────────────────────────────────────────┐ │ 服务器端 │ │ │ │ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │ │ │ Gateway │◄────►│ socat │◄────►│ Tailscale │ │ │ │ 127.0.0.1 │ │ 转发 │ │ 网络 │ │ │ │ :18789 │ │ 18790→18789 │ │ │ │ │ └─────────────┘ └─────────────┘ └─────────────┘ │ │ ▲ │ └──────────────────────────────│───────────────────────────────┘ │ Tailscale 网络 │ ┌──────────────────────────────│───────────────────────────────┐ │ 节点端 │ │ ▼ │ │ ┌─────────────┐ ┌─────────────┐ │ │ │ OpenClaw │◄────►│ Tailscale │ │ │ │ Node │ │ 客户端 │ │ │ └─────────────┘ └─────────────┘ │ │ │ └─────────────────────────────────────────────────────────────┘
|
核心原理:
- Gateway 保持绑定
127.0.0.1:18789 (loopback)
- 使用 socat 将 Tailscale IP:18790 转发到 127.0.0.1:18789
- 节点通过 Tailscale IP:18790 连接 Gateway
第一步:服务器端配置
1.1 Gateway 基础配置
1 2 3 4 5 6 7 8
| openclaw config set gateway.bind loopback openclaw gateway restart
openclaw gateway status | grep -E "bind|Listening"
|
1.2 获取 Gateway Token
1 2 3 4 5 6
| cat ~/.openclaw/openclaw.json | grep -A5 '"auth"' | grep token
openclaw config set gateway.auth.token YOUR_NEW_TOKEN openclaw gateway restart
|
重要: 请妥善保管 Gateway Token,不要泄露到公开渠道。
1.3 启动 socat 端口转发
1 2 3 4 5 6 7 8 9 10 11 12
| tailscale ip -4
GATEWAY_TS_IP=$(tailscale ip -4) nohup socat TCP-LISTEN:18790,bind=$GATEWAY_TS_IP,fork,reuseaddr TCP:127.0.0.1:18789 > /tmp/socat-tailscale.log 2>&1 &
ss -tlnp | grep -E "18789|18790"
|
1.4 socat 持久化(开机自启动)
创建 systemd 服务:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
| GATEWAY_TS_IP=$(tailscale ip -4)
sudo tee /etc/systemd/system/openclaw-socat.service > /dev/null << EOF [Unit] Description=OpenClaw socat port forward After=network.target tailscaled.service Requires=tailscaled.service
[Service] Type=simple ExecStart=/usr/bin/socat TCP-LISTEN:18790,bind=$GATEWAY_TS_IP,fork,reuseaddr TCP:127.0.0.1:18789 Restart=always RestartSec=5
[Install] WantedBy=multi-user.target EOF
sudo systemctl daemon-reload sudo systemctl enable openclaw-socat sudo systemctl start openclaw-socat
sudo systemctl status openclaw-socat
|
第二步:节点端配置
2.1 安装 Tailscale
macOS:
Linux:
1
| curl -fsSL https://tailscale.com/install.sh | sh
|
2.2 登录 Tailscale
1 2 3 4 5 6 7 8
| tailscale login
tailscale status
tailscale ping <GATEWAY_TS_IP>
|
2.3 安装 OpenClaw CLI
macOS:
Linux:
2.4 首次连接
1 2 3 4 5 6 7 8
| export OPENCLAW_GATEWAY_TOKEN=YOUR_GATEWAY_TOKEN
openclaw node run \ --host <GATEWAY_TS_IP> \ --port 18790 \ --display-name "YOUR_NODE_NAME"
|
首次连接会显示:
1
| node host gateway connect failed: pairing required
|
这是正常的! 表示连接成功,等待服务器批准配对。
第三步:服务器端批准配对
节点发起连接后,在服务器端执行:
1 2 3 4 5
| openclaw devices list
openclaw devices approve <request-id>
|
第四步:节点端重新连接
批准后,节点端重新执行连接命令:
1 2 3 4 5 6
| export OPENCLAW_GATEWAY_TOKEN=YOUR_GATEWAY_TOKEN
openclaw node run \ --host <GATEWAY_TS_IP> \ --port 18790 \ --display-name "YOUR_NODE_NAME"
|
成功标志:
- 不再显示
pairing required
- 连接保持活跃,终端不会退出
第五步:配置节点开机自启动
macOS (launchd)
创建 LaunchAgent 配置文件:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40
|
cat > ~/Library/LaunchAgents/com.openclaw.node.plist << 'EOF' <?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> <plist version="1.0"> <dict> <key>Label</key> <string>com.openclaw.node</string> <key>ProgramArguments</key> <array> <string>/usr/local/bin/openclaw</string> <string>node</string> <string>run</string> <string>--host</string> <string>YOUR_GATEWAY_IP</string> <string>--port</string> <string>18790</string> <string>--display-name</string> <string>YOUR_NODE_NAME</string> </array> <key>EnvironmentVariables</key> <dict> <key>OPENCLAW_GATEWAY_TOKEN</key> <string>YOUR_GATEWAY_TOKEN</string> </dict> <key>RunAtLoad</key> <true/> <key>KeepAlive</key> <true/> <key>StandardOutPath</key> <string>/tmp/openclaw-node.log</string> <key>StandardErrorPath</key> <string>/tmp/openclaw-node.error.log</string> </dict> </plist> EOF
|
管理服务:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| launchctl load ~/Library/LaunchAgents/com.openclaw.node.plist
launchctl list | grep openclaw
tail -f /tmp/openclaw-node.log
launchctl unload ~/Library/LaunchAgents/com.openclaw.node.plist
launchctl unload ~/Library/LaunchAgents/com.openclaw.node.plist launchctl load ~/Library/LaunchAgents/com.openclaw.node.plist
|
Linux (systemd)
创建服务文件:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
| sudo tee /etc/systemd/system/openclaw-node.service > /dev/null << 'EOF' [Unit] Description=OpenClaw Node After=network.target tailscaled.service Requires=tailscaled.service
[Service] Type=simple Environment="OPENCLAW_GATEWAY_TOKEN=YOUR_GATEWAY_TOKEN" ExecStart=/usr/local/bin/openclaw node run --host YOUR_GATEWAY_IP --port 18790 --display-name "YOUR_NODE_NAME" Restart=always RestartSec=10
[Install] WantedBy=multi-user.target EOF
sudo systemctl daemon-reload sudo systemctl enable openclaw-node sudo systemctl start openclaw-node
sudo systemctl status openclaw-node
journalctl -u openclaw-node -f
|
常见问题
Q1: 显示 ECONNREFUSED
原因: Gateway 未运行或 socat 未启动
解决:
1 2 3 4 5 6 7 8 9 10
| openclaw gateway status
ps aux | grep socat
pkill socat GATEWAY_TS_IP=$(tailscale ip -4) nohup socat TCP-LISTEN:18790,bind=$GATEWAY_TS_IP,fork,reuseaddr TCP:127.0.0.1:18789 > /tmp/socat.log 2>&1 &
|
Q2: 显示 pairing required 但服务器看不到设备
原因: 配对请求在断开后被删除
解决:
- 节点保持连接状态(不要退出)
- 服务器立即执行
openclaw devices list
- 批准后节点重新连接
Q3: 显示 gateway token mismatch
原因: Token 不正确
解决:
1 2 3 4 5
| cat ~/.openclaw/openclaw.json | grep -A5 '"auth"' | grep token
export OPENCLAW_GATEWAY_TOKEN=<正确的 Token>
|
Q4: Tailscale DNS 无法解析
解决: 直接使用 Tailscale IP 地址,不使用域名
1 2 3 4 5
| tailscale ip -4
openclaw node run --host <IP> --port 18790 --display-name "NAME"
|
Q5: 节点重启后无法自动连接
解决:
1 2 3 4 5 6 7 8 9
| launchctl list | grep openclaw
sudo systemctl status openclaw-node
tail -f /tmp/openclaw-node.log journalctl -u openclaw-node -f
|
配置清单
服务器端
节点端
快速命令参考
服务器端
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| openclaw gateway status openclaw gateway restart openclaw gateway stop openclaw gateway start
openclaw nodes status openclaw devices list openclaw devices approve <id> openclaw devices remove <id>
openclaw config set gateway.bind loopback openclaw config set gateway.auth.token <token>
ss -tlnp | grep -E "18789|18790" ps aux | grep socat
|
节点端
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| export OPENCLAW_GATEWAY_TOKEN=<token> openclaw node run --host <ip> --port <port> --display-name "<name>" openclaw node status openclaw node stop
tailscale status tailscale ping <ip> tailscale ip -4
launchctl load ~/Library/LaunchAgents/com.openclaw.node.plist launchctl unload ~/Library/LaunchAgents/com.openclaw.node.plist launchctl list | grep openclaw
sudo systemctl start openclaw-node sudo systemctl stop openclaw-node sudo systemctl restart openclaw-node sudo systemctl status openclaw-node
|
安全提醒
- Gateway Token - 不要泄露到公开渠道
- Tailscale IP - 只在 Tailnet 内部有效,但仍需保护
- 防火墙 - 确保只开放必要端口
- 定期更新 - 保持 OpenClaw 和 Tailscale 版本最新
总结
配置 OpenClaw 节点的关键在于:
- 理解网络架构 - Gateway 绑定 loopback,需要 socat 转发
- 配对流程 - 首次连接需要服务器批准
- 持久化配置 - 服务器 socat + 节点 LaunchAgent/systemd
按照本教程操作,后续设备应该能一次成功。
相关文档: