Skill: ember-claw/failover-gateway-pub (version 1.0.0)

--- name: failover-gateway version: 1.0.0 description: Set up an active-passive failover gateway for OpenClaw. Deploy a standby node that auto-promotes when your primary goes down and auto-demotes when it recovers. Includes health monitor script, systemd services, channel splitting strategy, and step-by-step deployment guide. Use when you need high availability, disaster recovery, or redundancy for your OpenClaw instance. --- # Failover Gateway for OpenClaw Deploy a standby OpenClaw gateway that automatically takes over when your primary goes down. Active-passive design with auto-promotion and auto-demotion. ## What You Get - **~30 second failover** — health monitor detects primary down, promotes standby - **Auto-recovery** — when primary comes back, standby demotes itself - **Zero split-brain** — primary and standby use different channels (no duplicate messages) - **Git-synced workspace** — standby pulls latest workspace on promotion - **$12/month** — runs on a minimal VPS ## Architecture ``` PRIMARY (your main VPS) STANDBY (failover VPS) ├─ Full stack (all channels) ├─ Single channel only (e.g., Discord DM) ├─ All cron jobs ├─ No crons (recovery mode) ├─ Gateway active ✅ ├─ Gateway stopped 💤 └─ Pushes workspace to git └─ Health monitor watches primary │ ├─ Primary healthy → sleep ├─ Primary down 30s → PROMOTE └─ Primary back → DEMOTE ``` The key insight: **split your channels between primary and standby**. Don't share credentials — give each node exclusive ownership of different channels. This eliminates split-brain entirely. ### Channel Split Examples | Setup | Primary | Standby | |-------|---------|---------| | RC + Discord | Rocket.Chat (full) | Discord DM only | | Discord + Telegram | Discord (full) | Telegram DM only | | Slack + Discord | Slack (full) | Discord DM only | Your primary handles everything. The standby is minimal recovery — just enough to stay reachable. ## Prerequisites - Primary OpenClaw instance running on a VPS - A second VPS for the standby ($6-12/mo, any provider) - [Tailscale](https://tailscale.com) mesh network (or any VPN/private network) - Git repository for workspace sync (GitHub, GitLab, etc.) - A second messaging channel for the standby (different from primary) ## Step-by-Step Deployment ### Phase 1: Provision the Standby VPS Any cheap VPS works. Recommended: 2GB RAM, Ubuntu 24.04. ```bash # Harden the box ufw allow 22/tcp ufw enable apt install -y fail2ban unattended-upgrades # Create openclaw user adduser openclaw --disabled-password usermod -aG sudo openclaw # Copy your SSH key to openclaw user # Install Tailscale curl -fsSL https://tailscale.com/install.sh | sh tailscale up --hostname=your-failover-name ``` ### Phase 2: Install OpenClaw ```bash # As openclaw user curl -fsSL https://raw.githubusercontent.com/nvm-sh/nvm/v0.40.3/install.sh | bash source ~/.bashrc nvm install --lts npm install -g openclaw # Clone workspace git clone <your-workspace-repo> ~/.openclaw/workspace ``` ### Phase 3: Failover Config Create a **minimal** OpenClaw config on the standby. Only enable the standby channel: ```json { "agents": { "defaults": { "model": { "primary": "anthropic/claude-opus-4-6", "fallbacks": ["anthropic/claude-sonnet-4-5"] }, "workspace": "/home/openclaw/.openclaw/workspace" }, "list": [{ "id": "main", "default": true }] }, "channels": { "discord": { "enabled": true, "token": "<YOUR_DISCORD_BOT_TOKEN>", "dm": { "policy": "allowlist", "allowFrom": ["<YOUR_DISCORD_USER_ID>"] } } }, "gateway": { "port": 18789, "mode": "local", "bind": "tailnet" } } ``` **Important:** Disable this channel on your primary to avoid conflicts. Test it works: `openclaw gateway run` — verify the bot connects and responds, then stop it. ### Phase 4: Deploy Health Monitor Copy the included `scripts/health-monitor.sh` to the standby: ```bash sudo cp health-monitor.sh /usr/local/bin/openclaw-health-monitor.sh sudo chmod +x /usr/local/bin/openclaw-health-monitor.sh ``` Edit the variables at the top: - `PRIMARY_IP` — your primary's Tailscale IP - `PRIMARY_PORT` — your primary's gateway port (default: 18789) - `SECRETS_HOST` — (optional) host to rsync secrets from on promotion Create the systemd services: **`/etc/systemd/system/openclaw-health-monitor.service`** ```ini [Unit] Description=OpenClaw Failover Health Monitor After=network-online.target tailscaled.service Wants=network-online.target [Service] Type=simple ExecStart=/usr/local/bin/openclaw-health-monitor.sh Restart=always RestartSec=10 [Install] WantedBy=multi-user.target ``` **`/etc/systemd/system/openclaw.service`** ```ini [Unit] Description=OpenClaw Gateway (Failover) After=network-online.target tailscaled.service Wants=network-online.target [Service] Type=simple User=openclaw Group=openclaw WorkingDirectory=/home/openclaw/.openclaw/workspace ExecStart=/usr/bin/openclaw gateway run Restart=on-failure RestartSec=5 Environment=HOME=/home/openclaw Environment=NODE_ENV=production [Install] WantedBy=multi-user.target ``` Enable the monitor (but NOT the gateway — the monitor starts it on promotion): ```bash sudo systemctl daemon-reload sudo systemctl enable openclaw-health-monitor sudo systemctl start openclaw-health-monitor # Do NOT enable openclaw.service — the monitor controls it ``` ### Phase 5: Disable Standby Channel on Primary This is critical. Remove or disable the standby's channel from your primary config: ```json { "channels": { "discord": { "enabled": false } } } ``` Each node owns its channels exclusively. No sharing, no conflicts. ### Phase 6: Test ```bash # On primary — simulate failure sudo systemctl stop openclaw-gateway # or kill the process # Watch the standby logs journalctl -u openclaw-health-monitor -f # Expected: 3 failed checks → PROMOTE → gateway starts → standby channel live # On primary — recover sudo systemctl start openclaw-gateway # Expected: standby detects primary → DEMOTE → gateway stops ``` ## Failover Timeline | Time | Event | |------|-------| | 0s | Primary goes down | | 10s | First health check fails | | 20s | Second check fails | | 30s | Third check fails → **PROMOTE** | | 35s | Git pull, secrets sync | | 40s | Gateway starting | | 45s | Standby channel active | | ~60s | **You're reachable again** | ## Edge Cases | Scenario | Result | |----------|--------| | Primary dies | Standby promotes in ~30-60s | | Primary + standby die | You're offline (add a third node?) | | Network partition | Standby may promote while primary is still running — but since they use different channels, no conflicts | | Standby reboots | Health monitor auto-restarts (systemd), resumes watching | | Primary flaps | Promote/demote cycles — health monitor handles it, but consider increasing FAIL_THRESHOLD | ## Failback Recovery is automatic. When the primary comes back: 1. Health monitor detects primary healthy 2. Stops the standby gateway 3. Primary resumes all channels 4. Standby returns to watching No manual intervention needed. ## Cost | Component | Cost | |-----------|------| | VPS (2GB RAM) | $6-12/mo | | Tailscale | Free (personal) | | Git repo | Free | | **Total** | **$6-12/mo** | ## Tips - **Test monthly.** Kill your primary, verify failover works. Trust but verify. - **Keep the standby minimal.** No crons, no extra channels. It's recovery mode. - **Git push frequently.** The standby's workspace is only as fresh as your last push. - **Use Tailscale.** It makes cross-VPS networking trivial. No firewall rules, no port forwarding. - **Different bot tokens.** If using Discord on both, you need two bot applications. Same bot [REDACTED_SECRET] - **Monitor the monitor.** Check `journalctl -u openclaw-health-monitor` occasionally to make sure it's running.


Security scan verdicts — ClawScan: suspicious | static analysis: clean | VirusTotal: suspicious | SkillSpector: suspicious (CRITICAL)