11 setup steps + 13 optional enhancements. 113 findings resolved across 18 adversarial audits. Provider env vars match official auto-enable names. Every command verified against docs.openclaw.ai/cli and Pi OS Bookworm documentation.
Tap any step to expand. Work top to bottom. Copy buttons on every command block.
Hardware checklist
Find and save your laptop's local IP
192.168.1.0/24). Raspberry Pi Connect in Step 4 Part F provides browser-based backup access if locked out.Get your 4 free API keys
Create Telegram bot + get numeric user ID
Telegram → @BotFather → /newbot → copy bot token. Then @userinfobot → Start → copy numeric ID.
Prepare secrets template (becomes ~/.openclaw/.env in Step 7)
GOOGLE_API_KEY auto-enables Google provider. NVIDIA_API_KEY auto-enables NVIDIA. OPENROUTER_API_KEY auto-enables OpenRouter. TELEGRAM_BOT_TOKEN is the official OpenClaw env var for Telegram. TELEGRAM_CHAT_ID is used by the health watchdog cron only (not an OpenClaw auto-enable var).=. The health watchdog cron in Step 10 reads this file using the POSIX dot operator (. file), which breaks with spaces.Download Raspberry Pi Imager from raspberrypi.com/software.
1. Device → Raspberry Pi 5
2. OS → Raspberry Pi OS (other) → Raspberry Pi OS Lite (64-bit)
3. Storage → your SanDisk → Next → Edit Settings
pigatewaypi — scripts reference this pathClick Save → Yes → Yes. Flashing takes 5–10 min. Safely eject.
Insert SD → plug in USB-C power → wait 90 seconds.
Type yes for fingerprint. Enter password. All commands from here run inside SSH.
Part A — update, essentials, performance env vars
Part B — SSH key authentication
sshd_config starts with Include /etc/ssh/sshd_config.d/*.conf. OpenSSH uses first match wins — if any provisioning tool (Imager's firstrun.sh, cloud-init, or a manual drop-in) set PasswordAuthentication yes, the sed edit alone is insufficient. The 01-disable-password.conf drop-in ensures the correct value takes priority.Part C — fail2ban (nftables-multiport for Bookworm)
Part D — UFW firewall, home subnet
192.168.1.0/24 with your home subnet. This allows any device on your LAN (laptop, phone, tablet) to SSH in — but SSH key auth (Part B) blocks all password attempts, and fail2ban (Part C) bans brute-force. Safe on a home network.192.168.1.0/24 with individual IPs: run sudo ufw allow from 192.168.1.105 to any port 22 for each IP. Subnet is recommended for home use — you can SSH from any device without re-editing rules when DHCP assigns a new IP.Part E — automatic security updates
Part F — Raspberry Pi Connect (browser-based backup access)
connect.raspberrypi.com if you don't have one). After sign-in, your Pi appears in the Connect dashboard. Click "Connect" for a browser shell — works from any device, anywhere.curl -fsSL https://tailscale.com/install.sh | sh).log2ram (dynamic codename, SIZE=256M)
apt update fails for azlux repo (codename not found), replace $(bash -c '. /etc/os-release; echo ${VERSION_CODENAME}') with bookworm in /etc/apt/sources.list.d/azlux.list and retry.Cap journald
zram (swap in RAM)
Wi-Fi power management (NetworkManager for Bookworm)
/etc/network/interfaces method doesn't work.Disable unused services
avahi-daemon is kept running — provides .local mDNS. Disabling it breaks ssh pi@pigateway.local.Reboot + verify
Part A — create .env
Part B — inspect then install
npm install -g openclaw@latestPart C — onboarding wizard
GOOGLE_API_KEY (env var name — wizard stores ${GOOGLE_API_KEY} SecretRef)gemini-3-flash-previewmodels list --provider google shows gemini-3-flash-preview, consider it as primary — 66K output tokens and native web search. Preview, may be less stable.Part D — check which service was installed
Part E — service override (after knowing which service type)
Part F — context pruning + doctor + backup cron
openclaw config get agents.defaults.contextPruning — should show mode: "cache-ttl". If your model/provider doesn't support cache-ttl, OpenClaw falls back gracefully.PATH= line.Stage 1 — pairing
1. Telegram → find bot → send any message
2. Bot replies with code like ABC-123
3. In SSH:
4. Send another message — should respond via Gemini 3.0 Flash Preview.
Stage 2 — allowlist (JSON array format, two separate commands)
allowFrom requires a JSON array of quoted strings: '["123456789"]'. A bare number without quotes causes schema validation failure. The tg: prefix follows official convention and is normalized internally. Setting dmPolicy allowlist without allowFrom blocks all DMs.Part A — primary model + provider keys
Part B — DeepSeek (second fallback)
DEEPSEEK_API_KEY auto-enables it — no plugin or OAuth needed. Uses OpenAI-compatible API at api.deepseek.com. Ultra-low-cost: ~$0.28/M input, ~$0.40/M output. $5 credit lasts weeks of daily use.Part C — Nvidia Model
Part D — scan OpenRouter
Part E — build fallback chain
Part E — Ollama + Gemma3:1b (offline fallback)
Part F — AGENTS.md (security + memory)
Service check
CLI wrappers (always work)
Memory + services
Dashboard (run on laptop)
Final verification
secrets audit scans for plaintext residues and unresolved refs. If issues: openclaw secrets configureAll cron jobs (single crontab edit)
/usr/bin:/bin — it does not include /usr/local/bin where openclaw is installed. The PATH= line below is required as the first line in your crontab, or every openclaw command silently fails.RPC probe: ok — the definitive gateway health signal. A gateway can be systemd "active" but have a crashed RPC.If Telegram responds and openclaw gateway status shows RPC probe: ok, your agent is live.
Sign in at app.netdata.cloud, claim your Pi.
RAM-first storage (Netdata v2+ [db] section)
mode = ram in the [db] section, Netdata writes metrics every second to the SD card.Your Pi 5 is a fully working, always-on AI agent. 5-tier chain (4 free + DeepSeek ultra-low-cost) · .env secrets (provider auto-enable) · SSH key auth · fail2ban nftables-multiport · UFW subnet · Pi Connect backup access · auto security patches · log2ram 256M · NetworkManager Wi-Fi fix · pairing-first Telegram · JSON array allowlist · prompt injection guards · RPC probe cron · Netdata Cloud.
Confirm: Telegram responds, openclaw gateway status shows RPC probe: ok, all 5 fallbacks listed, Netdata shows live data.
nftables-multiport from Step 4.systemd-creds encrypts credentials into the service unit — no gpg-agent needed.Recovery options: (1) Use Raspberry Pi Connect from any browser (Step 4 Part F), (2) keyboard+monitor on Pi, (3) mount SD on another machine and edit /etc/ufw/user.rules.
${TELEGRAM_BOT_TOKEN} as part of the curl URL. After the POSIX dot sources .env, the token is expanded into the command line — visible to any local process via ps aux or /proc/*/cmdline. On a single-user Pi this is low risk, but worth hardening.ps — not its internal variables. The token lifetime in the process table is reduced to the curl duration.GOOGLE_API_KEY works (it's in the resolution chain as a fallback), but the official Google provider page and onboarding CLI flag (--gemini-api-key) use GEMINI_API_KEY. Renaming aligns with official docs and ensures compatibility with other tools expecting the canonical name.GOOGLE_API_KEY during onboarding, the SecretRef in openclaw.json references that name. After renaming in .env, run openclaw doctor --deep --fix to update refs. Or manually: openclaw config set models.providers.google.apiKey '${GEMINI_API_KEY}'~/.openclaw with default 755 permissions. The .env is correctly chmod 600, but any local user can ls ~/.openclaw/ and see filenames (openclaw.json, credentials/, etc.). On a single-user Pi this is low risk.retention = 3600 in the [db] section. Netdata v2 docs (learn.netdata.cloud) don't document this key for ram mode — it's silently ignored. Ram mode defaults to ~3600 samples anyway, so functionally this changes nothing.grep -q … || guards, preventing duplicate lines. This cleanup is only needed if you previously ran v16 or earlier without the guards./etc/NetworkManager/conf.d/ config file. This works, but the Raspberry Pi community and official Bookworm guides recommend nmcli as the canonical method.nmcli approach modifies the connection profile directly.