SSD Nodes Learn Hosting plans →
Guides Matt ConnorBy Matt Connor

What Tailscale's tailnet lock actually protects

Tailnet lock stops a compromised Tailscale coordination server from adding a node to your tailnet. It also gives you ten secrets you must not lose.

What tailnet lock protects

Tailnet lock is the Tailscale feature that stops Tailscale's own coordination server from adding a device to your tailnet. With it enabled, your nodes refuse any node key that has not been signed by a key held on a machine you already trust, so the control plane still distributes keys but can no longer create members. That claim is narrow on purpose. Tailnet lock guards the moment a device joins, and it does nothing for a device whose key has already been stolen.

In an ordinary tailnet, each node generates its own WireGuard keys and never sends the private half anywhere. The coordination server, the control plane that every client talks to, distributes public keys and tells each node who belongs. That is the design Tailscale's coordination server and key distribution rests on, and it is why Tailscale never holds the keys that encrypt your traffic. It also means the control plane decides membership on its own. Someone in control of it could publish one extra node key into your tailnet, and your nodes would encrypt to it, because nothing in the protocol let a node tell an injected key from a real one.

The threat model, stated precisely

The attacker tailnet lock answers is a party with control of the coordination server. That covers a compromise of Tailscale's infrastructure, a malicious insider there, and an order that compels Tailscale to act. Against that attacker, and only that attacker, tailnet lock changes the answer from "they can add a node" to "they cannot, and the attempt is visible".

The mechanism is a signature chain you own. Each signing node generates a tailnet lock key (TLK) locally and keeps it on that device. Your tailnet gets an append-only log of authority updates, the tailnet key authority (TKA), and every node holds its own copy of that log. A node key that arrives without a valid signature from a currently trusted TLK is refused, so the peer gets no connectivity and shows up as locked out. Tailscale's white paper states the result plainly: Tailscale infrastructure cannot add an unauthorised node to a tailnet with tailnet lock enabled, and any attempt to do so can be detected and blocked.

Four things it does not cover, and every one of them matters more than the thing it does cover for most tailnets.

  • A stolen device. A signature records that a trusted admin approved that node key at some point. It says nothing about who holds the laptop now.
  • A compromised signing node. Tailscale's own limitations list says it directly: tailnet lock keys are stored on the device, so an attacker who gets the device can get the key. A signing node deserves the care you would give a machine holding a root SSH key, which is the same discipline covered in generating, storing and rotating SSH keys.
  • Denial of service. The white paper is explicit that tailnet lock protects against unauthorised nodes, not denial of service. A hostile control plane can still stop distributing updates and break your connectivity. It just cannot become a member.
  • The first five minutes. See the next section, because this is the part people skip.

Why tailnet lock is trust on first use

When you enable tailnet lock, the initial set of trusted keys reaches your nodes through the control plane, which is the party you are trying to remove trust from. Every node accepts what it is told the first time and enforces it from then on. Tailscale's white paper names this gap: when tailnet lock is first enabled, each node relies on the initial state of tailnet lock sent to it from the control plane. A control plane that was already compromised at that moment could seed a key set containing an attacker's key, and every later signature would check out.

This is trust on first use (TOFU), the same model as an SSH host key fingerprint you accept on a first connection. There is no external authority to check against, so the check is manual and it is yours to run.

tailscale lock status

Run that on several nodes after enabling. Compare the trusted tlpub: values each one reports against the keys your signing nodes actually printed. Compare them over a channel that does not depend on the tailnet, because a compromised control plane that seeded a bad key set can also see the chat you are using to check it. This is a one-time job that takes ten minutes and is the only thing standing between you and a lock that guards nothing.

Check these before you turn it on

  • Every node you want to keep working needs Tailscale v1.46.1 or later, the minimum version Tailscale's documentation names for tailnet lock. Run tailscale version on each one, including the router or appliance you enrolled once and forgot about.
  • You must select at least two signing nodes. The reason is not ceremony: the signing keys live on those devices, so a single signing node is one dead disk away from a tailnet you can never add a machine to.
  • An Android device cannot act as a signing node, because it cannot perform the signing operation.
  • Tailnet lock and device approval are mutually exclusive features. If your tailnet already requires manual device approval, you are choosing between the two, not stacking them.
  • Tailscale's documentation lists tailnet lock on the Personal and Enterprise plans as of September 2026, so confirm your plan before you promise the control in a security review.

How to turn tailnet lock on

The admin console builds the command and you run it on a machine. Neither half works alone.

  1. In the admin console, open the Device management page and choose to enable tailnet lock.
  2. Select the nodes whose tailnet lock keys you want to trust. Pick at least two, on hardware you can physically reach.
  3. Decide whether to send one disablement secret to Tailscale support. Read the next section before you answer this.
  4. Copy the tailscale lock init command the console generates. It carries one tlpub: argument per signing node you selected.
  5. Run it on one of those signing nodes.
tailscale lock init "tlpub:SIGNING_NODE_1_KEY" "tlpub:SIGNING_NODE_2_KEY"

Every node already in the tailnet is signed by the trusted keys during initialisation, so nothing that was working stops working. New nodes are what changes. A machine that joins a locked tailnet arrives with an unsigned node key, and tailscale lock status on that machine says so:

This node is LOCKED OUT by tailnet-lock, and action is required to establish connectivity.

The admin console shows the same state as a Locked out badge, and the machines-list filter property:locked-out finds all of them at once. The status output on the locked out node also prints the exact command that fixes it. Copy that line and run it on a signing node:

tailscale lock sign "nodekey:NODE_KEY" "tlpub:ROTATION_KEY"

Signers change over time, and two commands cover that. tailscale lock add tlpub:<key> trusts a new signing node. tailscale lock remove tlpub:<key> retires one, and by default it re-signs the nodes that the retired key had signed so they keep working, which you suppress with --re-sign=false. A signing node that was stolen rather than retired calls for tailscale lock revoke-keys tlpub:<key> instead, which runs in stages across your remaining signers using --cosign and then --finish. tailscale lock log --limit 20 prints the recent authority history, which is where you look when a node is locked out and nobody remembers changing anything.

The ten disablement secrets, and why they are the risky part

tailscale lock init prints ten disablement secrets. They are displayed once, at initialisation, and never again. Any single one of them turns tailnet lock off for the whole tailnet:

tailscale lock disable "DISABLEMENT_SECRET"

Tailscale's documentation states the consequence without softening it: if you lose your disablement secrets, and you did not provide one to Tailscale support, the tailnet cannot be recovered. Picture the real version of that. Your two signing nodes are a laptop that was wiped and a VPS that was deleted. Nobody can sign a new node key, nobody can add a signing node, and nobody can turn the lock off. The tailnet keeps running for existing members and accepts no new ones, permanently. The way out is building a new tailnet and re-enrolling everything.

So store the secrets like the recovery codes they are. Keep at least two copies, in places that do not both depend on the tailnet being reachable, and keep one of them offline. A copy that lives only on a server you reach through the tailnet is not a backup of anything.

The support option deserves a real decision rather than a default. Sending one secret to Tailscale support means Tailscale can disable your tailnet lock, which hands a piece of the guarantee back to the exact party the feature exists to constrain. It also means a lost binder does not end your tailnet. If you enabled tailnet lock because a third-party-risk review asked what happens when your VPN vendor is breached, do not send the secret. If you enabled it because admins come and go and you want node admission tied to devices, send it and sleep better.

Why unattended provisioning breaks, and how to fix it

This is the consequence teams hit within a week. In a locked tailnet, a machine that boots and runs tailscale up with an ordinary auth key joins locked out. The automation reports success, the node appears in the console, and nothing can reach it. Signing has to happen before the node exists, not after, which means signing the auth key.

AUTH_KEY="tskey-auth-xxxxxxxxxxxxxxxx"
tailscale lock sign $AUTH_KEY

Run that on a signing node. It prints a signed version of the auth key, and that signed value is what your image, cloud-init file or Terraform variable passes to tailscale up --auth-key. Any node created with it arrives already signed and reachable.

Two failure modes are worth knowing before you meet them. First, signing does not like concurrency. Issue 15266 in the tailscale/tailscale repository, filed in March 2025 and still open, reports Terraform runs where concurrent tailscale lock sign calls returned blank signed keys, so a subset of the nodes came up locked out while the rest worked. The reporter's workaround was signing one key at a time with a short pause between calls. Make your automation check that the command returned a non-empty key before it stores one.

Second, signed auth keys leave state behind. Signing adds a key to the authority, and that key stays after the node it created is gone. Issue 16607, from July 2025, describes automation that signed a fresh key per deployment until the authority hit its ceiling:

network-lock modify failed: modify network-lock keys: generating checkpoint: generated update was invalid: checkpoint state: too many keys (552, max 512)

At that point the tailnet could neither add keys nor remove the excess ones, because the removal is itself an authority update that has to produce a valid checkpoint. Sign few keys and reuse them rather than signing one per machine, and check tailscale lock log occasionally so the count is something you know rather than something you discover.

Ephemeral and CI nodes need a plan

Ephemeral nodes, the ones that remove themselves from the tailnet when they log out, are still nodes, so they still need a signature to talk to anything. A CI job that joins your tailnet to run a deployment needs a pre-signed auth key exactly like a long-lived server does. CI is also where the key accumulation above bites hardest, because CI is where you create and destroy the most nodes.

The workable pattern is one signed, reusable, ephemeral auth key held in the CI secret store, rotated on a schedule you pick rather than on every job. Rotation costs one key in the authority each time, which is a number you can plan around. Signing per job is what produced 552 keys.

The same thought applies to the servers that carry other machines' traffic. a subnet router advertising a private range from a VPS speaks for every address behind it, so an injected node in that position reaches far more than one host. Those are the boxes to provision with signed keys and to keep out of the fully automatic path.

The two escape hatches, and what each one does

tailscale lock disable <disablement-secret> turns tailnet lock off for the whole tailnet. It needs one of the ten secrets, and it is the answer when the authority itself is the problem.

tailscale lock local-disable

tailscale lock local-disable is the per-node hatch, and its scope is commonly misread. It makes the node you run it on stop enforcing tailnet lock, so that node will accept peers whose keys are unsigned. It does not make other nodes accept that node's unsigned key. A locked out server does not become reachable because you ran local-disable on it. That is why Tailscale's documentation describes running the command on each of your nodes to make the tailnet in effect ignore tailnet lock. Treat it as a break-glass step for a node that cannot be signed right now, then sign the node properly and stop leaving enforcement off.

Who should turn tailnet lock on, and who should not

Turn it on if node admission needs to survive people leaving. Without lock, anyone with admin rights in the console can add a machine. With lock, adding a machine also requires a device holding a trusted signing key, so a departing admin whose console access you forgot to revoke still cannot introduce a node. Turn it on if a customer's third-party-risk questionnaire asks what stops your VPN vendor from joining your network, because this is the control that answers that question with a mechanism instead of a promise.

Do not turn it on for a one-person tailnet with a laptop, a phone and a VPS. The realistic threat to that tailnet is you losing access to it, not Tailscale being compromised. Tailnet lock adds ten secrets you must store correctly forever, and losing them is unrecoverable, so it raises the risk you actually face in order to lower one you do not. The same reasoning applies to a small team without an inventory of who holds which signing device. Get that bookkeeping right first, because tailnet lock is bookkeeping with a permanent failure mode attached.

Headscale answers the same question a different way

If the objection is that a third party decides who is in your network, there are two answers. Tailnet lock keeps Tailscale's coordination server and removes its power to add members. Running Headscale, the open source coordination server you host yourself removes the server instead, and you keep both the power and the work of running it: patching, backups and an outage that is yours to fix at two in the morning. Neither one is more secure in the abstract. Choose based on which failure you would rather own, a hosted control plane you have constrained, or a control plane you operate.

FAQ

What does tailnet lock actually stop?

It stops Tailscale's coordination server from adding a node to your tailnet. With tailnet lock enabled, a node key is only accepted after a signing node you control has signed it with its tailnet lock key, so a compromised control plane can distribute keys but cannot introduce a member. It does not encrypt anything extra, because traffic between nodes is already end to end encrypted with WireGuard keys the coordination server never holds. It also does not help against a stolen device, a compromised signing node, or a control plane that simply stops serving your tailnet.

What happens if I lose all ten disablement secrets?

The secrets are printed once, when tailscale lock init runs, and are never shown again. If you lose all of them and did not send one to Tailscale support, the documentation says the tailnet cannot be recovered. In practice, if you also lose your signing nodes, you can never sign another node key and can never turn the lock off, so the only path forward is a new tailnet with every device re-enrolled. Keep two copies in places that do not both depend on the tailnet being up, and keep one of them offline.

Do I have to sign every new device by hand?

No. Sign the auth key instead of the node. On a signing node, export the key and run tailscale lock sign $AUTH_KEY, then pass the signed value the command prints to tailscale up --auth-key in your image or provisioning tool. Nodes created that way arrive signed. Sign a small number of reusable keys rather than one per machine, because each signed key adds a key to the authority that stays after the node is gone, and the authority has a 512 key ceiling that automation has hit in the field.

Is tailnet lock the same as device approval?

No, and you cannot run both, because they are mutually exclusive features. Device approval is a policy check in the admin console: an admin ticks a box before a new device gets access, and the coordination server enforces that decision. Tailnet lock is a cryptographic check performed by your own nodes, using keys held on your own hardware, which is why it still holds if the coordination server is hostile. Device approval is the lighter control for managing people. Tailnet lock is the one that answers a question about the vendor.

#tailscale#tailnet-lock#vpn#key-management#security