feat(gateway): add tailscale auth + pam

This commit is contained in:
Peter Steinberger
2025-12-21 00:44:39 +00:00
parent d69064f364
commit 053c8d5731
14 changed files with 417 additions and 7 deletions

View File

@@ -224,6 +224,8 @@ Defaults:
mode: "local", // or "remote"
bind: "loopback",
// controlUi: { enabled: true }
// auth: { mode: "token" | "password" | "system" }
// tailscale: { mode: "off" | "serve" | "funnel" }
}
}
```
@@ -231,6 +233,16 @@ Defaults:
Notes:
- `clawdis gateway` refuses to start unless `gateway.mode` is set to `local` (or you pass the override flag).
Auth and Tailscale:
- `gateway.auth.mode` sets the handshake requirements (`token`, `password`, or `system`/PAM).
- When `gateway.auth.mode` is set, only that method is accepted (plus optional Tailscale headers).
- `gateway.auth.password` can be set here, or via `CLAWDIS_GATEWAY_PASSWORD` (recommended).
- `gateway.auth.username` defaults to the current OS user; override with `CLAWDIS_GATEWAY_USERNAME`.
- `gateway.auth.allowTailscale` controls whether Tailscale identity headers can satisfy auth.
- `gateway.tailscale.mode: "serve"` uses Tailscale Serve (tailnet only, loopback bind).
- `gateway.tailscale.mode: "funnel"` exposes the dashboard publicly; requires auth.
- `gateway.tailscale.resetOnExit` resets Serve/Funnel config on shutdown.
### `canvasHost` (LAN/tailnet Canvas file server + live reload)
The Gateway serves a directory of HTML/CSS/JS over HTTP so iOS/Android nodes can simply `canvas.navigate` to it.

16
docs/dashboard.md Normal file
View File

@@ -0,0 +1,16 @@
---
summary: "Gateway dashboard (Control UI) access and auth"
read_when:
- Changing dashboard authentication or exposure modes
---
# Dashboard (Control UI)
The Gateway dashboard is the browser Control UI served at `/ui/`.
Key references:
- `docs/control-ui.md` for usage and UI capabilities.
- `docs/tailscale.md` for Serve/Funnel automation.
- `docs/web.md` for bind modes and security notes.
Authentication is enforced at the WebSocket handshake via `connect.params.auth`
(token or password). See `gateway.auth` in `docs/configuration.md`.

87
docs/tailscale.md Normal file
View File

@@ -0,0 +1,87 @@
---
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)
Clawdis can auto-configure Tailscale **Serve** (tailnet) or **Funnel** (public) for the
Gateway dashboard and WebSocket port. This keeps the Gateway bound to loopback while
Tailscale provides HTTPS, routing, and (for Serve) identity headers.
## Modes
- `serve`: Tailnet-only HTTPS via `tailscale serve`. The gateway stays on `127.0.0.1`.
- `funnel`: Public HTTPS via `tailscale funnel`. Requires auth.
- `off`: Default (no Tailscale automation).
## Auth
Set `gateway.auth.mode` to control the handshake:
- `token` (default when `CLAWDIS_GATEWAY_TOKEN` is set)
- `password` (shared secret via `CLAWDIS_GATEWAY_PASSWORD` or config)
- `system` (PAM, validates your OS password)
When `tailscale.mode = "serve"`, the gateway trusts Tailscale identity headers by
default unless you force `gateway.auth.mode` to `password`/`system` or set
`gateway.auth.allowTailscale: false`.
## Config examples
### Tailnet-only (Serve)
```json5
{
gateway: {
bind: "loopback",
tailscale: { mode: "serve" }
}
}
```
Open: `https://<magicdns>/ui/`
### Public internet (Funnel + system password)
```json5
{
gateway: {
bind: "loopback",
tailscale: { mode: "funnel" },
auth: { mode: "system" }
}
}
```
Open: `https://<magicdns>/ui/` (public)
### Public internet (Funnel + shared password)
```json5
{
gateway: {
bind: "loopback",
tailscale: { mode: "funnel" },
auth: { mode: "password", password: "replace-me" }
}
}
```
Prefer `CLAWDIS_GATEWAY_PASSWORD` over committing a password to disk.
## CLI examples
```bash
clawdis gateway --tailscale serve
clawdis gateway --tailscale funnel --auth system
```
## Notes
- Tailscale Serve/Funnel requires the `tailscale` CLI to be installed and logged in.
- System auth uses the optional `authenticate-pam` native module; install if missing.
- `tailscale.mode: "funnel"` refuses to start without auth to avoid public exposure.
- Set `gateway.tailscale.resetOnExit` if you want Clawdis to undo `tailscale serve`
or `tailscale funnel` configuration on shutdown.