#Control UI token

1 messages · Page 1 of 1 (latest)

brittle tusk
#

At least most of the time when I open control-ui in the browser o have to re-enter the token. Is there a way to have it saved , or does the password method last longer?

lucid oliveBOT
# brittle tusk At least most of the time when I open control-ui in the browser o have to re-ent...

Short answer: password won’t last longer. Current docs say the Control UI keeps the gateway token only in session-scoped browser storage for the current browser tab/session + selected gateway URL, and passwords are kept in memory only.

So a refresh in the same tab should usually keep token auth, but opening a new tab/window or after browser session/site-data cleanup can make you paste it again. Docs: https://docs.openclaw.ai/web/control-ui and https://docs.openclaw.ai/web/dashboard

Best options:

  • Use the URL that openclaw dashboard prints/opens; it can bootstrap the token via a URL fragment, then the UI strips it and stores it for that tab session.
  • If you’re using Tailscale Serve with gateway.auth.allowTailscale: true, Control UI/WebSocket auth can use Tailscale identity instead of pasting a token.
  • If it’s losing the token on same-tab refresh, please share openclaw --version and which browser/profile you’re using, because that would be worth debugging.
brittle tusk
#

I know not reccomended, but control-ui is protected by reverse proxy already, so can I just turn off auth?

lucid oliveBOT
# brittle tusk I know not reccomended, but control-ui is protected by reverse proxy already, so...

Technically yes, gateway.auth.mode: "none" exists, but I would not use it for a normal reverse-proxy setup unless the Gateway is truly private ingress only and cannot be reached except through that proxy. With none, Gateway HTTP APIs become open to anything that can reach the Gateway port, not just the Control UI.

The safer reverse-proxy answer is usually:

{
  gateway: {
    bind: "lan",
    trustedProxies: ["<your-proxy-ip>"],
    auth: {
      mode: "trusted-proxy",
      trustedProxy: {
        userHeader: "x-forwarded-user",
        allowUsers: ["you@example.com"]
      }
    },
lucid oliveBOT
brittle tusk
#

I am using pangolin proxy does this count as trusted proxy?

lucid oliveBOT
# brittle tusk I am using pangolin proxy does this count as trusted proxy?

Yes, Pangolin can count, but only if you’re using a Pangolin auth mode that forwards identity headers.

Pangolin docs say identity headers are available with SSO, and include headers like Remote-User, Remote-Email, Remote-Name, Remote-Role. PIN/password/share links don’t provide identity headers, so those are not a good fit for OpenClaw trusted-proxy auth.

For SSO-backed Pangolin, the OpenClaw side would be roughly:

{
  gateway: {
    bind: "lan",
    trustedProxies: ["<pangolin-or-traefik-source-ip>"],
    auth: {
      mode: "trusted-proxy",
      trustedProxy: {
        userHeader: "remote-email",
        allowUsers: ["you@example.com"]
lucid oliveBOT
brittle tusk
#

before I make this change regarding the trusted-proxy auth, use dev tools in firefox can I verify that the headers are being sent to openclaw from pangolin

lucid oliveBOT
# brittle tusk before I make this change regarding the trusted-proxy auth, use dev tools in fir...

Short version: Firefox DevTools can’t directly prove the headers Pangolin sends upstream to OpenClaw.

DevTools shows the browser -> Pangolin request headers, and the response back to the browser. The trusted-proxy identity header is usually added on the Pangolin -> OpenClaw hop, so Firefox won’t see it unless Pangolin exposes it back to the browser, which it generally should not.

What you can check in Firefox:

  • Network tab -> reload the Control UI
  • Look at __openclaw/control-ui-config.json and the WebSocket request
  • If those succeed without entering a gateway token/password, that’s a good functional signal that proxy auth is working
  • If you get 401/403/1008 unauthorized, OpenClaw likely didn’t accept the trusted-proxy headers/source

For actual proof, check server-side: Pangolin/upstream proxy logs, or OpenClaw logs while loading the page. OpenClaw’s trusted-proxy mode also requires the request source to match gateway.trustedProxies, and it rejects loopback-source trusted-proxy requests, so the proxy IP/path matters as much as the header.

Docs: https://docs.openclaw.ai/gateway/trusted-proxy-auth

If it fails after the change, first thing to grab is openclaw --version plus the relevant openclaw logs --follow lines around the failed page load.

brittle tusk
#

0:32:45-04:00 error gateway connect failed: GatewayClientRequestError: unauthorized
10:32:45-04:00 error gateway connect failed: GatewayClientRequestError: unauthorized
gateway connect failed: GatewayClientRequestError: unauthorized
10:32:45-04:00 warn gateway/ws {"subsystem":"gateway/ws"} {"cause":"unauthorized","handshake":"failed","durationMs":13,"lastFrameType":"req","lastFrameMethod":"connect","lastFrameId":"d2ef00c9-ba01-4638-948b-843a0b29d853","host":"127.0.0.1:18789","remoteAddr":"127.0.0.1","remotePort":39932,"localAddr":"127.0.0.1","localPort":18789,"endpoint":"127.0.0.1:39932->127.0.0.1:18789","authMode":"trusted-proxy","authProvided":"password","authReason":"trusted_proxy_untrusted_source","allowTailscale":false,"peer":"127.0.0.1:39932->127.0.0.1:18789","role":"operator","scopeCount":1,"hasDeviceIdentity":true,"client":"cli","mode":"cli","version":"2026.5.12","platform":"linux","instanceId":"7425e00b-a671-4aad-bc9d-075070299119"} closed before connect conn=d8700849-363f-4ff9-92f0-093393352462 peer=127.0.0.1:39932->127.0.0.1:18789 remote=127.0.0.1 fwd=n/a origin=n/a host=127.0.0.1:18789 ua=n/a code=1008 reason=connect failed
10:32:46-04:00 warn gateway/ws {"subsystem":"gateway/ws"} unauthorized conn=46c6a697-6f7d-446d-b99b-41e3021a8c44 peer=127.0.0.1:39940->127.0.0.1:18789 remote=127.0.0.1 client=cli cli v2026.5.12 role=operator scopes=1 auth=password device=yes platform=linux instance=e1a8f7aa-d1b6-4352-82a7-85604456dc89 host=127.0.0.1:18789 origin=n/a ua=n/a reason=trusted_proxy_untrusted_source
10:32:46-04:00 error gateway connect failed: GatewayClientRequestError: unauthorized
10:32:46-04:00 error gateway connect failed: GatewayClientRequestError: unauthorized

lucid oliveBOT
# brittle tusk 0:32:45-04:00 error gateway connect failed: GatewayClientRequestError: unauthori...

That log is pretty diagnostic:

authMode="trusted-proxy"
remoteAddr="127.0.0.1"
authReason="trusted_proxy_untrusted_source"
authProvided="password"

So this request is not coming through Pangolin. It’s a local CLI/client connection directly to 127.0.0.1:18789, and OpenClaw is in trusted-proxy mode. In that mode, password/token auth is not the path; OpenClaw expects a request from a configured non-loopback trusted proxy IP with the configured identity header.

Two likely fixes depending on what you want:

  1. For local CLI/control commands, point the client at the Pangolin URL instead of 127.0.0.1:18789, so the request goes through the proxy and gets the identity headers.
  2. If you still need local direct CLI access on the box, don’t use gateway.auth.mode: "trusted-proxy" as the only auth mode for that gateway. Use token/password auth, or run a separate/proxied path that actually arrives from the trusted proxy source.

Also check that gateway.trustedProxies contains Pangolin’s IP as seen by OpenClaw, not your browser/client IP. Same-host loopback proxying won’t satisfy trusted-proxy auth.

Docs: https://docs.openclaw.ai/gateway/trusted-proxy-auth

brittle tusk
#

So for this the only local connection I had was doing 'openclaw logs --follow' does this count as a connection?

lucid oliveBOT
# brittle tusk So for this the only local connection I had was doing 'openclaw logs --follow' d...

Yes, very likely. openclaw logs --follow can still open a gateway client connection so it can stream/resolve logs through the running gateway/service plumbing. Your log says client="cli" mode="cli", which lines up with that command rather than Firefox/Pangolin.

So I’d separate the two tests:

  • openclaw logs --follow may generate local 127.0.0.1 unauthorized noise while trusted-proxy mode is enabled.
  • To test Pangolin, load the Control UI through the Pangolin public/internal URL and look for a separate log line where remoteAddr is Pangolin’s IP and authReason is not trusted_proxy_untrusted_source.

If the only unauthorized lines are client=cli with host=127.0.0.1:18789, they don’t prove the browser/Pangolin path is failing. They prove local CLI access is failing under trusted-proxy mode.

brittle tusk
#

so yes it seems to be working through the reverse proxy. But I would like to not have those errors regarding the cli

lucid oliveBOT
# brittle tusk so yes it seems to be working through the reverse proxy. But I would like to not...

Yep, that’s the annoying edge here: openclaw logs --follow first tries the Gateway RPC path, so in trusted-proxy mode it can create those local CLI auth failures before it can show you logs.

Best practical workaround: read the log file directly instead of using the CLI RPC command:

tail -f "$(ls -t /tmp/openclaw/openclaw-*.log | head -1)"

That bypasses Gateway auth entirely, so no trusted_proxy_untrusted_source noise.

The other options are tradeoffs:

  • Point CLI commands at the proxied Gateway URL with --url / OPENCLAW_GATEWAY_URL, but that only works cleanly if the proxy auth flow makes sense for CLI traffic. Browser/OIDC proxies often don’t.
  • Use token/password auth instead of trusted-proxy if local CLI access is more important than proxy-delegated auth.
  • Keep trusted-proxy for the Control UI and use direct file tailing for logs on the host.

Honestly, this looks like a decent GitHub issue: openclaw logs --follow should probably fall back to local file tailing for trusted-proxy local CLI rejection too, not only some pairing cases. Issue link: https://github.com/openclaw/openclaw/issues

brittle tusk
#

seems like openclaw tui will also fail

lucid oliveBOT
# brittle tusk seems like openclaw tui will also fail

Yes, that’s expected. openclaw tui is a local CLI client too, so if your Gateway is configured with:

gateway: {
  auth: { mode: "trusted-proxy" }
}

then direct local TUI connections to 127.0.0.1:18789 won’t authenticate. Trusted-proxy mode is basically saying: “only accept identity-bearing requests from my configured proxy IP.” The local TUI is not Pangolin, so it gets rejected.

So the usable split is:

  • Control UI through Pangolin: works with trusted-proxy auth.
  • Local CLI/TUI directly to loopback: will fail under trusted-proxy auth.
  • Local log viewing: use direct file tailing instead of openclaw logs --follow.

If you want both reverse-proxy browser access and local TUI/CLI access, current practical answer is probably token/password auth plus proxy protection in front, rather than pure trusted-proxy mode. If you want pure trusted-proxy, expect local TUI/CLI to be unavailable unless it can connect through a proxy path that OpenClaw sees as trusted and identity-bearing.

brittle tusk
#

how about 'allowLoopback: true' does this fix this issue?

lucid oliveBOT
# brittle tusk how about 'allowLoopback: true' does this fix this issue?

No, not for current OpenClaw trusted-proxy auth. I checked the docs/schema/source, and I don’t see a gateway.auth.trustedProxy.allowLoopback option.

The supported trusted-proxy fields are basically:

trustedProxy: {
  userHeader: "x-forwarded-user",
  requiredHeaders: ["x-forwarded-proto"],
  allowUsers: ["you@example.com"]
}

And the behavior is explicit: trusted-proxy auth rejects loopback-source requests. The tests cover this too, including “valid token”, “wrong token”, and even identity headers from 127.0.0.1; they all fail as trusted_proxy_loopback_source.

So allowLoopback: true either won’t validate, or it’ll be ignored depending on how your config is loaded. It won’t fix openclaw tui / local CLI direct-to-loopback.

For your goal, the real options are still: