# Headscale

Self-hosted Tailscale coordination server. Keeps device metadata on your own infrastructure. [Upstream docs](https://headscale.net).

- **URL**: `hs.{domain}` (must be public — clients contact it before joining the tailnet)
- **STUN**: 3478/udp (embedded DERP relay)
- **Data**: `/var/lib/headscale` (SQLite DB + noise keys)

## Deploy

```bash
auberge ansible run --tags headscale
```

## Required config

| Key                      | Purpose                                                                                                                                           |
| ------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------- |
| `headscale_subdomain`    | Subdomain for the control plane (e.g. `hs`)                                                                                                       |
| `tailscale_login_server` | Headscale URL (e.g. `https://hs.example.com`) — passed to `tailscale up --login-server`. When set, nodes use Headscale instead of Tailscale SaaS. |
| `tailscale_authkey`      | Pre-auth key for nodes joining the tailnet (generated by `auberge headscale add-user`)                                                            |

## First-run sequence

```bash
auberge ansible run --tags headscale
auberge headscale add-user --host my-vps
auberge config set tailscale_login_server https://hs.example.com
auberge config set tailscale_authkey <PREAUTH_KEY>
auberge ansible run --tags tailscale                 # roll nodes onto Headscale
```

?> Existing tailnet services (Paperless, Bichon, Cockpit) keep working unchanged — same Tailscale client, same WireGuard data plane.

## Migration from Tailscale SaaS

On each node: `tailscale logout`, then re-run `auberge ansible run --tags tailscale`. Verify with `tailscale status`.

## Backup

`auberge backup create --apps headscale` snapshots `/var/lib/headscale` (SQLite + keys). No external DB.
