docs/web/index.md
The Gateway serves a small browser Control UI (Vite + Lit) from the same port as the Gateway WebSocket:
http://<host>:18789/gateway.tls.enabled: true: https://<host>:18789/gateway.controlUi.basePath (e.g. /openclaw)Capabilities live in Control UI. The rest of this page focuses on bind modes, security, and web-facing surfaces.
When hooks.enabled=true, the Gateway also exposes a small webhook endpoint on the same HTTP server.
See Gateway configuration → hooks for auth + payloads.
The Control UI is enabled by default when assets are present (dist/control-ui).
You can control it via config:
{
gateway: {
controlUi: { enabled: true, basePath: "/openclaw" }, // basePath optional
},
}
Keep the Gateway on loopback and let Tailscale Serve proxy it:
{
gateway: {
bind: "loopback",
tailscale: { mode: "serve" },
},
}
Then start the gateway:
openclaw gateway
Open:
https://<magicdns>/ (or your configured gateway.controlUi.basePath){
gateway: {
bind: "tailnet",
controlUi: { enabled: true },
auth: { mode: "token", token: "your-token" },
},
}
Then start the gateway (this non-loopback example uses shared-secret token auth):
openclaw gateway
Open:
http://<tailscale-ip>:18789/ (or your configured gateway.controlUi.basePath){
gateway: {
bind: "loopback",
tailscale: { mode: "funnel" },
auth: { mode: "password" }, // or OPENCLAW_GATEWAY_PASSWORD
},
}
gateway.auth.mode: "trusted-proxy".connect.params.auth.token or
connect.params.auth.password.gateway.tls.enabled: true, local dashboard and status helpers render
https:// dashboard URLs and wss:// WebSocket URLs.trusted-proxy, the
WebSocket auth check is satisfied from request headers instead.gateway.controlUi.allowedOrigins
explicitly (full origins). Without it, gateway startup is refused by default.gateway.controlUi.dangerouslyAllowHostHeaderOriginFallback=true enables
Host-header origin fallback mode, but is a dangerous security downgrade.gateway.auth.allowTailscale is true (no token/password required).
HTTP API endpoints do not use those Tailscale identity headers; they follow
the gateway's normal HTTP auth mode instead. Set
gateway.auth.allowTailscale: false to require explicit credentials. See
Tailscale and Security. This
tokenless flow assumes the gateway host is trusted.gateway.tailscale.mode: "funnel" requires gateway.auth.mode: "password" (shared password).The Gateway serves static files from dist/control-ui. Build them with:
pnpm ui:build