Gateway Web Surfaces: Control UI, Bind Modes, and Security
Learn about the Gateway's web-facing surfaces, including the browser Control UI, webhooks, admin HTTP RPC, and Tailscale access. This page covers bind modes and security for operators and developers.
Read this when
- You want to access the Gateway over Tailscale
- You want the browser Control UI and config editing
The Gateway hosts a lightweight browser Control UI (built with Vite + Lit) on the same port that serves the Gateway WebSocket:
- default:
http://<host>:18789/ - with
gateway.tls.enabled: true:https://<host>:18789/ - optional prefix: configure
gateway.controlUi.basePath(e.g./openclaw)
Control UI features are documented in Control UI. This page addresses bind modes, security, and other web-facing surfaces.
Config (default-on)
Control UI is on by default whenever assets are available (dist/control-ui):
{
gateway: {
controlUi: { enabled: true, basePath: "/openclaw" }, // basePath optional
},
}
Webhooks
When hooks.enabled=true is set, the Gateway also serves a webhook endpoint on that same HTTP server. Refer to hooks in the Gateway configuration reference for authentication details and payload formats.
Admin HTTP RPC
POST /api/v1/admin/rpc makes selected Gateway control-plane methods reachable over HTTP. It is disabled by default and only gets registered when the admin-http-rpc plugin is active. The Admin HTTP RPC page covers the authentication model, permitted methods, and how it compares to the WebSocket API.
Tailscale access
Integrated Serve (recommended)
Bind the Gateway to loopback only and let Tailscale Serve proxy traffic to it:
{
gateway: {
bind: "loopback",
tailscale: { mode: "serve" },
},
}
Launch the gateway:
openclaw gateway
Visit https://<magicdns>/ (or your configured gateway.controlUi.basePath).
Public internet (Funnel)
{
gateway: {
bind: "loopback",
tailscale: { mode: "funnel" },
auth: { mode: "password" }, // or OPENCLAW_GATEWAY_PASSWORD
},
}
tailscale.mode: "funnel" depends on gateway.auth.mode: "password"; both Serve and Funnel need gateway.bind: "loopback".
Security notes
- Gateway authentication is mandatory by default: token, password, trusted-proxy, or Tailscale Serve identity headers when those are enabled.
- Non-loopback binds still demand gateway auth: token/password authentication or an identity-aware reverse proxy using
gateway.auth.mode: "trusted-proxy". - The onboarding wizard defaults to shared-secret auth and typically generates a gateway token, even for loopback setups.
- In shared-secret mode, the UI sends
connect.params.auth.tokenorconnect.params.auth.passwordduring the WebSocket handshake. - When
gateway.tls.enabled: trueis active, local dashboard and status helpers renderhttps://URLs along withwss://WebSocket URLs. - For identity-bearing modes (Tailscale Serve,
trusted-proxy), the WebSocket auth check pulls from request headers rather than a shared secret. - For public Control UI deployments on non-loopback addresses, set
gateway.controlUi.allowedOriginsexplicitly (full origins). Private same-origin loads skip this requirement for loopback, RFC1918/link-local,.local,.ts.net, and Tailscale CGNAT hosts. gateway.controlUi.dangerouslyAllowHostHeaderOriginFallback: trueturns on Host-header origin fallback, which is a serious security downgrade.- Under Serve, Tailscale identity headers fulfill Control UI/WebSocket auth when
gateway.auth.allowTailscale: trueis set (no token or password needed). HTTP API endpoints ignore Tailscale identity headers; they always follow the gateway's standard HTTP auth mode. Setgateway.auth.allowTailscale: falseto force explicit credentials even over Serve. This tokenless flow presumes the gateway host itself is trusted. See Tailscale and Security.
Building the UI
Static files are served by the Gateway from dist/control-ui:
pnpm ui:build