I recently got a Raspberry Pi 5 (8GB) and decided to connect it to my OpenClaw setup as a remote node. The idea: give my AI assistant direct access to a physical machine sitting on my home network, so it can run commands there, monitor things, and eventually interact with hardware.
This post documents how I did it, the pitfalls I ran into, and what I plan to use it for.
The Setup
- Raspberry Pi 5 8GB running Debian, on home WiFi
- OpenClaw gateway running on a VPS (remote server, different country)
- Goal: connect the Pi as a node so the AI can execute commands on it remotely
The challenge: the Pi is behind home NAT (no public IP), and the VPS is on the public internet. They can’t talk directly without some routing setup.
Architecture
[AI / OpenClaw gateway] ←→ [SSH tunnel] ←→ [Pi node service]
VPS Home network
The Pi initiates an outbound SSH tunnel to the VPS, forwarding the gateway’s WebSocket port locally. The OpenClaw node service then connects to localhost through that tunnel. All traffic is encrypted via SSH — no TLS cert needed, no port forwarding on the home router.
Step 1: Install OpenClaw on the Pi
curl -fsSL https://deb.nodesource.com/setup_22.x | sudo -E bash -
sudo apt install -y nodejs
sudo npm install -g openclaw
Step 2: Configure the Gateway Auth Token
The node needs to authenticate with the gateway. Set the token in the Pi’s local OpenClaw config:
openclaw config set gateway.auth.token YOUR_GATEWAY_TOKEN
Find your gateway token on the VPS with openclaw config get gateway.auth.token.
Pitfall: I first tried passing the token via an
OPENCLAW_TOKENenvironment variable in the systemd service — this didn’t work. The token must be set in the local config file.
Step 3: Leave the Gateway on Loopback
OpenClaw binds to loopback (127.0.0.1) by default — and that’s exactly what you want with the SSH tunnel approach. The Pi connects via the tunnel to localhost:18789 on the VPS, so the gateway never needs to be reachable from the outside.
Don’t change
gateway.bindtolanor open port 18789 in the firewall. The SSH tunnel makes both unnecessary, and exposing the gateway port publicly would be a pointless attack surface.
Pitfall: OpenClaw refuses plaintext
ws://connections to public IPs — this is a security feature. Don’t try to connect the Pi directly to the VPS IP over plain WebSocket. Use the SSH tunnel instead.
Step 5: Set Up SSH Key Access from Pi to VPS
Generate a key on the Pi:
ssh-keygen -t ed25519 -C "raspi5"
Add the public key to ~/.ssh/authorized_keys on the VPS, then verify:
ssh YOUR_VPS_USER@YOUR_VPS_HOST
Step 6: Create Persistent systemd Services
Two services: one for the SSH tunnel, one for the OpenClaw node. The node depends on the tunnel.
/etc/systemd/system/openclaw-tunnel.service:
[Unit]
Description=SSH tunnel to OpenClaw VPS
After=network-online.target
Wants=network-online.target
[Service]
User=YOUR_USER
ExecStart=/usr/bin/ssh -N \
-o ServerAliveInterval=60 \
-o ServerAliveCountMax=3 \
-o ExitOnForwardFailure=yes \
-o StrictHostKeyChecking=no \
-L 18789:127.0.0.1:18789 \
YOUR_VPS_USER@YOUR_VPS_HOST
Restart=always
RestartSec=10
[Install]
WantedBy=multi-user.target
/etc/systemd/system/openclaw-node.service:
[Unit]
Description=OpenClaw Node
After=openclaw-tunnel.service
Requires=openclaw-tunnel.service
[Service]
User=YOUR_USER
Environment=OPENCLAW_ALLOW_INSECURE_PRIVATE_WS=1
ExecStart=/usr/bin/openclaw node run --host 127.0.0.1 --port 18789
Restart=always
RestartSec=15
[Install]
WantedBy=multi-user.target
Note:
OPENCLAW_ALLOW_INSECURE_PRIVATE_WS=1is required because the connection is technicallyws://localhost— even though it’s safe (tunnelled over SSH). Without this flag, OpenClaw refuses to connect.
Enable and start:
sudo systemctl daemon-reload
sudo systemctl enable openclaw-tunnel openclaw-node
sudo systemctl start openclaw-tunnel
sleep 3
sudo systemctl start openclaw-node
Step 7: Grant Exec Permissions
By default the node blocks remote exec calls. Create the approvals file:
echo '{"version":1,"defaults":{"security":"full","ask":"off"}}' > ~/.openclaw/exec-approvals.json
sudo systemctl restart openclaw-node
Pitfall: Even though
openclaw approvals getshowedsecurity=fullin the effective policy, commands were still denied until this file was explicitly written. The gateway policy and node policy must both agree.
Step 8: Approve the Pairing (on the VPS)
openclaw devices list # confirm Pi shows as pending or paired
openclaw nodes status # confirm connected
In my case the Pi auto-paired on first connect. If yours shows as pending, run:
openclaw devices approve --latest
Result
After all that, running a command on the Pi from the AI assistant in Telegram:
hostname → raspi5
RAM: 7.9GB total, 736MB used
The Pi is now a persistent, always-on node. The AI can run scripts, check disk space, tail logs, or trigger automations — all from chat.
Pitfalls Summary
| Problem | Cause | Fix |
|---|---|---|
unknown option '--gateway' | Wrong flag name | Use --host and --port separately |
SECURITY ERROR: Cannot connect over plaintext ws:// | OpenClaw blocks ws:// to public IPs | Use SSH tunnel to localhost instead |
gateway token missing | Token not in Pi’s config | openclaw config set gateway.auth.token ... |
SYSTEM_RUN_DENIED | Node exec approvals file missing/empty | Write exec-approvals.json with security=full |
Pi’s openclaw config set says “restart gateway” | Pi tried to restart its own (non-existent) gateway | Just restart the node service directly |
| Tempted to open port 18789 in firewall | Unnecessary with SSH tunnel | Don’t — the tunnel connects to localhost, no firewall rule needed |
What’s Next: Use Cases
Having a home-network node opens up a lot:
Monitoring & Alerts
- Disk space, CPU temp, memory — alert me via Telegram if thresholds are crossed
- Check if home network devices are online
- Monitor Pi-hole stats and blocked query counts
Home Automation
- Trigger scripts via chat (“turn on the garden lights”)
- Read GPIO sensors (temperature, door sensors, motion)
- Interface with smart home devices on the local network
Local Services
- Run Pi-hole for network-wide ad blocking
- Host Jellyfin for local media streaming
- Run Home Assistant for smart home coordination
- Local Ollama instance for small LLM inference (Phi-3, Gemma 2B)
Offload Cron Jobs
- Move heavy scheduled tasks from the VPS to the Pi
- Local backups without cloud round-trips
- Process files on the local network without transferring them to the VPS
Camera & Physical Sensing
- Attach a Pi Camera Module — take snapshots on demand from Telegram
- Time-lapse, motion detection, or garden monitoring
The Pi 5 with 8GB is genuinely capable for all of these. The node setup took about an hour including the debugging — and now it’s a permanent fixture in my AI assistant setup.