diff --git a/docs/docs.json b/docs/docs.json index af750f0bc8e..57205e8d9dd 100644 --- a/docs/docs.json +++ b/docs/docs.json @@ -786,6 +786,10 @@ { "source": "/platforms/northflank", "destination": "/install/northflank" + }, + { + "source": "/gateway/trusted-proxy", + "destination": "/gateway/trusted-proxy-auth" } ], "navigation": { @@ -1106,6 +1110,7 @@ "gateway/configuration-reference", "gateway/configuration-examples", "gateway/authentication", + "gateway/trusted-proxy-auth", "gateway/health", "gateway/heartbeat", "gateway/doctor", diff --git a/docs/gateway/configuration-reference.md b/docs/gateway/configuration-reference.md index 8c58cd4e94a..0655cb3860f 100644 --- a/docs/gateway/configuration-reference.md +++ b/docs/gateway/configuration-reference.md @@ -1889,9 +1889,10 @@ See [Plugins](/tools/plugin). port: 18789, bind: "loopback", auth: { - mode: "token", // token | password + mode: "token", // token | password | trusted-proxy token: "your-token", // password: "your-password", // or OPENCLAW_GATEWAY_PASSWORD + // trustedProxy: { userHeader: "x-forwarded-user" }, // for mode=trusted-proxy; see /gateway/trusted-proxy-auth allowTailscale: true, rateLimit: { maxAttempts: 10, @@ -1934,6 +1935,7 @@ See [Plugins](/tools/plugin). - `port`: single multiplexed port for WS + HTTP. Precedence: `--port` > `OPENCLAW_GATEWAY_PORT` > `gateway.port` > `18789`. - `bind`: `auto`, `loopback` (default), `lan` (`0.0.0.0`), `tailnet` (Tailscale IP only), or `custom`. - **Auth**: required by default. Non-loopback binds require a shared token/password. Onboarding wizard generates a token by default. +- `auth.mode: "trusted-proxy"`: delegate auth to an identity-aware reverse proxy and trust identity headers from `gateway.trustedProxies` (see [Trusted Proxy Auth](/gateway/trusted-proxy-auth)). - `auth.allowTailscale`: when `true`, Tailscale Serve identity headers satisfy auth (verified via `tailscale whois`). Defaults to `true` when `tailscale.mode = "serve"`. - `auth.rateLimit`: optional failed-auth limiter. Applies per client IP and per auth scope (shared-secret and device-token are tracked independently). Blocked attempts return `429` + `Retry-After`. - `auth.rateLimit.exemptLoopback` defaults to `true`; set `false` when you intentionally want localhost traffic rate-limited too (for test setups or strict proxy deployments). diff --git a/docs/gateway/security/index.md b/docs/gateway/security/index.md index 0f7364d92d3..d4644d713cf 100644 --- a/docs/gateway/security/index.md +++ b/docs/gateway/security/index.md @@ -439,6 +439,7 @@ Auth modes: - `gateway.auth.mode: "token"`: shared bearer token (recommended for most setups). - `gateway.auth.mode: "password"`: password auth (prefer setting via env: `OPENCLAW_GATEWAY_PASSWORD`). +- `gateway.auth.mode: "trusted-proxy"`: trust an identity-aware reverse proxy to authenticate users and pass identity via headers (see [Trusted Proxy Auth](/gateway/trusted-proxy-auth)). Rotation checklist (token/password): @@ -459,7 +460,7 @@ injected by Tailscale. **Security rule:** do not forward these headers from your own reverse proxy. If you terminate TLS or proxy in front of the gateway, disable -`gateway.auth.allowTailscale` and use token/password auth instead. +`gateway.auth.allowTailscale` and use token/password auth (or [Trusted Proxy Auth](/gateway/trusted-proxy-auth)) instead. Trusted proxies: diff --git a/docs/web/webchat.md b/docs/web/webchat.md index 4dc8a985331..a765f67598a 100644 --- a/docs/web/webchat.md +++ b/docs/web/webchat.md @@ -44,6 +44,7 @@ Channel options: Related global options: - `gateway.port`, `gateway.bind`: WebSocket host/port. -- `gateway.auth.mode`, `gateway.auth.token`, `gateway.auth.password`: WebSocket auth. +- `gateway.auth.mode`, `gateway.auth.token`, `gateway.auth.password`: WebSocket auth (token/password). +- `gateway.auth.mode: "trusted-proxy"`: reverse-proxy auth for browser clients (see [Trusted Proxy Auth](/gateway/trusted-proxy-auth)). - `gateway.remote.url`, `gateway.remote.token`, `gateway.remote.password`: remote gateway target. - `session.*`: session storage and main key defaults.