Minimum supported Tailscale client version: v1.74.0
Tags as identity
Tags are now implemented following the Tailscale model where tags and user ownership are mutually exclusive. Devices can be either
user-owned (authenticated via web/OIDC) or tagged (authenticated via tagged PreAuthKeys). Tagged devices receive their identity from
tags rather than users, making them suitable for servers and infrastructure. Applying a tag to a device removes user-based
ownership. See the Tailscale tags documentation for details on how tags work.
User-owned nodes can now request tags during registration using --advertise-tags. Tags are validated against the tagOwners policy
and applied at registration time. Tags can be managed via the CLI or API after registration. Tagged nodes can return to user-owned
by re-authenticating with tailscale up --advertise-tags= --force-reauth.
A one-time migration will validate and migrate any RequestTags (stored in hostinfo) to the tags column. Tags are validated against
your policy's tagOwners rules during migration. #3011
Smarter map updates
The map update system has been rewritten to send smaller, partial updates instead of full network maps whenever possible. This reduces bandwidth usage and improves performance, especially for large networks. The system now properly tracks peer
changes and can send removal notifications when nodes are removed due to policy changes.
#2856 #2961
Pre-authentication key security improvements
Pre-authentication keys now use bcrypt hashing for improved security #2853. Keys
are stored as a prefix and bcrypt hash instead of plaintext. The full key is only displayed once at creation time. When listing keys,
only the prefix is shown (e.g., hskey-auth-{prefix}-***). All new keys use the format hskey-auth-{prefix}-{secret}. Legacy plaintext keys in the format {secret} will continue to work for backwards compatibility.
Web registration templates redesign
The OIDC callback and device registration web pages have been updated to use the Material for MkDocs design system from the official
documentation. The templates now use consistent typography, spacing, and colours across all registration flows.
Database migration support removed for pre-0.25.0 databases
Headscale no longer supports direct upgrades from databases created before version 0.25.0. Users on older versions must upgrade
sequentially through each stable release, selecting the latest patch version available for each minor release.
BREAKING
-
API: The Node message in the gRPC/REST API has been simplified - the
ForcedTags,InvalidTags, andValidTagsfields have been removed and replaced with a singleTagsfield that contains the node's applied tags #2993- API clients should use the
Tagsfield instead ofValidTags - The
headscale nodes listCLI command now always shows a Tags column and the--tagsflag has been removed
- API clients should use the
-
PreAuthKey CLI: Commands now use ID-based operations instead of user+key combinations #2992
headscale preauthkeys createno longer requires--userflag (optional for tracking creation)headscale preauthkeys listlists all keys (no longer filtered by user)headscale preauthkeys expire --id <ID>replaces--user <USER> <KEY>headscale preauthkeys delete --id <ID>replaces--user <USER> <KEY>
Before:
headscale preauthkeys create --user 1 --reusable --tags tag:server headscale preauthkeys list --user 1 headscale preauthkeys expire --user 1 <KEY> headscale preauthkeys delete --user 1 <KEY>
After:
headscale preauthkeys create --reusable --tags tag:server headscale preauthkeys list headscale preauthkeys expire --id 123 headscale preauthkeys delete --id 123
-
Tags: The gRPC
SetTagsendpoint now allows converting user-owned nodes to tagged nodes by setting tags. #2885 -
Tags: Tags are now resolved from the node's stored Tags field only #2931
--advertise-tagsis processed during registration, not on every policy evaluation- PreAuthKey tagged devices ignore
--advertise-tagsfrom clients - User-owned nodes can use
--advertise-tagsif authorized bytagOwnerspolicy - Tags can be managed via CLI (
headscale nodes tag) or the SetTags API after registration
-
Database migration support removed for pre-0.25.0 databases #2883
- If you are running a version older than 0.25.0, you must upgrade to 0.25.1 first, then upgrade to this release
- See the upgrade path documentation for detailed guidance
- In version 0.29, all migrations before 0.28.0 will also be removed
-
Remove ability to move nodes between users #2922
- The
headscale nodes moveCLI command has been removed - The
MoveNodeAPI endpoint has been removed - Nodes are permanently associated with their user or tag at registration time
- The
-
Add
oidc.email_verified_requiredconfig option to control email verification requirement #2860- When
true(default), only verified emails can authenticate via OIDC in conjunction withoidc.allowed_domainsor
oidc.allowed_users. Previous versions allowed to authenticate with an unverified email but did not store the email
address in the user profile. This is now rejected during authentication with anunverified emailerror. - When
false, unverified emails are allowed for OIDC authentication and the email address is stored in the user
profile regardless of its verification state.
- When
-
SSH Policy: Wildcard (
*) is no longer supported as an SSH destination #3009- Use
autogroup:memberfor user-owned devices - Use
autogroup:taggedfor tagged devices - Use specific tags (e.g.,
tag:server) for targeted access
Before:
{ "action": "accept", "src": ["group:admins"], "dst": ["*"], "users": ["root"] }After:
{ "action": "accept", "src": ["group:admins"], "dst": ["autogroup:member", "autogroup:tagged"], "users": ["root"] } - Use
-
SSH Policy: SSH source/destination validation now enforces Tailscale's security model #3010
Per Tailscale SSH documentation, the following rules are now enforced:
- Tags cannot SSH to user-owned devices: SSH rules with
tag:*orautogroup:taggedas source cannot have username destinations (e.g.,alice@) orautogroup:member/autogroup:selfas destination - Username destinations require same-user source: If destination is a specific username (e.g.,
alice@), the source must be that exact same user only. Useautogroup:selffor same-user SSH access instead
Invalid policies now rejected at load time:
// INVALID: tag source to user destination {"src": ["tag:server"], "dst": ["alice@"], ...} // INVALID: autogroup:tagged to autogroup:member {"src": ["autogroup:tagged"], "dst": ["autogroup:member"], ...} // INVALID: group to specific user (use autogroup:self instead) {"src": ["group:admins"], "dst": ["alice@"], ...}
Valid patterns:
// Users/groups can SSH to their own devices via autogroup:self {"src": ["group:admins"], "dst": ["autogroup:self"], ...} // Users/groups can SSH to tagged devices {"src": ["group:admins"], "dst": ["autogroup:tagged"], ...} // Tagged devices can SSH to other tagged devices {"src": ["autogroup:tagged"], "dst": ["autogroup:tagged"], ...} // Same user can SSH to their own devices {"src": ["alice@"], "dst": ["alice@"], ...}
- Tags cannot SSH to user-owned devices: SSH rules with
Changes
- Smarter change notifications send partial map updates and node removals instead of full maps #2961
- Send lightweight endpoint and DERP region updates instead of full maps #2856
- Add NixOS module in repository for faster iteration #2857
- Add favicon to webpages #2858
- Redesign OIDC callback and registration web templates #2832
- Reclaim IPs from the IP allocator when nodes are deleted #2831
- Add bcrypt hashing for pre-authentication keys #2853
- Add prefix to API keys (
hskey-api-{prefix}-{secret}) #2853 - Add prefix to registration keys for web authentication tracking (
hskey-reg-{random}) #2853 - Tags can now be tagOwner of other tags #2930
- Add
taildrop.enabledconfiguration option to enable/disable Taildrop file sharing #2955 - Allow disabling the metrics server by setting empty
metrics_listen_addr#2914 - Log ACME/autocert errors for easier debugging #2933
- Improve CLI list output formatting #2951
- Use Debian 13 distroless base images for containers #2944
- Fix ACL policy not applied to new OIDC nodes until client restart #2890
- Fix autogroup:self preventing visibility of nodes matched by other ACL rules #2882
- Fix nodes being rejected after pre-authentication key expiration #2917
- Fix list-routes command respecting identifier filter with JSON output #2927
- API Key CLI: Add
--idflag to expire/delete commands as alternative to--prefix#3016headscale apikeys expire --id <ID>or--prefix <PREFIX>headscale apikeys delete --id <ID>or--prefix <PREFIX>
Upgrade
Please follow the steps outlined in the upgrade guide to update your existing Headscale installation.
It's best to update from one stable version to the next (e.g., 0.24.0 → 0.25.1 → 0.26.1) in case you are multiple releases behind. You should always pick the latest available patch release.
Be sure to check the changelog above for version-specific upgrade instructions and breaking changes.
Backup Your Database
Always backup your database before upgrading. Here's how to backup a SQLite database:
# Stop headscale
systemctl stop headscale
# Backup sqlite database
cp /var/lib/headscale/db.sqlite /var/lib/headscale/db.sqlite.backup
# Backup sqlite WAL/SHM files (if they exist)
cp /var/lib/headscale/db.sqlite-wal /var/lib/headscale/db.sqlite-wal.backup
cp /var/lib/headscale/db.sqlite-shm /var/lib/headscale/db.sqlite-shm.backup
# Start headscale (migration will run automatically)
systemctl start headscaleChangelog
- 9146140 Add headscale-operator
- bb30208 Add headscale-piying web UI to docs
- 25a7434 Bump version in mkdocs
- e43f19d CHANGELOG: add breaking change for Node API simplification
- d50108c Changelog: mark oidc.email_verified_required as breaking
- c3e2e57 Clarify autogroup:member
- 6d21a4a Document /version in the API docs
- 7d81dca Document how to disable the metrics interfaces
- 99d35fb Document oidc.email_verification_required
- 183a387 Fix list-routes examples
- 8387c9c Fix ownership description for auto approved routers/exits
- 18e13f6 Link to headscale.net for docs
- a445278 Mention tags on the features page
- eec54cb api/v1: replace ForcedTags/InvalidTags/ValidTags with Tags
- 606e5f6 changelog: fixups for 0.28.0-beta.2
- c1cfb59 ci: add ACL unknown user tests to integration workflow
- 1325fd8 cli,hscontrol: use ID-based preauthkey operations
- e0bae9b cli: add --id flag to API key expire/delete commands
- 72fcb93 cli: ensure tagged-devices is included in profile list (#2991)
- 165c5f0 cli: fix preauthkeys expire/delete argument validation
- 951fd5a cli: show Owner column in preauthkeys list
- 6654142 cmd/headscale: migrate tests from check.v1 to testify
- 0bcfdc2 cmd/hi: enable concurrent test execution
- 424e26d db: migrate tests from check.v1 to testify
- 4e1834a db: use PolicyManager for RequestTags migration
- aa29fd9 derp: migrate to derpserver package API
- 84c092a flake.lock: Update
- 8631581 gen: regenerate proto code
- a04b21a gen: regenerate protobuf and type views
- 8776745 gen: regenerate protobuf code
- 0516c0e gen: regenerate protobuf code
- 515a22e go.mod: remove gopkg.in/check.v1 dependency
- 0565e01 go.mod: update dependencies
- a194712 grpc: support expire/delete API keys by ID
- c8c3c9d hscontrol: allow CreatePreAuthKey without user when tags provided
- 3b4b9a4 hscontrol: fix tag updates not propagating to node self view
- 4ab0693 hscontrol: handle tags-only PreAuthKeys in registration
- 07a4b1b integration/tags: add dedicated issue #2978 reproduction test
- 1b6db34 integration/tags: add self-tag validation to existing tests
- 87c230d integration: add run ID isolation for concurrent test execution
- 2e180d2 integration: add test for reauth tag removal
- 98c0817 integration: add tests for ACL group with deleted/unknown users
- b3c4d0e integration: add tests for API key expire/delete by ID
- b8f3e09 integration: fix tags-only auth key tests
- 740d2b5 integration: support auth keys without user
- 00da536 integration: test tags-only auth key behavior
- 4dd1b49 integration: update CLI tests for ID-based preauthkey commands
- db6882b integration: update DeleteAuthKey to use ID
- e9a94f0 integration: update SSH tests for validation rules
- aee1d2a nix: fix deprecated attributes and update dev tools
- 92caadc nix: update vendor hash for Go dependencies
- f5c7796 nix: use testers.nixosTest instead of nixosTest
- 5688c20 policy/v2: validate SSH source/destination combinations
- 22afb2c policy: fix asymmetric peer visibility with autogroup:self
- d40203e policy: update tests for SSH validation rules
- b01eda7 proto: add id field to API key expire/delete requests
- 1398d01 proto: change preauthkey API to ID-based operations
- 5103b35 sqliteconfig: add config opt for tx locking
- 42bd9cd state: add GetAPIKeyByID method
- d9cbb96 state: add unit test for DeleteUser change signal
- 0451dd4 state: allow untagging nodes via reauth with empty RequestTags
- 00f22a8 state: disable key expiry for nodes with approved advertise-tags
- 1d99002 state: disable key expiry for tagged nodes
- 4be13ba state: update policy manager when deleting users
- 3689f05 types: use Username() in User.Proto() when Name is empty
- a669658 util/dns: fix variable redeclaration in ValidateDNSName