Files
openclaw/docs/case-study-5-phone-deployment.md
Clawd Bot ca9b510922 chore: align with upstream openclaw/openclaw and overlay local additions
- Reset master to upstream/main (16,697 commits)
- Overlay 2,271 local-only files (skills, tools, workspace, configs, apps)
- Restore IDENTITY.md and USER.md templates
- Build verified, gateway running, Discord working

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-03 07:40:46 +01:00

302 lines
11 KiB
Markdown

---
summary: "Case study: 5 cheap Android phones each running an OpenClaw gateway on a different channel"
read_when:
- Planning a multi-device distributed gateway deployment
- Wanting to spread channels across separate phones
- Budget hardware planning for an OpenClaw setup
title: "Case Study: 5-Phone Distributed Gateway"
---
# Case Study: 5-Phone Distributed Gateway
This case study walks through a real-world deployment pattern: five cheap Android phones, each
running its own OpenClaw gateway, each dedicated to one messaging channel. The result is a
distributed setup where no single device is a point of failure for all channels, and each
phone keeps its own channel account isolated.
## Scenario
| Device | Channel | Notes |
| ------- | ------------------------------ | ---------------------------------------- |
| Phone 1 | WhatsApp | WhatsApp Web (Baileys); dedicated number |
| Phone 2 | Telegram | Bot token; always-on polling |
| Phone 3 | Discord | Bot token; private server |
| Phone 4 | Signal | signal-cli + dedicated number |
| Phone 5 | SMS (iMessage/Twilio fallback) | SIM-based or Twilio; read section below |
Each gateway runs independently. There is no cross-device routing by default; each device owns
its own conversations, sessions, and workspace. Cross-channel routing (sending a WhatsApp reply
from a Telegram prompt, for example) can be added via hooks or a shared orchestration agent
but is not required for the basic setup.
## Hardware
**Device choice:** Xiaomi Redmi 9 (or equivalent mid-range Android, ~50 EUR each).
| Item | Approx. cost |
| ---------------------------- | -------------------- |
| 5x Xiaomi Redmi 9 | 5 x 50 EUR = 250 EUR |
| 5x USB chargers + cables | ~15 EUR |
| Small USB hub or power strip | ~10 EUR |
| **Total hardware** | ~275 EUR |
Any Android phone with 3 GB RAM or more works. The Redmi 9 hits the budget sweet spot: it runs
Node 22 (via Termux) comfortably, has adequate thermal performance for a background process, and
charges reliably off a USB hub.
**Why not a Raspberry Pi or VPS instead?**
- Phones already have LTE/SIM slots for the SMS/Signal use case.
- WhatsApp Web requires an active mobile-linked session; a phone holding its own WhatsApp
account stays linked without the re-link prompts that happen on a VPS after idle.
- Total cost is comparable to a Pi 4 + SIM HAT per channel.
## Software Stack (per phone)
1. **Termux** (F-Droid build recommended) -- provides the terminal, `pkg` package manager, and
persistent background process support via `termux-services`.
2. **Node 22** -- `pkg install nodejs-lts` (or build from source for exact version).
3. **OpenClaw** (stable release) -- `npm install -g openclaw`.
4. **Tailscale** -- `pkg install tailscale`; used for remote access and cross-device LAN.
Optional but useful:
- `termux-api` + Termux:API companion app: exposes SMS send/receive on the phone's SIM for
the SMS gateway device.
- `openssh` in Termux: allows SSH from your laptop for maintenance.
## Network Setup
### Local network
All five phones connect to the same home WiFi. Each gateway binds to loopback by default
(`127.0.0.1:18789`). Tailscale Serve exposes each gateway on the tailnet so you can reach
the dashboard from any device on your Tailscale network.
```
Home router (192.168.1.0/24)
Phone 1 (WhatsApp) 192.168.1.101 tailnet: phone1.your-tailnet.ts.net
Phone 2 (Telegram) 192.168.1.102 tailnet: phone2.your-tailnet.ts.net
Phone 3 (Discord) 192.168.1.103 tailnet: phone3.your-tailnet.ts.net
Phone 4 (Signal) 192.168.1.104 tailnet: phone4.your-tailnet.ts.net
Phone 5 (SMS) 192.168.1.105 tailnet: phone5.your-tailnet.ts.net
```
### Tailscale for remote access
Each phone runs Tailscale in Termux. After `tailscale up`, each phone gets a stable tailnet
hostname. The gateway dashboard (port 18789) is then reachable via Tailscale Serve:
```bash
# On each phone, one-time setup
tailscale serve --bg https+insecure://localhost:18789
```
With `gateway.tailscale.mode: "serve"` set in the OpenClaw config, OpenClaw manages this
automatically. See [Tailscale](/gateway/tailscale) for auth details.
This means you can open any phone's dashboard from your laptop even when you are away from
home, without exposing any port to the public internet.
## OpenClaw Configuration (per phone)
Each phone has its own `~/.openclaw/openclaw.json`. Here are minimal examples.
**Phone 1 -- WhatsApp:**
```json5
{
channels: {
whatsapp: {
dmPolicy: "allowlist",
allowFrom: ["+15551234567"],
},
},
gateway: {
tailscale: { mode: "serve" },
},
}
```
Run `openclaw channels login` once to scan the WhatsApp QR code. After that, the session
persists across restarts.
**Phone 2 -- Telegram:**
```json5
{
channels: {
telegram: {
enabled: true,
botToken: "<your-bot-token>",
dmPolicy: "pairing",
},
},
gateway: {
tailscale: { mode: "serve" },
},
}
```
**Phone 3 -- Discord:**
```json5
{
channels: {
discord: {
enabled: true,
token: "<raw-bot-token>",
dmPolicy: "pairing",
},
},
gateway: {
tailscale: { mode: "serve" },
},
}
```
**Phone 4 -- Signal:**
Signal requires `signal-cli` (Java-based). Install a Termux-compatible JDK (`pkg install openjdk-17`) and
download the `signal-cli` release binary. Link the bot account once:
```bash
signal-cli link -n "OpenClaw"
```
Config:
```json5
{
channels: {
signal: {
enabled: true,
account: "+15550001111",
cliPath: "/data/data/com.termux/files/usr/bin/signal-cli",
dmPolicy: "pairing",
},
},
gateway: {
tailscale: { mode: "serve" },
},
}
```
Note: `signal-cli` on Android/Termux uses more RAM than the others. Give Phone 4 a slightly
beefier device (4 GB RAM) if budget allows.
**Phone 5 -- SMS:**
SMS via the phone's own SIM uses `termux-api` to send and receive. This is a community
pattern; OpenClaw does not yet have a built-in SMS channel adapter. Alternatives:
- Use a Twilio number and the OpenClaw webhook/HTTP integration.
- Use a WhatsApp-linked number on Phone 5 as a second WhatsApp gateway instead.
For this case study, Phone 5 runs a Twilio-backed webhook adapter proxied into OpenClaw
via the HTTP API.
## Starting the Gateway (Termux)
To keep the gateway running after Termux is backgrounded, use `termux-services`:
```bash
# Enable the background service
sv-enable openclaw
sv up openclaw
```
Or use a simple `nohup` approach in a `tmux` session:
```bash
tmux new -s openclaw
nohup openclaw gateway run --bind loopback --port 18789 > ~/openclaw.log 2>&1 &
```
Check status:
```bash
openclaw channels status --probe
openclaw health
```
## How Routing Works
Each phone is a fully independent gateway. Routing within a single device is standard
OpenClaw routing: a message arrives on the configured channel, the gateway assigns it an
agent session, the agent replies on the same channel.
There is no built-in cross-phone routing. If you want a message from WhatsApp (Phone 1) to
be visible on Telegram (Phone 2), you have two options:
1. **Hooks:** configure an `outgoing` hook on Phone 1 that POSTs to Phone 2's HTTP API.
2. **Orchestration agent:** run a fifth agent that subscribes to a shared coordination
channel (e.g., a private Discord channel on Phone 3) and fans messages out.
For most personal deployments, isolation per channel is actually the desired behaviour:
each channel has its own conversation history and workspace.
## Cost Breakdown
| Item | One-time | Monthly |
| ---------------------------------------------------------- | -------- | --------------------------- |
| 5x Android phones (~50 EUR) | 275 EUR | -- |
| SIM cards (1 for Signal, 1 for SMS) | ~10 EUR | ~5-10 EUR |
| Electricity (5 phones idle, ~2W each, ~720 Wh/month total) | -- | ~0.15 EUR |
| Tailscale (Personal plan) | -- | Free |
| OpenClaw (self-hosted) | -- | Free |
| API keys (Anthropic/OpenAI) | -- | ~5-20 EUR (usage-dependent) |
| **Total** | ~285 EUR | ~10-30 EUR/month |
The dominant ongoing cost is the LLM API usage, not the infrastructure. Using a local model
(Ollama, llama.cpp) on one of the phones or a local server reduces this to near-zero for
light workloads, at the cost of response quality.
## Lessons Learned and Gotchas
**WhatsApp re-linking:** WhatsApp Web (Baileys) requires an active linked-device session.
If the phone reboots and the session cookie expires, you need to re-scan the QR. Keep the
Phone 1 screen accessible (use `scrcpy` over ADB or a small LCD). Avoid factory-resetting
the WhatsApp account; that invalidates all sessions.
**Signal and Java memory:** `signal-cli` on ARM (Termux/Android) is memory-hungry. The JVM
default heap can exceed 512 MB on some message loads. Set `JAVA_OPTS="-Xmx256m"` in your
Termux environment to cap it, and accept slightly slower startup.
**Termux wake lock:** Android aggressively kills background processes. In Termux settings,
enable "Acquire Wakelock" and add Termux to the battery optimization exclusion list for each
phone. Without this, the gateway silently dies after ~20 minutes of screen-off.
**Tailscale on Android Termux:** Tailscale in Termux runs as a userspace daemon and needs
`/dev/tun`. On some Android versions, `/dev/tun` requires root or a VPN permission. Grant
the Termux app VPN permissions in Android settings, or use the official Tailscale Android
app alongside Termux (the Tailscale app does not conflict with Termux's instance if you pick
only one approach per phone).
**Port conflicts:** each phone runs a single gateway, so there are no port conflicts. If you
later add a second gateway on the same phone (rescue-bot pattern), follow the port-spacing
rules in [Multiple Gateways](/gateway/multiple-gateways).
**SD card storage:** store sessions and workspace on internal storage, not SD card. SD card
I/O latency causes session file write delays that can corrupt JSONL session logs under load.
**Power cycling:** phones on USB hubs occasionally restart due to insufficient current. Use
a powered USB hub (minimum 2 A per port) or individual USB chargers. Unplanned reboots
trigger the WhatsApp re-link problem above.
**Network interruptions:** if home WiFi drops, Signal and Telegram reconnect automatically.
WhatsApp Web needs the gateway process to handle reconnection; OpenClaw does this internally,
but if the phone's WiFi stack stalls (common on budget Androids), a Termux `wakeup` script
via `termux-wake-lock` + a cron-style ping loop helps.
## Related Docs
- [Channels overview](/channels)
- [WhatsApp](/channels/whatsapp)
- [Telegram](/channels/telegram)
- [Discord](/channels/discord)
- [Signal](/channels/signal)
- [Tailscale](/gateway/tailscale)
- [Multiple Gateways](/gateway/multiple-gateways)
- [VPS Hosting](/vps)