Documentation Index
Fetch the complete documentation index at: https://docs.openclaw.ai/llms.txt
Use this file to discover all available pages before exploring further.
When to use
Usetrusted-proxy auth mode when:
- You run OpenClaw behind an identity-aware proxy (Pomerium, Caddy + OAuth, nginx + oauth2-proxy, Traefik + forward auth).
- Your proxy handles all authentication and passes user identity via headers.
- You’re in a Kubernetes or container environment where the proxy is the only path to the Gateway.
- You’re hitting WebSocket
1008 unauthorizederrors because browsers can’t pass tokens in WS payloads.
When NOT to use
- If your proxy doesn’t authenticate users (just a TLS terminator or load balancer).
- If there’s any path to the Gateway that bypasses the proxy (firewall holes, internal network access).
- If you’re unsure whether your proxy correctly strips/overwrites forwarded headers.
- If you only need personal single-user access (consider Tailscale Serve + loopback for simpler setup).
How it works
Proxy adds an identity header
Proxy adds a header with the authenticated user identity (e.g.,
x-forwarded-user: nick@example.com).Gateway verifies trusted source
OpenClaw checks that the request came from a trusted proxy IP (configured in
gateway.trustedProxies).Control UI pairing behavior
Whengateway.auth.mode = "trusted-proxy" is active and the request passes trusted-proxy checks, Control UI WebSocket sessions can connect without device pairing identity.
Implications:
- Pairing is no longer the primary gate for Control UI access in this mode.
- Your reverse proxy auth policy and
allowUsersbecome the effective access control. - Keep gateway ingress locked to trusted proxy IPs only (
gateway.trustedProxies+ firewall).
Configuration
Configuration reference
Array of proxy IP addresses to trust. Requests from other IPs are rejected.
Must be
"trusted-proxy".Header name containing the authenticated user identity.
Additional headers that must be present for the request to be trusted.
Allowlist of user identities. Empty means allow all authenticated users.
Opt-in support for same-host loopback reverse proxies. Defaults to
false.TLS termination and HSTS
Use one TLS termination point and apply HSTS there.- Proxy TLS termination (recommended)
- Gateway TLS termination
When your reverse proxy handles HTTPS for
https://control.example.com, set Strict-Transport-Security at the proxy for that domain.- Good fit for internet-facing deployments.
- Keeps certificate + HTTP hardening policy in one place.
- OpenClaw can stay on loopback HTTP behind the proxy.
Rollout guidance
- Start with a short max age first (for example
max-age=300) while validating traffic. - Increase to long-lived values (for example
max-age=31536000) only after confidence is high. - Add
includeSubDomainsonly if every subdomain is HTTPS-ready. - Use preload only if you intentionally meet preload requirements for your full domain set.
- Loopback-only local development does not benefit from HSTS.
Proxy setup examples
Pomerium
Pomerium
Pomerium passes identity in Pomerium config snippet:
x-pomerium-claim-email (or other claim headers) and a JWT in x-pomerium-jwt-assertion.Caddy with OAuth
Caddy with OAuth
Caddy with the Caddyfile snippet:
caddy-security plugin can authenticate users and pass identity headers.nginx + oauth2-proxy
nginx + oauth2-proxy
oauth2-proxy authenticates users and passes identity in nginx config snippet:
x-auth-request-email.Traefik with forward auth
Traefik with forward auth
Mixed token configuration
OpenClaw rejects ambiguous configurations where both agateway.auth.token (or OPENCLAW_GATEWAY_TOKEN) and trusted-proxy mode are active at the same time. Mixed token configs can cause loopback requests to silently authenticate on the wrong auth path.
If you see a mixed_trusted_proxy_token error on startup:
- Remove the shared token when using trusted-proxy mode, or
- Switch
gateway.auth.modeto"token"if you intend token-based auth.
gateway.auth.password / OPENCLAW_GATEWAY_PASSWORD instead. Token fallback remains intentionally unsupported in trusted-proxy mode.
Operator scopes header
Trusted-proxy auth is an identity-bearing HTTP mode, so callers may optionally declare operator scopes withx-openclaw-scopes.
Examples:
x-openclaw-scopes: operator.readx-openclaw-scopes: operator.read,operator.writex-openclaw-scopes: operator.admin,operator.write
- When the header is present, OpenClaw honors the declared scope set.
- When the header is present but empty, the request declares no operator scopes.
- When the header is absent, normal identity-bearing HTTP APIs fall back to the standard operator default scope set.
- Gateway-auth plugin HTTP routes are narrower by default: when
x-openclaw-scopesis absent, their runtime scope falls back tooperator.write. - Browser-origin HTTP requests still have to pass
gateway.controlUi.allowedOrigins(or deliberate Host-header fallback mode) even after trusted-proxy auth succeeds.
x-openclaw-scopes explicitly when you want a trusted-proxy request to be narrower than the defaults, or when a gateway-auth plugin route needs something stronger than write scope.
Security checklist
Before enabling trusted-proxy auth, verify:- Proxy is the only path: The Gateway port is firewalled from everything except your proxy.
- trustedProxies is minimal: Only your actual proxy IPs, not entire subnets.
- Loopback proxy source is deliberate: trusted-proxy auth fails closed for loopback-source requests unless
gateway.auth.trustedProxy.allowLoopbackis explicitly enabled for a same-host proxy. - Proxy strips headers: Your proxy overwrites (not appends)
x-forwarded-*headers from clients. - TLS termination: Your proxy handles TLS; users connect via HTTPS.
- allowedOrigins is explicit: Non-loopback Control UI uses explicit
gateway.controlUi.allowedOrigins. - allowUsers is set (recommended): Restrict to known users rather than allowing anyone authenticated.
- No mixed token config: Do not set both
gateway.auth.tokenandgateway.auth.mode: "trusted-proxy". - Local password fallback is private: If you configure
gateway.auth.passwordfor internal direct callers, keep the Gateway port firewalled so non-proxy remote clients cannot reach it directly.
Security audit
openclaw security audit will flag trusted-proxy auth with a critical severity finding. This is intentional — it’s a reminder that you’re delegating security to your proxy setup.
The audit checks for:
- Base
gateway.trusted_proxy_authwarning/critical reminder - Missing
trustedProxiesconfiguration - Missing
userHeaderconfiguration - Empty
allowUsers(allows any authenticated user) - Enabled
allowLoopbackfor same-host proxy sources - Wildcard or missing browser-origin policy on exposed Control UI surfaces
Troubleshooting
trusted_proxy_untrusted_source
trusted_proxy_untrusted_source
The request didn’t come from an IP in
gateway.trustedProxies. Check:- Is the proxy IP correct? (Docker container IPs can change.)
- Is there a load balancer in front of your proxy?
- Use
docker inspectorkubectl get pods -o wideto find actual IPs.
trusted_proxy_loopback_source
trusted_proxy_loopback_source
OpenClaw rejected a loopback-source trusted-proxy request.Check:
- Is the proxy connecting from
127.0.0.1/::1? - Are you trying to use trusted-proxy auth with a same-host loopback reverse proxy?
- Prefer token/password auth for internal same-host clients that do not go through the proxy, or
- Route through a non-loopback trusted proxy address and keep that IP in
gateway.trustedProxies, or - For a deliberate same-host reverse proxy, set
gateway.auth.trustedProxy.allowLoopback = true, keep the loopback address ingateway.trustedProxies, and make sure the proxy strips or overwrites identity headers.
trusted_proxy_user_missing
trusted_proxy_user_missing
The user header was empty or missing. Check:
- Is your proxy configured to pass identity headers?
- Is the header name correct? (case-insensitive, but spelling matters)
- Is the user actually authenticated at the proxy?
trusted_proxy_missing_header_*
trusted_proxy_missing_header_*
A required header wasn’t present. Check:
- Your proxy configuration for those specific headers.
- Whether headers are being stripped somewhere in the chain.
trusted_proxy_user_not_allowed
trusted_proxy_user_not_allowed
The user is authenticated but not in
allowUsers. Either add them or remove the allowlist.trusted_proxy_origin_not_allowed
trusted_proxy_origin_not_allowed
Trusted-proxy auth succeeded, but the browser
Origin header did not pass Control UI origin checks.Check:gateway.controlUi.allowedOriginsincludes the exact browser origin.- You are not relying on wildcard origins unless you intentionally want allow-all behavior.
- If you intentionally use Host-header fallback mode,
gateway.controlUi.dangerouslyAllowHostHeaderOriginFallback=trueis set deliberately.
WebSocket still failing
WebSocket still failing
Make sure your proxy:
- Supports WebSocket upgrades (
Upgrade: websocket,Connection: upgrade). - Passes the identity headers on WebSocket upgrade requests (not just HTTP).
- Doesn’t have a separate auth path for WebSocket connections.
Migration from token auth
If you’re moving from token auth to trusted-proxy:Related
- Configuration — config reference
- Remote access — other remote access patterns
- Security — full security guide
- Tailscale — simpler alternative for tailnet-only access