v0.28.0
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
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
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 headscale
Changelog
- 7f003ecafff59e627fda3f9597bd3e7d28cacf53 Add a page to describe supported registration methods
- 5d300273dc57d552c64d9ebd0142f1bce8a1bf66 Add a tags page and describe a few common operations
- d32f6707f7e2f8e670a6aadf155817bb1ebcb194 Add missing words
- 89e436f0e6abdb4aa259425699aca8c046c332f4 Bump year/version for mkdocs
- 49b70db7f2997a0a13a68ba50390feac937dd488 Conversion from personal to tagged node is reversible
- 04b4071888980f7944d231487790158553d2c9a1 Fix node expiration success message
- ee127edbf7fcbfc949fbcce56e4307730ae72c51 Remove trace log for preauthkeys create
- 2695d1527e6edb76a151b4a72e1cebb0d349a228 Use registration key instead of machine key
- 44af046196e9824394f3cca4c8c0329279bb9b5e all: update Go module dependencies
- 4a744f423b7cd47c4432b8d174057a60b58cd111 changelog: change api key format
- 97fa117c48a58bee3941e5e8b4393873501afe14 changelog: set 0.28 date
- b5329ff0f3acf0d4fbbc8457c05ac8e8a5cdc2a1 flake.lock: update nixpkgs to 2026-02-03
- eac8a57bce7688efddaa4ad0b3ca07244a9712c5 flake.nix: update hashes for dependency changes
- ca75e096e6833c0a01d14381a1b9cacf12e7272f integration: add test for tagged→user-owned conversion panic
- a09b0d1d6919058de6ed58557032bcd7a671bb22 policy/v2: add Caller() to log statements in compileACLWithAutogroupSelf
- 1f32c8bf615ce97b21bdb29dc920c1227f058df1 policy/v2: add IsTagged() guards to prevent panics on tagged nodes
- c2f28efbd710c129b1c62dcffa9041e99860b0b3 policy/v2: add test for issue #2990 same-user tagged device
- 11f0d4cfdd935b3cc7612eab48a75a29c9c910b4 policy/v2: include nodes with empty filters in BuildPeerMap
- 362696a5ef220a09b10459f6a899d2a5720bcab7 policy/v2: keep partial IPSet on SSH destination resolution errors
- fb137a8fe3bfc7e4c739bceb30a5297ebe8b11eb policy/v2: use partial IPSet on group resolution errors in autogroup:self path
- df184e5276ae2ea827955f9d4332386734cc4367 state: fix expiry handling during node tag conversion
- 306aabbbce1fbcedad8e74b180490b266d993667 state: fix nil pointer panic when re-registering tagged node without user
- 4912ceaaf5f8576ef7270f91c3b568caa74b7f92 state: inline reauthExistingNode and convertTaggedNodeToUser
- 46daa659e23278751063001a402f308f35693dc3 state: omit AuthKeyID/AuthKey in node Updates to prevent FK errors
- 0630fd32e5f5abf73f04daf5b282da904c7c4734 state: refactor HandleNodeFromAuthPath for clarity
- ce7c256d1e30dc2583e32d557432879bea6ef9b0 state: set User pointer during tagged→user-owned conversion
- d7f7f2c85e762bba3f11cae10a31f7099af960ce state: validate tags before UpdateNode to ensure consistency