Minimum supported Tailscale client version: v1.80.0
Changes
- Fix a node being listed among its own peers in an incremental map update, which crashes the Tailscale Android app on the device list #3459
- Fix deleting a node leaving its long poll open, so the client stayed connected instead of asking for a new login #3449
- Fix interactive OIDC login when the confirmation page is reloaded by an ad blocker, back navigation, or pull-to-refresh; the confirmation page now has its own URL, keeping single-use authorization codes out of reloads #3448
- Harden the OIDC callback: state and nonce cookies take their Secure flag from
server_urlso they survive a TLS-terminating proxy, a callback state is single-use, and an invalidoidc.issueror a missingoidc.client_id/oidc.client_secretnow fails at startup #3334 - Fix HTTP metrics only counting
OPTIONSrequests, sohttp_requests_totalandhttp_request_duration_secondsnow cover regular traffic #3414 - Fix extra-records filewatcher hanging on shutdown after the watched file is deleted, and leaking the watcher when setup fails #3437
- Lowercase DNS extra record names so mixed-case records resolve #3366
- Fix
headscale users renamesending the raw--identifierflag value instead of the matched user's identifier, so renaming by name works again #3442 - Fix tailsql not shutting down with headscale, leaving the process hanging on graceful shutdown #3400
- Fix tvOS setup instructions: install the VPN configuration before setting the coordination server URL #3431
- Map requests that only bump LastSeen, endpoints or DERP region no longer resend the whole node to every peer, and health probes that change nothing no longer write. Adds
headscale_mapper_changes_dropped_totalandheadscale_ha_health_updates_total#3417 #3450 - The peer map is keyed by node ID and reused for writes that cannot change peer visibility, so a routine map request no longer rebuilds it. Adds
headscale_nodestore_snapshot_builds_total#3417 #3450 - Fix an expired node staying online forever, because expiring it updated the key deadline without ending its map session #3472
- Fix ACME renewal stopping permanently after a
badNoncereply, because the error logging middleware drained the response body the acme client needs to detect it #3461 - Fix
#-prefixed metadata fields being rejected outsideacls, so policy editors can store metadata in grants, SSH rules andnodeAttrs#3481 - Fix exit nodes not offered by recent macOS and iOS clients, which read the
suggest-exit-nodepeer attribute rather than the advertised0.0.0.0/0routes #3487 - Fix exit node not offered to viewers whose only matching rule is a
viagrant; peer visibility now comes from the peer map alone #3409
Upgrade
Please follow the steps outlined in the upgrade guide to update your existing Headscale installation.
Changelog
- 3a2b133 .github/workflows: regenerate the integration test matrix
- bdfa340 AGENTS.md: drop stale line numbers
- 8106636 CHANGELOG: add 0.29.4
- b9b2beb Update AppleTV configuration steps
- 2a76860 build: bump test image Go to 1.27.1
- 974becf change, mapper: distinguish deleted nodes
- b3b55cc cli: fix users rename when resolved by name
- 46a80ea dns: cancel extra-records retry on shutdown and close watcher on setup error
- 33db8c6 fix(metrics): collect metrics for non-OPTIONS requests
- 032470a hscontrol: cancel tailsql on graceful shutdown
- ebe18ce hscontrol: keep the ACME error body readable in acmeLogger
- c7d9d03 hscontrol: replace tailscale line refs with doc links
- 1e528f7 integration: cover deletion across client versions
- b9c7b4c integration: cover node deletion ending the long poll
- 7783e7f integration: cover node expiry and recovery for every client
- 625fa86 integration: pin docker client to daemon API version
- cc41593 integration: pin which Hostinfo changes reach peers
- fc894aa linting issue fix
- 2b8dbea mapper: assert no map response lists the recipient as its own peer
- b8da1c2 mapper: drop empty changes before fan-out
- 397149e mapper: stop a deleted node's map session
- 9fbf7b9 mapper: take peer visibility from the peer map only
- d388244 noise: make deleted-node expiry clock independent
- 2b28f57 oidc: harden callback CSRF cookies, state reuse, and issuer config
- cbb9357 oidc: harden reloadable confirmation flow
- 2da47a7 oidc: serve the registration confirmation page from a reloadable URL
- 938c2bd policy,state: key the peer map by node ID
- bc5b9d5 policy,types: skip recompile when the user list is unchanged
- 8490631 policy/v2: add via exit node capture
- 694bafe policy/v2: compare peer CapMap against SaaS route captures
- 5aded15 policy/v2: suggest approved exit nodes by default
- aa4c952 policy: ignore '#' metadata fields across the whole policy
- fb197db poll, noise: tell a deleted node to re-authenticate
- 83eff40 poll: interrupt blocked map writes
- a7f7e6a servertest: compare user-owned nodes in via compat tests
- 8973347 state: classify map requests before broadcasting
- d4b073e state: exclude self from peers on the named peer-ID path
- a91f708 state: mark expired nodes offline without ending the session
- 0fca2bb state: preserve committed node deletion changes
- fdb782d state: rename persist helpers to say what they do
- 6a0f67d state: resolve changed peers through adjacency
- 237dc74 state: reuse peer adjacency for payload-only writes
- 8f7ee37 state: skip node health writes that change nothing
- b972da3 state: stop broadcasting a whole peer on disconnect
- e3dba1f templates: apply the tvOS setup reorder to the served /apple page
- 2b6cb3a types/change: drop unused VisibilityChange
- 4411264 types: detect policy change on user identity and exit routes
- b4f991b types: lowercase DNS extra record names
- e6c0a8a types: regenerate node view