Multi-region automation fails when someone “temporarily” binds the gateway on 0.0.0.0 to demo a dashboard. The pattern below is boring on purpose: the only process that speaks HTTP to the world is whatever you place in front of the tunnel exit, and OpenClaw itself never acquires a routable socket. Pair the layout with the GeoDNS and SSH latency matrix when you choose PoPs, and with split-horizon versus GeoDNS stickiness when DNS answers must not flap under CI. Use Pricing to keep builders and gateways in the same region you already measured.
Security boundaries (read before ssh -R)
Loopback is the trust anchor. Configure OpenClaw so its admin and inference gateway listen only on 127.0.0.1 (or an abstract UNIX socket if your build supports it). The SSH client on the workload host then opens a remote forward so the bastion’s loopback inherits a port that proxies back to OpenClaw. Nothing else on the LAN needs a route to the model host.
Non-loopback listeners require authentication by policy. If you ever promote a listener to a non-loopback address—because a legacy load balancer insists on binding a real interface, or because a platform agent hardcodes 0.0.0.0—treat that as a red-team exercise: the surface is now reachable without the tunnel’s key exchange, so you must enforce bearer tokens, mutual TLS, or an OAuth proxy before traffic hits OpenClaw. Narratively, our rule is simple: “loopback plus tunnel” is the default posture; “anything else” ships only behind an auth gateway you could show an auditor. Document the exception in the same ticket that adds firewall rules.
- Bastion is the only public pivot. Security groups or
pf/nftrules should allow the forwarded port only from your edge load balancer or break-glass IPs, not from the whole Internet unless you intentionally run a public demo. - One region, one tunnel owner. Each vpshalo PoP terminates on its own bastion account so a stolen key in Tokyo cannot pivot to Singapore’s
OPENCLAW_HOME. - No shared
OPENCLAW_HOMEover NFS. Reuse the isolation advice from other OpenClaw write-ups: journals and API caches stay local to the Mac or Linux host that runs the model.
Minimal reproducible steps
Perform these steps once per region. Names are examples; substitute your inventory tags.
- Step 1 — Fix OpenClaw on loopback. Set
OPENCLAW_HOME=/var/lib/openclaw/<region>(or the macOS equivalent under/usr/local/var) and start OpenClaw with explicit bind flags so HTTP and any metrics port attach to127.0.0.1:18080only. Verify withcurl http://127.0.0.1:18080/healthzfrom localhost. - Step 2 — Create a dedicated tunnel user on the bastion. On the vpshalo bastion, provision a locked-down POSIX user whose sole job is to accept the reverse forward. Enable
AllowTcpForwarding yesbut disable shell access for automated keys if your sshd supports command restrictions. - Step 3 — Open the reverse tunnel from the workload host. From the OpenClaw host, run a long-lived SSH session similar to
ssh -N -o ServerAliveInterval=30 -R 127.0.0.1:7443:127.0.0.1:18080 tunnel@bastion-sin.example. Binding the remote side to127.0.0.1keeps the forwarded port off the bastion’s public interfaces; promote to0.0.0.0only if you also layer TLS termination and auth at the edge. - Step 4 — Front the bastion port. Terminate TLS on nginx, Caddy, or Envoy, then proxy to
127.0.0.1:7443. Issue certificates per region so a compromise in DNS does not reuse a single wildcard everywhere. - Step 5 — Automate resurrection. Wrap the SSH command in systemd, launchd, or a small supervisor that backs off exponentially on failure and alerts after three consecutive crashes—tunnel flaps are how operators accidentally open permissive firewalls “just to debug.”
# Workload host (inside your CI image or remote Mac): loopback health only
curl -fsS --max-time 2 http://127.0.0.1:18080/healthz
# Bastion: prove the tunnel lands locally before exposing TLS
curl -fsS --max-time 2 http://127.0.0.1:7443/healthz
Token rotation without tearing the tunnel
SSH host keys should rotate rarely, but API tokens for upstream models and webhook receivers should rotate often. Store secrets in a vault; render a short-lived env file into the systemd unit before reload. Rotation playbook: (1) mint the new token, (2) write it beside the old one under OPENCLAW_HOME/secrets.d/next, (3) signal OpenClaw to reload if supported, otherwise restart the process—loopback binding means the restart does not change firewall posture, (4) revoke the previous token after five minutes of green metrics. Schedule the same chore across regions with a stagger so Tokyo and Singapore never reload simultaneously unless you are in a maintenance window documented in Help center runbooks.
Health probes and merged paging
Each region should emit the same JSON shape: region, lane (loopback, tunnel, edge_https), rtt_ms, and error_class. A tiny merge worker (fifteen lines of Python or a scheduled query in your metrics store) collapses events inside a sliding five-minute bucket. Page once when all lanes fail in a single region; escalate to “multi-region” only when at least two regions lose the tunnel lane within the same bucket. That single alert carries the deduplicated evidence instead of three separate pages for the same SSH flap.
- Lane A — loopback on the model host. Cheap, runs every minute from localhost.
- Lane B — bastion to forwarded port. Exercises the reverse tunnel without touching the public Internet.
- Lane C — synthetic HTTPS through the edge. Low frequency (every five minutes) so you do not confuse TLS rate limits with OpenClaw outages.
Backoff repeat pages exponentially, identical to the MagicDNS article’s guidance, but the merge worker’s input is now purely SSH and HTTPS—no tailnet identity required.
FAQ
Why not just use Tailscale? Some regulated tenants forbid overlay meshes on builder subnets. SSH reverse forwarding reuses skills you already audit, and it keeps DNS simple. When the mesh is allowed again, migrate to the MagicDNS playbook without renaming OPENCLAW_HOME.
Does GatewayPorts make this unsafe? Only if you bind 0.0.0.0 without an auth layer. Keep remote forwards on 127.0.0.1 and let nginx handle client certificates.
How do probes authenticate? Issue a dedicated probe token stored next to the merge worker, not on developer laptops. Rotate it with the same schedule as model API keys.
What breaks first during outages? Usually the SSH keepalive, not OpenClaw. Train on-call to restart the tunnel service before touching model weights.
When the steps above are scripted, you get a reproducible perimeter: loopback inside each vpshalo region, a narrow tunnel, explicit auth if anything ever leaves loopback, predictable token churn, and alert noise that scales with real incidents instead of probe cardinality. That is enough to ship confidently while you decide whether overlay DNS is worth the operational lift.