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_TOKEN environment 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.bind to lan or 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=1 is required because the connection is technically ws://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 get showed security=full in 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

ProblemCauseFix
unknown option '--gateway'Wrong flag nameUse --host and --port separately
SECURITY ERROR: Cannot connect over plaintext ws://OpenClaw blocks ws:// to public IPsUse SSH tunnel to localhost instead
gateway token missingToken not in Pi’s configopenclaw config set gateway.auth.token ...
SYSTEM_RUN_DENIEDNode exec approvals file missing/emptyWrite exec-approvals.json with security=full
Pi’s openclaw config set says “restart gateway”Pi tried to restart its own (non-existent) gatewayJust restart the node service directly
Tempted to open port 18789 in firewallUnnecessary with SSH tunnelDon’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.