Hybrid Gateway — VPS + Local Node
Run your OpenClaw gateway on a cloud VPS for reliability, and connect a local machine as a node for hardware capabilities the VPS lacks: residential IP, GPU/ML inference, browser automation, local models, macOS-only tools, etc.
Why this architecture?
| VPS (Gateway) | Local Node |
|---|
| Always online | ✅ Static IP, no ISP outages | ❌ Power/network dependent |
| Messaging |
✅ Handles Telegram, Discord, etc. | ❌ Not its job |
|
Agent brain | ✅ Runs models, routes tools | ❌ Peripheral only |
|
GPU / ML | ❌ Most VPS have no GPU | ✅ Apple Silicon, NVIDIA, etc. |
|
Browser automation | ⚠️ Headless only, cloud IP | ✅ Real browser, residential IP |
|
Local models | ❌ No hardware for it | ✅ Ollama, whisper, etc. |
|
macOS tools | ❌ Linux VPS | ✅ Native macOS (if using Mac) |
Prerequisites
Before starting, you need:
- 1. OpenClaw installed on both machines — VPS (gateway) and local machine (node)
- Tailscale installed on both machines — this is how they talk to each other
-
Download Tailscale
- Sign in on both machines with the same Tailscale account
- Verify connectivity:
tailscale status on either machine should show both devices
- 3. Gateway already running on the VPS —
openclaw gateway status should show running - Gateway auth token configured — required for non-loopback connections
If you don't have Tailscale set up yet, do that first. The rest of this guide assumes both machines are on the same tailnet.
Step 1 — Configure gateway bind mode
By default, the gateway binds to loopback (127.0.0.1 only). Your node can't reach that from another machine.
Recommended: lan bind (listens on all interfaces)
CODEBLOCK0
This listens on 0.0.0.0 — both 127.0.0.1 (local agents) and your Tailscale IP (remote node) will work.
Alternative: tailnet bind (Tailscale IP only)
CODEBLOCK1
⚠️ Warning: tailnet bind breaks local agent-to-agent sessions. Local tools try ws://127.0.0.1:18789 but the gateway only listens on the Tailscale IP. If you use multi-agent workflows, use lan instead.
Ensure auth is configured (required for any non-loopback bind):
CODEBLOCK2
Restart the gateway after config changes:
CODEBLOCK3
Verify:
CODEBLOCK4
Step 2 — Start the node on your local machine
On the local machine (Mac Mini, desktop, etc.):
CODEBLOCK5
If it connects, you'll see it register. If not, see Troubleshooting below.
Step 3 — Approve the device pairing
On the VPS:
CODEBLOCK6
Step 4 — Install as a service (auto-start)
You want the node to survive reboots and run headless.
macOS (LaunchAgent)
CODEBLOCK7
This creates a LaunchAgent plist that auto-starts on login.
Important: If the gateway requires ws:// over a private network (not wss://), you may need to set an environment variable in the LaunchAgent plist:
Add these environment variables to the plist's EnvironmentVariables dict:
- -
OPENCLAW_GATEWAY_TOKEN — your existing gateway auth token (the same one from openclaw config get gateway.auth.token on the VPS) - INLINECODE15 =
1 — allows ws:// over Tailscale (safe — traffic is WireGuard-encrypted at the network layer)
See the OpenClaw node host docs for the full plist reference.
The insecure WS override is only needed because OpenClaw blocks plaintext ws:// to non-loopback addresses by default. On Tailscale this is safe since all traffic is encrypted by WireGuard.
The LaunchAgent plist location: INLINECODE19
Load/unload manually:
CODEBLOCK8
Check logs: INLINECODE20
Linux (systemd)
CODEBLOCK9
Or create a systemd user service manually:
In the systemd service [Service] section, add:
- -
Environment=OPENCLAW_GATEWAY_TOKEN=<your-gateway-token> — same token from your VPS gateway config - INLINECODE23 — only if not using
wss:// via Tailscale Serve
See the OpenClaw node host docs for the full service file reference.
CODEBLOCK10
Step 5 — Configure exec routing
Tell the gateway to route exec host=node commands to your node:
CODEBLOCK11
Now agents can run commands on your local machine:
CODEBLOCK12
Set up exec approvals on the node
The node enforces its own allowlist. Add commands you want to permit:
CODEBLOCK13
Or edit ~/.openclaw/exec-approvals.json on the node directly.
Step 6 — Set up SSH fallback (optional but recommended)
The node protocol handles command execution, but SSH is still needed for:
- - File transfers (scp/rsync between VPS and node)
- Full shell environment (commands needing
.bashrc/.zshrc — nvm, homebrew PATH, env vars) - Fallback when the node disconnects
Set up SSH key access
CODEBLOCK14
When to use which transport
| Task | Use |
|---|
| Run a command | INLINECODE29 (node protocol) |
| Transfer files |
scp my-node:/path/to/file . (SSH) |
| Commands needing shell env |
ssh my-node "source ~/.zshrc; command" (SSH) |
| Node disconnected | SSH fallback for everything |
Troubleshooting
"SECURITY ERROR: Cannot connect over plaintext ws://"
The node is trying to connect via ws:// (not wss://) to a non-loopback address. This is blocked by default.
Fix: Set OPENCLAW_ALLOW_INSECURE_PRIVATE_WS=1 in the node's environment. This is safe on Tailscale (WireGuard-encrypted). Add it to your LaunchAgent plist or systemd service.
Better fix (long-term): Use Tailscale Serve to get proper wss:// on the gateway. Then you don't need the env override.
Local agent sessions fail after changing gateway.bind
If you changed gateway.bind from loopback to tailnet, local agent-to-agent communication breaks. Local sessions try ws://127.0.0.1 but the gateway only listens on the Tailscale IP.
Fix: Use gateway.bind: "lan" instead. This listens on 0.0.0.0 — both loopback and Tailscale interfaces.
Node shows "pairing required"
Network route is working, auth is fine, but the device hasn't been approved yet.
CODEBLOCK15
Node shows "bootstrap token invalid or expired"
The setup code or pairing token is stale.
Fix: Generate a fresh one and reconnect:
CODEBLOCK16
Node connects but exec host=node doesn't work
- 1. Check the node is actually paired and connected:
openclaw nodes status
- 2. Check
tools.exec.node points to the right node:
openclaw config get tools.exec.node
- 3. Check exec approvals on the node allow the command you're running.
Node disconnects frequently
- - Ensure the node machine doesn't sleep (macOS: System Settings → Energy → Prevent automatic sleeping)
- Check Tailscale stays connected: INLINECODE43
- Check node logs: INLINECODE44
- If on Wi-Fi, prefer ethernet for the node machine
Commands fail with "command not found" on node
Node system.run uses a minimal PATH. Homebrew, nvm, and other tools that modify PATH via shell config won't be available.
Fix: Use full binary paths:
CODEBLOCK19
Or fall back to SSH when you need the full shell environment:
CODEBLOCK20
Architecture diagram
CODEBLOCK21
Quick reference
| Task | Command |
|---|
| Check gateway bind | INLINECODE46 |
| Check node status |
openclaw nodes status |
| List pending pairings |
openclaw devices list |
| Approve a node |
openclaw devices approve <id> |
| Run command on node |
exec host=node command="..." |
| Check Tailscale |
tailscale status |
| Restart gateway |
openclaw gateway restart |
| Node logs |
~/.openclaw/logs/node.log |
Tested with
- - OpenClaw 2026.4.x
- Tailscale 1.x
- macOS 15 (Sequoia) + Ubuntu 24.04 VPS
- Mac Mini M4 as node, Hostinger VPS as gateway
Should work with any VPS provider and any local machine that can run OpenClaw + Tailscale.
License
MIT
Hybrid Gateway — VPS + 本地节点
在云端VPS上运行你的OpenClaw网关以确保可靠性,并连接本地机器作为节点,以提供VPS所缺乏的硬件能力:住宅IP、GPU/ML推理、浏览器自动化、本地模型、macOS专属工具等。
为何采用这种架构?
| VPS(网关) | 本地节点 |
|---|
| 始终在线 | ✅ 静态IP,无ISP中断 | ❌ 依赖电源/网络 |
| 消息处理 |
✅ 处理Telegram、Discord等 | ❌ 非其职责 |
|
智能体大脑 | ✅ 运行模型、路由工具 | ❌ 仅作为外设 |
|
GPU / ML | ❌ 大多数VPS没有GPU | ✅ Apple Silicon、NVIDIA等 |
|
浏览器自动化 | ⚠️ 仅无头模式,云IP | ✅ 真实浏览器,住宅IP |
|
本地模型 | ❌ 无硬件支持 | ✅ Ollama、whisper等 |
|
macOS工具 | ❌ Linux VPS | ✅ 原生macOS(如使用Mac) |
前提条件
开始之前,你需要:
- 1. 在两台机器上都安装OpenClaw — VPS(网关)和本地机器(节点)
- 在两台机器上都安装Tailscale — 这是它们相互通信的方式
-
下载Tailscale
- 使用同一个Tailscale账号在两台机器上登录
- 验证连接:在任意一台机器上运行 tailscale status 应显示两台设备
- 3. 网关已在VPS上运行 — openclaw gateway status 应显示运行中
- 已配置网关认证令牌 — 非回环连接必需
如果尚未设置Tailscale,请先完成设置。本指南其余部分假设两台机器位于同一个tailnet中。
步骤 1 — 配置网关绑定模式
默认情况下,网关绑定到 loopback(仅127.0.0.1)。你的节点无法从另一台机器访问该地址。
推荐:lan 绑定(监听所有接口)
bash
在VPS上
openclaw config set gateway.bind lan
这将监听 0.0.0.0 — 同时支持 127.0.0.1(本地智能体)和你的Tailscale IP(远程节点)。
备选:tailnet 绑定(仅Tailscale IP)
bash
openclaw config set gateway.bind tailnet
⚠️ 警告: tailnet 绑定会破坏本地智能体之间的会话。本地工具尝试连接 ws://127.0.0.1:18789,但网关仅监听Tailscale IP。如果你使用多智能体工作流,请改用 lan。
确保已配置认证(任何非回环绑定都需要):
bash
检查当前认证配置
openclaw config get gateway.auth.mode
openclaw config get gateway.auth.token
如果未配置,设置令牌认证
openclaw config set gateway.auth.mode token
openclaw config set gateway.auth.token <你的令牌>
添加速率限制(推荐)
openclaw config set gateway.auth.rateLimit.maxAttempts 10
openclaw config set gateway.auth.rateLimit.windowMs 60000
openclaw config set gateway.auth.rateLimit.lockoutMs 300000
配置更改后重启网关:
bash
openclaw gateway restart
验证:
bash
openclaw gateway status
应显示:bind=lan (0.0.0.0) 且 RPC probe: ok
步骤 2 — 在本地机器上启动节点
在本地机器上(Mac Mini、台式机等):
bash
获取VPS的Tailscale IP(在VPS上运行)
tailscale ip -4
示例输出:100.x.y.z
在本地机器上,设置网关令牌
export OPENCLAW
GATEWAYTOKEN=<你的令牌>
启动节点(前台模式,用于测试)
openclaw node run --host
TAILSCALEIP> --port 18789 --display-name 我的节点
如果连接成功,你会看到节点注册。如果没有,请参阅下面的故障排除部分。
步骤 3 — 批准设备配对
在VPS上:
bash
openclaw devices list
找到来自节点的待处理请求
openclaw devices approve <请求ID>
验证
openclaw nodes status
应显示你的节点已配对并连接
步骤 4 — 安装为服务(自动启动)
你希望节点在重启后保持运行,并能无头运行。
macOS(LaunchAgent)
bash
openclaw node install --host TAILSCALEIP> --port 18789 --display-name 我的节点
这将创建一个在登录时自动启动的LaunchAgent plist文件。
重要: 如果网关需要通过私有网络使用 ws://(而非 wss://),你可能需要在LaunchAgent plist中设置环境变量:
在plist的 EnvironmentVariables 字典中添加以下环境变量:
- - OPENCLAWGATEWAYTOKEN — 你现有的网关认证令牌(与VPS上 openclaw config get gateway.auth.token 获取的相同)
- OPENCLAWALLOWINSECUREPRIVATEWS = 1 — 允许通过Tailscale使用 ws://(安全 — 流量在网络层由WireGuard加密)
完整的plist参考请参阅 OpenClaw节点主机文档。
仅在OpenClaw默认阻止明文 ws:// 连接到非回环地址时需要此不安全WS覆盖。在Tailscale上这是安全的,因为所有流量都由WireGuard加密。
LaunchAgent plist位置:~/Library/LaunchAgents/ai.openclaw.node.plist
手动加载/卸载:
bash
launchctl load ~/Library/LaunchAgents/ai.openclaw.node.plist
launchctl unload ~/Library/LaunchAgents/ai.openclaw.node.plist
查看日志:~/.openclaw/logs/node.log
Linux(systemd)
bash
openclaw node install --host TAILSCALEIP> --port 18789 --display-name 我的节点
或手动创建systemd用户服务:
在systemd服务的 [Service] 部分添加:
- - Environment=OPENCLAWGATEWAYTOKEN=<你的网关令牌> — 与VPS网关配置中的令牌相同
- Environment=OPENCLAWALLOWINSECUREPRIVATEWS=1 — 仅当未通过Tailscale Serve使用 wss:// 时需要
完整的服务文件参考请参阅 OpenClaw节点主机文档。
bash
systemctl --user daemon-reload
systemctl --user enable openclaw-node
systemctl --user start openclaw-node
步骤 5 — 配置执行路由
告诉网关将 exec host=node 命令路由到你的节点:
bash
在VPS上
openclaw config set tools.exec.node 我的节点
现在智能体可以在你的本地机器上运行命令:
exec host=node command=uname -a
在节点上设置执行审批
节点强制执行自己的允许列表。添加你想要允许的命令:
bash
在VPS上(远程管理节点审批)
openclaw approvals allowlist add --node 我的节点 /usr/bin/uname
openclaw approvals allowlist add --node 我的节点 /bin/bash
openclaw approvals allowlist add --node 我的节点 /usr/local/bin/node
或直接在节点上编辑 ~/.openclaw/exec-approvals.json。
步骤 6 — 设置SSH备用方案(可选但推荐)
节点协议处理命令执行,但以下情况仍需要SSH:
- - 文件传输(VPS和节点之间的scp/rsync)
- 完整Shell环境(需要 .bashrc/.zshrc 的命令 — nvm、homebrew PATH、环境变量)
- 备用方案(节点断开连接时)
设置SSH密钥访问
bash
在VPS和节点之间设置基于SSH密钥的访问:
- 1. 在VPS上生成ed25519密钥对
- 将公钥复制到节点的 authorized_keys
- 创建SSH配置别名(例如 Host my-node),指向节点的Tailscale IP
- 使用 ssh my-node 测试,确认无需密码即可访问
详细步骤请参阅 GitHub SSH密钥指南 — 同样的流程适用于任何SSH主机。
何时使用哪种