docs/web/dashboard.md
The Gateway dashboard is the browser Control UI served at / by default (override with gateway.controlUi.basePath).
Quick open (local Gateway):
gateway.tls.enabled: true, use https://127.0.0.1:18789/ and wss://127.0.0.1:18789 for the WebSocket endpoint.Key references:
Auth is enforced at the WebSocket handshake via the configured gateway auth path:
connect.params.auth.tokenconnect.params.auth.passwordgateway.auth.allowTailscale: truegateway.auth.mode: "trusted-proxy"See gateway.auth in Gateway configuration.
openclaw dashboard (copies the link, opens a browser if possible, prints an SSH hint if headless).openclaw dashboard still prints the clean URL and tells you to append your token (from OPENCLAW_GATEWAY_TOKEN or gateway.auth.token) as the URL fragment key token; it never prints the token value in logs.http://127.0.0.1:18789/.gateway.tls.enabled: true, dashboard/status links use https:// and Control UI WebSocket links use wss://.gateway.auth.token (or OPENCLAW_GATEWAY_TOKEN). openclaw dashboard can pass it via URL fragment for one-time bootstrap; the Control UI keeps it in sessionStorage for the current tab and selected gateway URL, not localStorage.gateway.auth.token is SecretRef-managed, openclaw dashboard prints/copies/opens a non-tokenized URL by design, to avoid exposing externally managed tokens in shell logs, clipboard history, or browser-launch arguments. If the ref is unresolved in your current shell, it still prints the non-tokenized URL plus actionable auth setup guidance.gateway.auth.password (or OPENCLAW_GATEWAY_PASSWORD). The dashboard does not persist passwords across reloads.gateway.auth.allowTailscale: true; a non-loopback identity-aware reverse proxy satisfies gateway.auth.mode: "trusted-proxy". Neither needs a pasted shared secret for the WebSocket.gateway.auth.mode: "trusted-proxy", or an SSH tunnel. HTTP APIs still use shared-secret auth unless you intentionally run private-ingress gateway.auth.mode: "none" or trusted-proxy HTTP auth. See Web surfaces.<a id="if-you-see-unauthorized-1008"></a>
openclaw status; remote, SSH tunnel ssh -N -L 18789:127.0.0.1:18789 user@gateway-host then open http://127.0.0.1:18789/.AUTH_TOKEN_MISMATCH, clients may do one trusted retry with a cached device token when the gateway returns retry hints; that retry reuses the token's cached approved scopes (explicit deviceToken/scopes callers keep their requested scope set). If auth still fails after that retry, resolve token drift manually.AUTH_SCOPE_MISMATCH, the device token was recognized but does not carry the requested scopes; re-pair or approve the new scope set instead of rotating the shared gateway token.deviceToken, then stored device token, then bootstrap token.{scope, ip} are serialized before the failed-auth limiter records them, so a second concurrent bad retry can already show retry later.openclaw config get gateway.auth.tokengateway.auth.password or OPENCLAW_GATEWAY_PASSWORDOPENCLAW_GATEWAY_TOKEN in this shell and rerun openclaw dashboardopenclaw doctor --generate-gateway-token