A tiny, single-binary HTTP service for out-of-band management of an OpenClaw gateway. Designed to run alongside the gateway as a systemd service behind a Cloudflare Tunnel with Zero Trust access.
GET /— Web UI with live gateway status, health history bar, restart button, and doctorGET /health— No auth. Returns{"ok":true}if ops-gateway itself is aliveGET /status— Authenticated. Returns current gateway status + 1-hour health historyPOST /restart— Authenticated. Restarts the gateway viasystemctl --user restart openclaw-gatewayPOST /doctor— Authenticated. Runsopenclaw doctor(add?fix=truefor--fix)
Download the latest binary for your platform from the releases page:
# Linux amd64
curl -LO https://github.com/aweiker/ops-gateway/releases/latest/download/ops-gateway-linux-amd64
chmod +x ops-gateway-linux-amd64
sudo mv ops-gateway-linux-amd64 /usr/local/bin/ops-gatewayAvailable architectures: linux/amd64, linux/arm64, darwin/amd64, darwin/arm64, freebsd/amd64.
go install github.com/aweiker/ops-gateway@latestOr clone and build:
git clone https://github.com/aweiker/ops-gateway.git
cd ops-gateway
go build -o ops-gateway .Two mechanisms (either works):
- Cloudflare Access (Zero Trust) — email-based OTP, session lasts 24h. Ideal for phone access.
- Bearer token —
Authorization: Bearer <token>header. For automation/scripts.
| Variable | Default | Description |
|---|---|---|
OPS_TOKEN |
(required) | Bearer token for API authentication |
OPS_PORT |
18790 |
Listen port (binds to 127.0.0.1) |
OPENCLAW_BIN |
openclaw |
Path to the OpenClaw CLI binary |
export OPS_TOKEN="$(openssl rand -hex 32)"
./ops-gateway[Unit]
Description=Ops Gateway
[Service]
Type=simple
ExecStart=/usr/local/bin/ops-gateway
EnvironmentFile=/path/to/env
Restart=always
[Install]
WantedBy=default.target- Create a tunnel:
cloudflared tunnel create ops - Route DNS: create a CNAME record pointing to
<tunnel-id>.cfargotunnel.com - Create an Access application for the hostname
- Add an Access policy (e.g., email allowlist)
tunnel: <tunnel-id>
credentials-file: /path/to/credentials.json
ingress:
- hostname: ops.example.com
service: http://127.0.0.1:18790
- service: http_status:404The included watchdog.sh is a companion script designed to run as a systemd timer (every 2 minutes):
- Checks gateway health via HTTP and systemd
- Auto-restarts after 3 consecutive failures
- Sends Telegram alerts on failure/recovery (bypasses OpenClaw entirely)
[Timer]
OnBootSec=1min
OnUnitActiveSec=2minPhone/Browser
│
▼ (HTTPS)
Cloudflare Access (Zero Trust)
│
▼ (authenticated)
Cloudflare Tunnel
│
▼ (localhost)
ops-gateway (:18790)
│
├──▶ systemctl restart openclaw-gateway
├──▶ openclaw doctor [--fix]
└──▶ systemctl is-active openclaw-gateway
Zero dependencies beyond Go stdlib. ~250 lines.
MIT
