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.
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
- Tags: The gRPC
SetTagsendpoint now allows converting user-owned nodes to tagged nodes by setting tags. Once a node is tagged, it cannot be converted back to a user-owned node. #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 at registration time
- The
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
oidc.email_verified_requiredconfig option to control email verification requirement #2860- When
true(default), only verified emails can authenticate via OIDC withallowed_domainsorallowed_users - When
false, unverified emails are allowed for OIDC authentication
- When
- 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
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
- c460034 .github/workflows: prebuilt integration test artifacts (#2954)
- 2c3c943 .github/workflows: split long TestAutoApproveMultiNetwork into multiple jobs
- 5655ef8 AGENTS: golangci-lint from main, no "full matrix"
- 249630b Add API documentation
- 14af9b3 Add docs to manage headscale from another local user
- 21af106 Containers should be read-only
- a288f04 Dockerfile: align packages
- 9c33cbf Exclude docs/ only for prettier pre-commit hook
- 665cc44 Explicitly drop
apt-get cleanand usedist-clean - c5133ee Fix trailing whitespace
- 5c6cd62 Legacy preauthkeys must be used as-is
- e86d063 Mention /health instead of /windows
- f00c412 Move static doc assets into docs/assets
- 2010805 Provide Headscale's favicon at its expected place
- 72d5fd0 Remove duplicated documentation and link to getting started instead
- e0c9e18 Update OIDC documentation for allowed groups filter
- 9b327f6 Update pre-commit-hooks
- 6359511 Use debian13 distroless images
- bba91a8 Use lists for integration docs
- 218a8db add favicon to webpages (#2858)
- 6d24afb add pre-commit hooks, move claude to agents. (#2877)
- 0e16730 all: remove deadcode (#2952)
- 56bec66 app: only wire up debug server if set
- 3cf2d71 auth: ensure machines are allowed in when pak change (#2917)
- f3767dd batcher: ensure removal from batcher
- 616c0e8 batcher: fix closed panic
- 7fb0f9a batcher: send endpoint and derp only updates. (#2856)
- e875361 capver: generate
- 8394e70 capver: update latest (#2774)
- 5767ca5 change: smarter change notifications
- 1dcb04c changelog: add changelog entry
- 2aa5b8b changelog: add entry for templates redesign
- 705b239 changelog: prep for 0.27.2 rc
- 3f0bfe2 changelog: prepare for 0.28.0 beta
- 0078eb7 chore: fix filterHash to work with autogroup:self in the acls (#2882)
- f3f2d30 cli: better formatting of lists (#2951)
- 16d811b cli: remove node move command (#2922)
- ed78bf4 cmd/hi: improve test cleanup to reduce CI disk usage (#2881)
- bfcd9d2 cmd/hi: reject if we are already running (#2919)
- 4b25976 db: add comment to always check errors in migration
- 1c146f7 db: remove _schema from migration tests
- d2fcd5b docs(tools): Add tailscale-exporter
- daf9f36 editorconfig: add basic editor config
- 299cef4 fix: free ips from usedIps ipset on DeleteNode
- 5d0a6ab fix: list-routes command now respects identifier filter with JSON output
- 75e24de flake: disable CGO in dev shell
- cf1ad47 flake: remove hi from shell
- 9368fee generate: add new patches (#2921)
- 87bd673 golangci-lint: use forbidigo to block time.Sleep (#2946)
- 75247f8 hscontrol/db: add init schema, drop pre-0.25 support (#2883)
- cb4d5b1 hscontrol/oidc: fix ACL policy not applied to new OIDC nodes (#2890)
- db293e0 hscontrol/state: make NodeStore batch configuration tunable (#2886)
- 285c4e4 hscontrol/templates: add Material for MkDocs design assets
- 3ed1067 hscontrol/templates: refactor to use CSS classes and embedded files
- a496864 hscontrol: add template HTML consistency test
- e3ced80 hscontrol: consolidate assets into single package
- 09c9762 hscontrol: convert BlankHandler to use elem-go
- 1f5df01 hscontrol: log acme/autocert errors (#2933)
- 4e77e91 hscontrol: use octal literal syntax in test
- 21ba197 integration: make entrypoint override more robust
- a50bd13 integration: prepare AutoApprove test for new tags
- f67ed36 integration: replicate tag propagation issue
- eb788cd make tags first class node owner (#2885)
- 82d4275 mapper: correct some variable names missed from change
- c8376e4 mapper: move tail node conversion to node type (#2950)
- eec196d modernize: run gopls modernize to bring up to 1.25 (#2920)
- d14be8d nix: add NixOS module and tests (#2857)
- 7be2091 oidc: make email verification configurable
- f0e464d policy: add test to confirm group cant approve tag
- 15c84b3 policy: allow tags to own tags (#2930)
- 9d77207 policy: clarify usernam resolve comment
- 506bd8c policy: more accurate node change
- 000d5c3 prettier: use standard config for all files including changelog (#2879)
- 22ee2bf tags: process tags on registration, simplify policy (#2931)
- 89285c3 templates: migrate OIDC callback to elem-go
- 251e16d tools/capver: regenerate from docker tags
- 642073f types: add option to disable taildrop, improve tests (#2955)
- da9018a types: make pre auth key use bcrypt (#2853)