diff --git a/docs/TAILSCALE.md b/docs/TAILSCALE.md new file mode 100644 index 0000000..477345e --- /dev/null +++ b/docs/TAILSCALE.md @@ -0,0 +1,149 @@ +# Tailscale + +Connect your Toes appliance to your Tailscale network for secure access from anywhere. + +Tailscale is pre-installed on the appliance but not configured. The user authenticates through the dashboard or CLI — no SSH required. + +## how it works + +1. User clicks "Connect to Tailscale" in the dashboard (or runs `toes tailscale connect`) +2. Toes runs `tailscale login` and captures the auth URL +3. Dashboard shows the URL and a QR code +4. User visits the URL and authenticates with Tailscale +5. Toes detects the connection, runs `tailscale serve --bg 80` +6. Appliance is now accessible at `https://..ts.net` + +## dashboard + +Settings area shows one of three states: + +**Not connected:** +- "Connect to Tailscale" button + +**Connecting:** +- Auth URL as a clickable link +- QR code for mobile +- Polls `tailscale status` until authenticated + +**Connected:** +- Tailnet URL (clickable) +- Tailnet name +- Device hostname +- `tailscale serve` toggle +- "Disconnect" button + +## cli + +```bash +toes tailscale # show status +toes tailscale connect # start auth flow, print URL, wait +toes tailscale disconnect # log out of tailnet +toes tailscale serve # toggle tailscale serve on/off +``` + +### `toes tailscale` + +``` +Tailscale: connected +Tailnet: user@github +Hostname: toes.tail1234.ts.net +IP: 100.64.0.1 +Serve: on (port 80) +``` + +Or when not connected: + +``` +Tailscale: not connected + +Run `toes tailscale connect` to get started. +``` + +### `toes tailscale connect` + +``` +Visit this URL to authenticate: +https://login.tailscale.com/a/abc123 + +Waiting for authentication... done! +Connected to tailnet user@github +https://toes.tail1234.ts.net +``` + +## server api + +All endpoints shell out to the `tailscale` CLI and parse output. + +### `GET /api/tailscale` + +Returns current status. + +```json +{ + "installed": true, + "connected": true, + "hostname": "toes", + "tailnetName": "user@github", + "url": "https://toes.tail1234.ts.net", + "ip": "100.64.0.1", + "serving": true +} +``` + +When not connected: + +```json +{ + "installed": true, + "connected": false +} +``` + +When tailscale isn't installed: + +```json +{ + "installed": false +} +``` + +### `POST /api/tailscale/connect` + +Runs `tailscale login`. Returns the auth URL. + +```json +{ + "authUrl": "https://login.tailscale.com/a/abc123" +} +``` + +### `POST /api/tailscale/disconnect` + +Runs `tailscale logout`. + +### `POST /api/tailscale/serve` + +Toggles `tailscale serve`. Body: + +```json +{ "enabled": true } +``` + +## install + +`scripts/install.sh` installs tailscale and enables the daemon, but does not authenticate: + +```bash +curl -fsSL https://tailscale.com/install.sh | sh +sudo systemctl enable tailscaled +``` + +## permissions + +The `toes` user needs passwordless sudo for tailscale commands. Add to sudoers during install: + +``` +toes ALL=(ALL) NOPASSWD: /usr/bin/tailscale +``` + +This lets the server run `sudo tailscale login`, `sudo tailscale serve`, etc. without a password prompt.