headscale-node-lifecycle · git:20260814.c0c7690 · 2026-08-14 · sha256 3d60d994e5e8302d
headscale-node-lifecycle git:20260814.c0c7690A
Immutable. This exact content is served forever at /api/v1/blob/3d60d994e5e8302d.
--- name: headscale-node-lifecycle description: Manage the full lifecycle of nodes in a Headscale tailnet — generate pre-authenticated keys, register, approve, tag, list, and decommission nodes. Use when adding new devices, generating auth keys for automation, or managing node inventory. metadata: category: devops --- # headscale-node-lifecycle ## Overview Headscale manages nodes in a tailnet with two identity models: - **Personal nodes** — registered under a specific user account (e.g. `yourname@domain`). The node key is tied to that user's identity. - **Tagged nodes** — belong to the special `tagged-devices` user (created automatically by Headscale). These nodes are identified by one or more tags (e.g. `tag:webserver`, `tag:monitoring`) and are typically used for infrastructure service nodes. Registration happens through: 1. **Web auth** — user visits a URL to authenticate with an OIDC/OAuth provider 2. **Pre-authenticated key (auth key)** — a one-time or reusable key generated by the admin that embeds tags, user, and expiry 3. **CLI / API** — direct node registration via `headscale` commands or REST API calls ## Pre-authenticated Keys Auth keys streamline automated node registration. Key attributes: | Parameter | Description | |-------------|------------------------------------------------------------------| | Expiration | Default: 1 hour. Use `0` for no expiry (not recommended). | | Reusable | Single-use by default. Mark reusable for fleet provisioning. | | Ephemeral | Ephemeral nodes are removed from the tailnet when they disconnect. Perfect for CI runners and ephemeral workloads. | | Tags | Assign tags to create a tagged node automatically. | ## Node Registration - **Personal nodes**: Create an auth key for a user → run `tailscale up --auth-key=<key>` on the device → approve in Headscale if registration is open. - **Tagged nodes**: Create an auth key with `--tags` → run `tailscale up --auth-key=<key>` → the node is auto-approved and tagged. ## Node Listing List nodes filtered by user, tag, or online status. Output includes: - Node ID - Name (hostname) - Tailscale IP address(es) - Assigned tags - User/owner - Online/offline status - Last seen timestamp - Operating system - Tailscale client version ## Node Tagging Tags can be added or replaced on existing nodes. Tags always carry the `tag:` prefix in Headscale. When adding tags, existing tags are preserved unless `--replace` is specified. ## Node Deletion To decommission a node permanently: ``` headscale nodes delete -i <node-id> ``` Or via the REST API: `DELETE /api/v1/node/<node-id>` Decommissioning is irreversible. For ephemeral nodes, disconnection alone is sufficient — the server removes them automatically. ## Environment | Variable | Description | |---------------------|-------------------------------| | `HEADSCALE_URL` | Base URL of the Headscale server (e.g. `https://headscale.example.com`) | | `HEADSCALE_API_KEY` | API key from `headscale apikeys create` | Both env vars are required for API-based operations when the `headscale` CLI is not available on `PATH`. ## Gotchas - **Auth key expiration**: Default is 1 hour. If you're provisioning a device and it takes longer, the key expires and registration fails. Set a longer expiry explicitly. - **Tagged node user**: Tagged nodes always belong to the `tagged-devices` user. Do not try to assign them to a personal user. - **Connectivity testing**: Nodes must be online (`Connected: true`) to test connectivity. Offline nodes do not respond to ping/ICMP within the tailnet. - **CLI vs API**: When both are available, the CLI is preferred for interactive use. The REST API is preferred for automation scripts. - **Key reuse**: Reusable keys are convenient but less secure. Use with care, especially in production environments. - **Ephemeral nodes**: Setting `--ephemeral` means the node is fully removed on disconnection — there is no record of it in the tailnet afterward. ## Trigger Conditions - "auth key" - "preauthkey" - "register node" - "approve node" - "tag node" - "node list" - "decommission node" ## Scripts ### hs-create-authkey.sh Create pre-authenticated keys via Headscale CLI or REST API. ``` hs-create-authkey.sh --user <user> --tags <tag> --expiration <duration> --reusable --ephemeral [--json] [--dry-run] ``` ### hs-list-nodes.sh List all nodes in the tailnet with status and metadata. ``` hs-list-nodes.sh [--json] [--user <user>] [--tag <tag>] [--online-only] ``` ### hs-approve-nodes.sh Approve pending node registrations. ``` hs-approve-nodes.sh [--all] [--auth-id <id>] [--dry-run] [--json] ``` ### hs-tag-node.sh Update tags on an existing node. ``` hs-tag-node.sh --node <id/name> --tags <tag1,tag2> [--replace | --add] [--dry-run] [--json] ```