2025-12-21 00:44:39 +00:00
|
|
|
|
---
|
|
|
|
|
|
summary: "Integrated Tailscale Serve/Funnel for the Gateway dashboard"
|
|
|
|
|
|
read_when:
|
|
|
|
|
|
- Exposing the Gateway Control UI outside localhost
|
|
|
|
|
|
- Automating tailnet or public dashboard access
|
|
|
|
|
|
---
|
|
|
|
|
|
# Tailscale (Gateway dashboard)
|
|
|
|
|
|
|
2026-01-04 14:32:47 +00:00
|
|
|
|
Clawdbot can auto-configure Tailscale **Serve** (tailnet) or **Funnel** (public) for the
|
2025-12-21 00:44:39 +00:00
|
|
|
|
Gateway dashboard and WebSocket port. This keeps the Gateway bound to loopback while
|
|
|
|
|
|
Tailscale provides HTTPS, routing, and (for Serve) identity headers.
|
|
|
|
|
|
|
|
|
|
|
|
## Modes
|
|
|
|
|
|
|
2026-01-08 07:15:45 +01:00
|
|
|
|
- `serve`: Tailnet-only Serve via `tailscale serve`. The gateway stays on `127.0.0.1`.
|
|
|
|
|
|
- `funnel`: Public HTTPS via `tailscale funnel`. Clawdbot requires a shared password.
|
2025-12-21 00:44:39 +00:00
|
|
|
|
- `off`: Default (no Tailscale automation).
|
|
|
|
|
|
|
|
|
|
|
|
## Auth
|
|
|
|
|
|
|
|
|
|
|
|
Set `gateway.auth.mode` to control the handshake:
|
|
|
|
|
|
|
2026-01-04 14:32:47 +00:00
|
|
|
|
- `token` (default when `CLAWDBOT_GATEWAY_TOKEN` is set)
|
|
|
|
|
|
- `password` (shared secret via `CLAWDBOT_GATEWAY_PASSWORD` or config)
|
2025-12-21 00:44:39 +00:00
|
|
|
|
|
2026-01-13 04:37:04 +00:00
|
|
|
|
When `tailscale.mode = "serve"` and `gateway.auth.allowTailscale` is `true`,
|
|
|
|
|
|
valid Serve proxy requests can authenticate via Tailscale identity headers
|
|
|
|
|
|
(`tailscale-user-login`) without supplying a token/password. Clawdbot only
|
|
|
|
|
|
treats a request as Serve when it arrives from loopback with Tailscale’s
|
|
|
|
|
|
`x-forwarded-for`, `x-forwarded-proto`, and `x-forwarded-host` headers.
|
|
|
|
|
|
To require explicit credentials, set `gateway.auth.allowTailscale: false` or
|
|
|
|
|
|
force `gateway.auth.mode: "password"`.
|
2025-12-21 00:44:39 +00:00
|
|
|
|
|
|
|
|
|
|
## Config examples
|
|
|
|
|
|
|
|
|
|
|
|
### Tailnet-only (Serve)
|
|
|
|
|
|
|
|
|
|
|
|
```json5
|
|
|
|
|
|
{
|
|
|
|
|
|
gateway: {
|
|
|
|
|
|
bind: "loopback",
|
|
|
|
|
|
tailscale: { mode: "serve" }
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
```
|
|
|
|
|
|
|
2026-01-03 17:54:52 +01:00
|
|
|
|
Open: `https://<magicdns>/` (or your configured `gateway.controlUi.basePath`)
|
2025-12-21 00:44:39 +00:00
|
|
|
|
|
2026-01-21 20:35:39 +00:00
|
|
|
|
### Tailnet-only (bind to Tailnet IP)
|
|
|
|
|
|
|
|
|
|
|
|
Use this when you want the Gateway to listen directly on the Tailnet IP (no Serve/Funnel).
|
|
|
|
|
|
|
|
|
|
|
|
```json5
|
|
|
|
|
|
{
|
|
|
|
|
|
gateway: {
|
|
|
|
|
|
bind: "tailnet",
|
|
|
|
|
|
auth: { mode: "token", token: "your-token" }
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
Connect from another Tailnet device:
|
|
|
|
|
|
- Control UI: `http://<tailscale-ip>:18789/`
|
|
|
|
|
|
- WebSocket: `ws://<tailscale-ip>:18789`
|
|
|
|
|
|
|
|
|
|
|
|
Note: loopback (`http://127.0.0.1:18789`) will **not** work in this mode.
|
|
|
|
|
|
|
2025-12-21 00:44:39 +00:00
|
|
|
|
### Public internet (Funnel + shared password)
|
|
|
|
|
|
|
|
|
|
|
|
```json5
|
|
|
|
|
|
{
|
|
|
|
|
|
gateway: {
|
|
|
|
|
|
bind: "loopback",
|
|
|
|
|
|
tailscale: { mode: "funnel" },
|
|
|
|
|
|
auth: { mode: "password", password: "replace-me" }
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
```
|
|
|
|
|
|
|
2026-01-04 14:32:47 +00:00
|
|
|
|
Prefer `CLAWDBOT_GATEWAY_PASSWORD` over committing a password to disk.
|
2025-12-21 00:44:39 +00:00
|
|
|
|
|
|
|
|
|
|
## CLI examples
|
|
|
|
|
|
|
|
|
|
|
|
```bash
|
2026-01-04 14:32:47 +00:00
|
|
|
|
clawdbot gateway --tailscale serve
|
|
|
|
|
|
clawdbot gateway --tailscale funnel --auth password
|
2025-12-21 00:44:39 +00:00
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
## Notes
|
|
|
|
|
|
|
|
|
|
|
|
- Tailscale Serve/Funnel requires the `tailscale` CLI to be installed and logged in.
|
2025-12-23 13:13:09 +00:00
|
|
|
|
- `tailscale.mode: "funnel"` refuses to start unless auth mode is `password` to avoid public exposure.
|
2026-01-04 14:32:47 +00:00
|
|
|
|
- Set `gateway.tailscale.resetOnExit` if you want Clawdbot to undo `tailscale serve`
|
2025-12-21 00:44:39 +00:00
|
|
|
|
or `tailscale funnel` configuration on shutdown.
|
2026-01-21 20:35:39 +00:00
|
|
|
|
- `gateway.bind: "tailnet"` is a direct Tailnet bind (no HTTPS, no Serve/Funnel).
|
|
|
|
|
|
- `gateway.bind: "auto"` prefers loopback; use `tailnet` if you want Tailnet-only.
|
2026-01-22 23:07:58 +00:00
|
|
|
|
- Serve/Funnel only expose the **Gateway control UI + WS**. Nodes connect over
|
2026-01-22 23:12:38 +00:00
|
|
|
|
the same Gateway WS endpoint, so Serve can work for node access.
|
2026-01-08 07:15:45 +01:00
|
|
|
|
|
2026-01-15 04:50:11 +00:00
|
|
|
|
## Browser control server (remote Gateway + local browser)
|
|
|
|
|
|
|
|
|
|
|
|
If you run the Gateway on one machine but want to drive a browser on another machine, use a **separate browser control server**
|
|
|
|
|
|
and publish it through Tailscale **Serve** (tailnet-only):
|
|
|
|
|
|
|
|
|
|
|
|
```bash
|
|
|
|
|
|
# on the machine that runs Chrome
|
|
|
|
|
|
clawdbot browser serve --bind 127.0.0.1 --port 18791 --token <token>
|
|
|
|
|
|
tailscale serve https / http://127.0.0.1:18791
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
Then point the Gateway config at the HTTPS URL:
|
|
|
|
|
|
|
|
|
|
|
|
```json5
|
|
|
|
|
|
{
|
|
|
|
|
|
browser: {
|
|
|
|
|
|
enabled: true,
|
|
|
|
|
|
controlUrl: "https://<magicdns>/"
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
And authenticate from the Gateway with the same token (prefer env):
|
|
|
|
|
|
|
|
|
|
|
|
```bash
|
|
|
|
|
|
export CLAWDBOT_BROWSER_CONTROL_TOKEN="<token>"
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
Avoid Funnel for browser control endpoints unless you explicitly want public exposure.
|
|
|
|
|
|
|
2026-01-08 07:15:45 +01:00
|
|
|
|
## Tailscale prerequisites + limits
|
|
|
|
|
|
|
|
|
|
|
|
- Serve requires HTTPS enabled for your tailnet; the CLI prompts if it is missing.
|
|
|
|
|
|
- Serve injects Tailscale identity headers; Funnel does not.
|
|
|
|
|
|
- Funnel requires Tailscale v1.38.3+, MagicDNS, HTTPS enabled, and a funnel node attribute.
|
|
|
|
|
|
- Funnel only supports ports `443`, `8443`, and `10000` over TLS.
|
|
|
|
|
|
- Funnel on macOS requires the open-source Tailscale app variant.
|
|
|
|
|
|
|
|
|
|
|
|
## Learn more
|
|
|
|
|
|
|
|
|
|
|
|
- Tailscale Serve overview: https://tailscale.com/kb/1312/serve
|
|
|
|
|
|
- `tailscale serve` command: https://tailscale.com/kb/1242/tailscale-serve
|
|
|
|
|
|
- Tailscale Funnel overview: https://tailscale.com/kb/1223/tailscale-funnel
|
|
|
|
|
|
- `tailscale funnel` command: https://tailscale.com/kb/1311/tailscale-funnel
|