OpenClaw via Cloudflare Tunnel + Cloudflare Access¶
Host: SRV1 (10.0.20.30)
Public URL: https://openclaw.gntech.me
Tunnel: Cloudflare Tunnel (cloudflared systemd service)
Auth: Cloudflare Access (Azure AD) — gateway auth disabled
Architecture¶
[Browser] ── HTTPS ──▶ [Cloudflare Edge]
│
Cloudflare Access (Azure AD)
│
Cloudflare Tunnel (cloudflared)
│
┌────────▼────────┐
│ cloudflared │
│ systemd service│
│ localhost:18789│
└────────┬────────┘
│
┌────────▼────────┐
│ OpenClaw GW │
│ port 18789 │
│ loopback bind │
│ auth: none │
│ trustedProxies:│
│ Cloudflare IPs │
└─────────────────┘
- User hits
https://openclaw.gntech.me - Cloudflare Access prompts for authentication (Azure AD)
- After auth, Access injects a
Cf-Access-Jwt-Assertionheader - Cloudflare Tunnel forwards the request to
localhost:18789 - OpenClaw gateway trusts Cloudflare source IPs, auth is bypassed
- No gateway password prompt — Cloudflare Access is the sole auth layer
Components¶
1. cloudflared (systemd service)¶
- Binary:
/usr/bin/cloudflared - Service:
cloudflared.service(system-wide, enabled) - Run mode:
--no-autoupdate tunnel run --token <TOKEN>(token-based, no config file) - Origin:
http://localhost:18789(OpenClaw gateway) - Auto-update: Separate
cloudflared-update.timer(daily, restarts service on update) - Reference:
/etc/systemd/system/cloudflared.service
2. OpenClaw Gateway¶
- Port:
18789 - Bind:
loopback(only accessible from localhost / cloudflared) - Auth mode:
none(authentication fully delegated to Cloudflare Access) - Trusted proxies:
127.0.0.1,::1+ full Cloudflare IPv4 ranges
⚠️ When
gateway.auth.modeisnone, do NOT expose port 18789 directly to the internet. The only access should be through Cloudflare Tunnel + Access.
3. Cloudflare Access Application¶
- Application type: Self-hosted
- Domain:
openclaw.gntech.me - Auth providers: Azure AD (configured in Cloudflare Zero Trust dashboard → Access → Applications)
Installation / Replication¶
Step 1 — Install cloudflared¶
curl -L https://github.com/cloudflare/cloudflared/releases/latest/download/cloudflared-linux-amd64.deb -o /tmp/cloudflared.deb
dpkg -i /tmp/cloudflared.deb
Step 2 — Create a tunnel¶
- Go to Cloudflare Zero Trust → Networks > Tunnels
- Create a new tunnel → Cloudflared → name it
- Under Public Hostnames, add a hostname pointing to
http://localhost:18789 - Copy the tunnel token
Step 3 — Install tunnel as system service¶
cloudflared service install <TUNNEL_TOKEN>
systemctl enable cloudflared
systemctl start cloudflared
Step 4 — Install OpenClaw gateway¶
# Start the gateway once to create the config
openclaw gateway start
Step 5 — Configure Cloudflare Access¶
- In Cloudflare Zero Trust → Access > Applications
- Add an application → Self-hosted
- Application domain:
openclaw.gntech.me - Set identity providers (Azure AD, Google, etc.) and access policies
Step 6 — Configure openclaw.json¶
Edit ~/.openclaw/openclaw.json. Set auth to none and add Cloudflare IP ranges to trustedProxies. This tells the gateway to skip IP-based auth for requests arriving through the tunnel.
{
"gateway": {
"mode": "local",
"bind": "loopback",
"port": 18789,
"auth": {
"mode": "none"
},
"trustedProxies": [
"127.0.0.1",
"::1",
"173.245.48.0/20",
"103.21.244.0/22",
"103.22.200.0/22",
"103.31.4.0/22",
"141.101.64.0/18",
"108.162.192.0/18",
"190.93.240.0/20",
"188.114.96.0/20",
"197.234.240.0/22",
"198.41.128.0/17",
"162.158.0.0/15",
"104.16.0.0/13",
"104.24.0.0/14",
"172.64.0.0/13",
"131.0.72.0/22"
],
"controlUi": {
"allowInsecureAuth": true,
"allowedOrigins": ["https://openclaw.gntech.me"]
},
"nodes": {
"denyCommands": [
"camera.snap", "camera.clip", "screen.record",
"contacts.add", "calendar.add", "reminders.add",
"sms.send", "sms.search"
]
}
}
}
Why whitelist Cloudflare IPs? Without this, every request through the tunnel appears to come from a Cloudflare edge IP, which changes frequently. The allowlist tells OpenClaw "skip IP-based checks for these known Cloudflare ranges" — otherwise you'd get a new auth prompt every time your mobile IP changes.
Step 7 — Restart gateway¶
systemctl --user restart openclaw-gateway.service
Step 8 — Verify¶
Visit https://openclaw.gntech.me in a browser:
- You should be prompted by Cloudflare Access (Azure AD login)
- After login, the OpenClaw dashboard loads without a second password prompt
- Test from mobile data (different IP) — should also work without prompts
Gateway Config (current)¶
{
"gateway": {
"mode": "local",
"bind": "loopback",
"port": 18789,
"auth": {
"mode": "none"
},
"trustedProxies": [
"127.0.0.1", "::1",
"173.245.48.0/20", "103.21.244.0/22",
"103.22.200.0/22", "103.31.4.0/22",
"141.101.64.0/18", "108.162.192.0/18",
"190.93.240.0/20", "188.114.96.0/20",
"197.234.240.0/22", "198.41.128.0/17",
"162.158.0.0/15", "104.16.0.0/13",
"104.24.0.0/14", "172.64.0.0/13",
"131.0.72.0/22"
],
"controlUi": {
"allowInsecureAuth": true,
"allowedOrigins": ["https://openclaw.gntech.me"]
},
"nodes": {
"denyCommands": [
"camera.snap", "camera.clip", "screen.record",
"contacts.add", "calendar.add", "reminders.add",
"sms.send", "sms.search"
]
}
}
}
Troubleshooting¶
Check cloudflared status¶
systemctl status cloudflared
journalctl -u cloudflared -n 50 --no-pager
Check gateway logs¶
journalctl --user -u openclaw-gateway.service -n 50 --no-pager
Gateway unreachable errors¶
Unable to reach the origin service: dial tcp [::1]:18789: connect: connection refused
This means cloudflared is running but the OpenClaw gateway is down. Restart:
systemctl --user restart openclaw-gateway.service
Still getting password prompt¶
If the gateway prompts for a password despite auth: none, check:
1. Config is saved correctly (verify with cat ~/.openclaw/openclaw.json | grep '"mode"')
2. Gateway was restarted after config change
3. Cloudflare Access policy is active for openclaw.gntech.me
4. You're hitting the tunnel URL, not a direct IP/port
Verifying Cloudflare IP trust¶
The gateway accepts requests from any IP in the trustedProxies list. To confirm your request comes through Cloudflare:
journalctl --user -u openclaw-gateway.service --since "5 min ago" | grep -i "trusted\|proxy\|cf-"