ClawKit Logo
ClawKitReliability Toolkit

allowInsecureAuth Ignored Behind Docker / Reverse Proxy

Documentation Gap — Now Fixed

Tracked in openclaw/openclaw#1679. Setting gateway.controlUi.allowInsecureAuth: true is not sufficient when the gateway is behind a reverse proxy (Docker, Nginx, Traefik, Caddy). You also need trustedProxies to tell the gateway to trust forwarded requests.

You deployed OpenClaw in Docker behind Nginx/Traefik/Caddy. You set allowInsecureAuth: true and configured a token. But the Control UI still demands device pairing, or rejects your token with "token_missing" or "Gateway token rejected."

Next Step

Fix now, then reduce repeat incidents

If this issue keeps coming back, validate your setup in Doctor first, then harden your config.

What the Error Looks Like

When accessing the Control UI through your reverse proxy:

Device pairing required — scan QR code or enter pairing code
Error: token_missing — no authentication token found in request
Gateway token rejected — device identity not recognized
[gateway] connection from 172.18.0.1 treated as untrusted (not localhost)
allowInsecureAuth is enabled but request origin is not local

The critical clue is the IP address in the logs: 172.18.0.1 (or similar Docker bridge IP) instead of 127.0.0.1. The gateway sees the proxy's IP, not your actual client IP.

Why This Happens

1

Reverse proxy changes the source IP

When a request passes through Nginx, Traefik, or any reverse proxy, the gateway sees the proxy's internal Docker IP (172.18.0.x) as the source — not your browser's IP. The gateway treats all non-localhost connections as remote and requires full device pairing.

2

allowInsecureAuth only affects localhost connections

The allowInsecureAuth flag allows token-only authentication without device pairing, but only for connections the gateway considers "local." Without trustedProxies, connections from the Docker bridge are not considered local.

3

Token is present but ignored

Your token may be correctly set in the URL or localStorage, but the gateway's auth handler skips token validation for untrusted remote connections and jumps straight to device pairing. The token is never even checked.

The Fix: Add trustedProxies

Add trustedProxies to your gateway config. This tells the gateway to trust X-Forwarded-For headers from your proxy, making the connection appear as "local" to the auth handler.

Complete working config — clawdbot.json
{
  "gateway": {
    "mode": "local",
    "bind": "lan",
    "port": 18789,
    "trustedProxies": ["0.0.0.0/0"],
    "controlUi": {
      "enabled": true,
      "allowInsecureAuth": true
    },
    "auth": {
      "mode": "token",
      "token": "your-secure-token-here"
    }
  }
}

The key addition is "trustedProxies": ["0.0.0.0/0"]. This tells the gateway to trust forwarded headers from any IP. Combined with allowInsecureAuth: true, it enables token-only authentication without device pairing.

Apply the config and restart
# If running in Docker
docker compose restart openclaw-gateway

# If running directly
openclaw gateway restart

Config Examples by Platform

Docker Compose + Nginx

docker-compose.yml (relevant section)
services:
  openclaw-gateway:
    image: openclaw/openclaw:latest
    volumes:
      - ./clawdbot.json:/app/clawdbot.json
    ports:
      - "18789:18789"  # Only needed if not using nginx proxy_pass
    networks:
      - openclaw-net

  nginx:
    image: nginx:alpine
    ports:
      - "443:443"
    volumes:
      - ./nginx.conf:/etc/nginx/conf.d/default.conf
      - ./certs:/etc/nginx/certs
    networks:
      - openclaw-net

Unraid / StartOS

On Unraid and StartOS, the Docker network uses a custom bridge. Add the bridge subnet to trustedProxies instead of 0.0.0.0/0:

More specific trustedProxies for Unraid
"trustedProxies": ["172.16.0.0/12"]

Tailscale / WireGuard VPN

trustedProxies for Tailscale
"trustedProxies": ["100.64.0.0/10"]  // Tailscale CGNAT range

Security Considerations

When 0.0.0.0/0 is safe: If the gateway port is only reachable through your reverse proxy (Docker internal network, not exposed to host), any IP that reaches the gateway is definitionally your proxy.

When 0.0.0.0/0 is risky: If the gateway port is also exposed directly (e.g., ports: "18789:18789" in docker-compose), an attacker could forge X-Forwarded-For headers. Restrict to your proxy's actual IP range.

Always use a strong token: Generate a random token with openssl rand -hex 32. The token replaces device pairing as the primary authentication mechanism.

Verify Token Auth Works

No pairing prompt in Control UI

Expected: Open the Control UI URL — should go straight to dashboard, no QR code or pairing prompt

Token accepted in API calls
curl -H "Authorization: Bearer your-token" http://localhost:18789/api/status

Expected: Returns gateway status JSON, no 401 or "token_missing"

Logs show trusted connection
openclaw logs --tail 20 | grep -i "trusted\|auth\|token"

Expected: "connection from 172.18.0.x treated as trusted" or similar

Still Stuck?

If you still get pairing prompts after adding trustedProxies, check that your config file is actually being loaded:

Debug config loading
# Check which config file the gateway is using
openclaw config path

# Dump the effective gateway config
openclaw config get gateway

# Check if trustedProxies is present in the output
openclaw config get gateway.trustedProxies

Common gotcha: the Docker container might mount a different clawdbot.json than the one you edited. Verify with docker exec openclaw-gateway cat /app/clawdbot.json.

Run the Doctor

npx clawkit-doctor@latest

Checks gateway auth mode, trustedProxies config, token presence, and Control UI accessibility.

Did this guide solve your problem?