Running OpenClaw on Raspberry Pi 5 with Docker
— 2026.02.04OpenClaw is a personal AI assistant created by Peter Steinberger. It’s gone through a few name changes — Clawdbot, then Moltbot, now OpenClaw — but the idea has stayed the same: run your own AI agent on your own hardware, connected to messaging apps you already use. WhatsApp, Telegram, iMessage. No new app, no cloud dependency.
It’s powered by whatever LLM you want (Claude, GPT, Kimi), keeps persistent memory across conversations, and can actually do things: manage files, run terminal commands, browse the web. Most people run it on a Mac mini or spare laptop. I wanted something more lightweight and always-on, so I set it up on my Raspberry Pi 5 running Docker, accessible only through my WireGuard VPN.
The architecture
┌─────────────────────────────────────────────────────────────┐
│ Raspberry Pi 5 │
│ ┌─────────────────────────────────────────────────────┐ │
│ │ Docker Network (web) │ │
│ │ ┌─────────────┐ ┌─────────────────────┐ │ │
│ │ │ Caddy │ ──────► │ OpenClaw Gateway │ │ │
│ │ │ (HTTPS) │ │ - Telegram Bot │ │ │
│ │ │ :443 │ │ - WhatsApp │ │
│ │ └─────────────┘ │ - Claude Code OAuth │ │ │
│ │ │ :18789 │ │ │
│ │ └─────────────────────┘ │ │
│ └─────────────────────────────────────────────────────┘ │
│ │ │
│ WireGuard (wg0) │
│ 10.13.13.1 │
└─────────────────────────────────────────────────────────────┘
│
┌──────────┴──────────┐
│ WireGuard VPN │
│ (encrypted) │
└──────────┬──────────┘
│
┌──────────┴──────────┐
│ Mac / Phone │
│ 10.13.13.x │
└─────────────────────┘
The stack: Raspberry Pi 5 with Docker, Caddy as reverse proxy with self-signed HTTPS, WireGuard for secure remote access, and OpenClaw itself with Telegram and WhatsApp channels. For the LLM, you can use Kimi K2.5 (free) or Claude (paid). Brave Search is optional if you want web search capabilities.
Before you start, you’ll need Docker and Docker Compose installed, WireGuard configured, and a Telegram Bot Token from @BotFather. For the LLM, either grab a free API key from platform.moonshot.cn (Kimi) or set up Claude Code OAuth if you have a Claude subscription. A Brave Search API key is optional but nice to have.
Getting it running
The directory structure I ended up with:
/srv/openclaw/
├── docker-compose.yml
├── .env
├── config/ # Mounted as /home/node/.openclaw
│ ├── openclaw.json
│ ├── credentials/
│ │ └── whatsapp/
│ └── agents/
│ └── main/
└── workspace/ # Mounted as /home/node/clawd
├── USER.md
├── IDENTITY.md
└── contacts.md
Start by creating it and cloning the source:
sudo mkdir -p /srv/openclaw
cd /srv/openclaw
mkdir -p config workspace
git clone https://github.com/openclaw/openclaw.git openclaw-src
The environment file
cat > .env << 'EOF'
OPENCLAW_GATEWAY_TOKEN=your-random-token-here
TELEGRAM_BOT_TOKEN=your-telegram-bot-token
# LLM Provider (choose one)
# Option A: Kimi Coding (free)
KIMI_API_KEY=your-kimi-api-key
# Option B: Claude Code OAuth (paid, requires Claude subscription)
# CLAUDE_CODE_OAUTH_TOKEN=your-claude-code-oauth-token
# Optional: Web search (get key from brave.com/search/api)
BRAVE_API_KEY=your-brave-api-key
EOF
| Variable | Required | Description |
|---|---|---|
OPENCLAW_GATEWAY_TOKEN | Yes | Random token for dashboard/API auth |
TELEGRAM_BOT_TOKEN | Yes | From @BotFather on Telegram |
KIMI_API_KEY | One LLM required | Free API key from platform.moonshot.cn |
CLAUDE_CODE_OAUTH_TOKEN | One LLM required | Requires Claude Pro subscription |
BRAVE_API_KEY | No | Enables web search. Free tier available at brave.com/search/api |
Generate a random gateway token with openssl rand -hex 32. If you’re going the Claude route, run claude setup-token to get your OAuth token.
Docker Compose
services:
openclaw-gateway:
build:
context: ./openclaw-src
dockerfile: Dockerfile
image: openclaw:local
container_name: openclaw
environment:
- HOME=/home/node
- TERM=xterm-256color
- OPENCLAW_GATEWAY_TOKEN=${OPENCLAW_GATEWAY_TOKEN}
- TELEGRAM_BOT_TOKEN=${TELEGRAM_BOT_TOKEN}
# LLM: use one or both
- KIMI_API_KEY=${KIMI_API_KEY}
- CLAUDE_CODE_OAUTH_TOKEN=${CLAUDE_CODE_OAUTH_TOKEN:-}
# Optional: web search
- BRAVE_API_KEY=${BRAVE_API_KEY:-}
volumes:
- ./config:/home/node/.openclaw
- ./workspace:/home/node/clawd
ports:
- "18789:18789"
networks:
- web
init: true
restart: unless-stopped
command:
- node
- dist/index.js
- gateway
- --bind
- lan
- --port
- "18789"
openclaw-cli:
image: openclaw:local
container_name: openclaw-cli
profiles:
- cli
environment:
- HOME=/home/node
- TERM=xterm-256color
- OPENCLAW_GATEWAY_TOKEN=${OPENCLAW_GATEWAY_TOKEN}
- TELEGRAM_BOT_TOKEN=${TELEGRAM_BOT_TOKEN}
- KIMI_API_KEY=${KIMI_API_KEY}
- CLAUDE_CODE_OAUTH_TOKEN=${CLAUDE_CODE_OAUTH_TOKEN:-}
- BRAVE_API_KEY=${BRAVE_API_KEY:-}
volumes:
- ./config:/home/node/.openclaw
- ./workspace:/home/node/clawd
networks:
- web
init: true
networks:
web:
external: true
Build and start with docker compose up -d --build. The first build takes a while on the Pi 5.
Initial setup
docker compose exec -it openclaw-gateway node dist/index.js onboard
The wizard asks you to pick your auth method, model, and channel. For auth, choose “Kimi Coding API key” for the free option or “Anthropic token (Claude Code)” if you’re paying for Claude. For the model, kimi-coding/k2p5 (Kimi K2.5) works well — 256k context window and reasoning capabilities, not bad for free. Select Telegram as the channel.
Verify it’s working:
docker compose logs | grep "agent model" | tail -1
# Should show: [gateway] agent model: kimi-coding/k2p5
Tip: Add google/gemini-2.0-flash as a fallback model in case Kimi hits rate limits on the free tier.
Then configure the gateway tokens:
docker compose exec openclaw-gateway node dist/index.js config set gateway.auth.token "your-gateway-token"
docker compose exec openclaw-gateway node dist/index.js config set gateway.remote.token "your-gateway-token"
docker compose restart openclaw-gateway
HTTPS with Caddy
OpenClaw’s dashboard requires HTTPS or localhost. Since this is behind WireGuard and not publicly accessible, I use Caddy with a self-signed certificate.
Add to your Caddyfile:
openclaw.yourdomain.local {
tls internal
reverse_proxy openclaw:18789
}
Add to your Mac’s /etc/hosts:
10.13.13.1 openclaw.yourdomain.local
Then access the dashboard at https://openclaw.yourdomain.local/?token=your-gateway-token. You’ll also need to enable insecure auth for self-signed certs:
docker compose exec openclaw-gateway node dist/index.js config set gateway.controlUi.allowInsecureAuth true
docker compose restart openclaw-gateway
Adding WhatsApp
This is where it gets interesting. Enable the channel, link your phone, and allowlist your number:
# Enable WhatsApp
docker compose exec openclaw-gateway node dist/index.js config set channels.whatsapp.enabled true
# Link your phone (scan the QR code with WhatsApp → Linked Devices)
docker compose exec -it openclaw-gateway node dist/index.js channels login --channel whatsapp
# Allowlist your number
docker compose exec openclaw-gateway node dist/index.js config set channels.whatsapp.allowFrom '["+your-phone-number"]'
docker compose restart openclaw-gateway
If you want to send WhatsApp messages from Telegram (cross-channel messaging):
docker compose exec openclaw-gateway node dist/index.js config set tools.message.crossContext.allowAcrossProviders true
docker compose restart openclaw-gateway
The contacts problem
On macOS, OpenClaw uses wacli to look up contacts by name. On the Pi, that’s not available. The workaround is simple — create a contacts file:
cat > /srv/openclaw/workspace/contacts.md << 'EOF'
# My Contacts
- Mom: +1234567890
- Dad: +0987654321
- Work: +1122334455
EOF
OpenClaw references this file when you ask to message someone by name. Not elegant, but it works.
Useful commands
# Check status
docker compose exec openclaw-gateway node dist/index.js status
# View logs
docker compose logs -f openclaw-gateway
# Send test message
docker compose exec openclaw-gateway node dist/index.js message send \
--channel whatsapp --target "+1234567890" --message "test"
# Re-link WhatsApp
docker compose exec -it openclaw-gateway node dist/index.js channels login --channel whatsapp
# List skills
docker compose exec openclaw-gateway node dist/index.js skills list
# Install skills from ClawdHub
docker compose exec openclaw-gateway clawdhub search email
docker compose exec openclaw-gateway clawdhub install <skill-name>
Troubleshooting
”No API key found for provider anthropic”
The agent auth isn’t configured. Make sure your LLM API key is in both the .env file and the docker-compose.yml environment section. Run the configure wizard again if needed:
docker compose run --rm openclaw-cli node dist/index.js configure
WhatsApp says “No active listener”
Restart the gateway after linking:
docker compose restart openclaw-gateway
“unauthorized: gateway token mismatch”
Sync the tokens:
source /srv/openclaw/.env
docker compose exec openclaw-gateway node dist/index.js config set gateway.auth.token "$OPENCLAW_GATEWAY_TOKEN"
docker compose exec openclaw-gateway node dist/index.js config set gateway.remote.token "$OPENCLAW_GATEWAY_TOKEN"
docker compose restart openclaw-gateway
Volume mount confusion
OpenClaw has gone through a few name changes (Clawdbot → Moltbot → OpenClaw), so you might see references to .clawdbot or .moltbot in older docs. Use /home/node/.openclaw for the config mount. Migration warnings can usually be ignored.
Security
The setup is intentionally locked down:
- The Pi is only reachable via WireGuard VPN
- Caddy provides HTTPS (self-signed, but encrypted)
- The gateway token is required for dashboard and CLI access
- API keys stay in the
.envfile - Only port 443 (Caddy) and WireGuard are exposed externally
On my radar: nanobot
While OpenClaw works well, I’ve been eyeing nanobot as an alternative. It bills itself as “The Ultra-Lightweight Clawdbot” — about 4,000 lines of Python compared to OpenClaw’s 430k+ lines. For a Raspberry Pi setup, that’s appealing: faster startup, lower memory usage, pip install nanobot-ai and you’re done. It supports Telegram and WhatsApp through OpenRouter, and the codebase is clean enough to hack on.
The tradeoff is fewer features — no ClawdHub skills ecosystem, simpler memory system, less polish. But for a personal AI assistant that handles messages and runs basic tasks, it might be all I need. I’m planning to spin up a second container and run them side-by-side for a while.
- OpenClaw Website
- OpenClaw GitHub
- OpenClaw v2026.1.30 Release Notes (Kimi support)
- Kimi / Moonshot AI Platform (free LLM API)
- Brave Search API (free tier available)
- ClawdHub Skills Registry
- nanobot GitHub (lightweight alternative)