Skip to content

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 │
                    └─────────────────┘
  1. User hits https://openclaw.gntech.me
  2. Cloudflare Access prompts for authentication (Azure AD)
  3. After auth, Access injects a Cf-Access-Jwt-Assertion header
  4. Cloudflare Tunnel forwards the request to localhost:18789
  5. OpenClaw gateway trusts Cloudflare source IPs, auth is bypassed
  6. 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.mode is none, 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

  1. Go to Cloudflare Zero TrustNetworks > Tunnels
  2. Create a new tunnel → Cloudflared → name it
  3. Under Public Hostnames, add a hostname pointing to http://localhost:18789
  4. 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

  1. In Cloudflare Zero TrustAccess > Applications
  2. Add an applicationSelf-hosted
  3. Application domain: openclaw.gntech.me
  4. 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-"