Tailscale parity with T3 Connect

On your personal tailnet, Tailscale already knows which devices are yours. T3 Code trusts that. Your own devices find every box and connect to it with no pairing code, no account, and no cloud in the path.

This is research only. No code changed. It is based on commit a4e1986585 (2026-10-28), 7 research agents, and a review council. The decisions are at the end.

Do this first

  1. Fix 3 gates with PRs that already exist: route flapping, the Serve switch, and Serve recovery.
  2. Ship honest status.
  3. Ship Tailscale sign-in, discovery, and npx t3 up.

Releases 2 and 3 do not depend on each other. Both can start after Release 1.

Your setup, step by step

The setup is 1 laptop with the app, 5 or more headless Linux servers, and a phone. All of them are on your personal tailnet.

StepWhat you doWhat happens
1. Each servernpx t3 upOnly the tailnet can reach the box. T3 runs as a background service, and Tailscale sign-in is on. The command prints a QR code. You type no code.
2. LaptopNothing, or turn on "Tailscale sign-in" in Settings if you also want to reach the laptop from the phoneThe desktop app finds every machine on your tailnet that runs T3 and connects to it. The switch also opens the laptop to the tailnet on port 3773.
3. PhoneScan any QR code once, or type one machine name. Tailscale must be on.The phone connects to that machine and gets the list of the others from it, then connects to them too.
4. Laptop goes offlineNothingThe phone stays connected. Each server checks with Tailscale itself. No laptop and no cloud are in the path.
5. Change things from the phoneNothing extraThe phone does not need the laptop. A new box appears through any machine the phone is connected to.

How sign-in works

  1. Your device connects to the box at its direct tailnet address, http://<100.x>:<port>. It sends a DPoP proof to /api/auth/tailnet.
  2. The box asks Tailscale who owns the connecting address (tailscale whois). WireGuard makes that address hard to fake. If the device is an untagged device that you own, the box issues a 2-minute grant bound to the device's key.
  3. The device exchanges the grant at /oauth/token for a 1-hour session. It renews the same way, always at the direct tailnet address, and every check runs again.

The grant and the session use the same code as T3 Connect: createPairingLink and the DPoP exchange. No new session store, scopes, or token format.

This works on the native desktop and mobile apps. Browser clients, hosted or self-hosted, keep pairing codes. The guard refuses web origins, and a page on plain http://100.x cannot make a DPoP key.

Your 3 asks

AskAnswerRelease
Discovery and no pairing codesTailscale sign-in for your own devices in the desktop and mobile apps. Desktop reads the tailnet peer list. Phones get the list from any connected machine.3
Clear machine statusThe host reports its Tailscale state. Each failed route gets its own message. Status dots appear in the composer picker and the sidebar.2
Off-tailnet statesDesktop reads its own Tailscale state. When every tailnet route fails but other routes work, mobile and web show a hint.2

Terms

Where we are

Works today

Broken or missing (checked in code)

Release 1: reliable connections

Done when:

  1. Route rule: rebase #25529, and close #24849, which has the same diff (decision 5).
  2. The switch follows the saved choice: #15027, then #26170. Fold in the copy from #24638.
  3. Serve retry and ownership: combine #23605 and #24943, with the rule from decision 4.
  4. The Serve probe checks the environment ID. About 10 lines.
  5. The startup QR uses the Serve URL: #25351 (clean).

Release 2: useful status

  1. Host Tailscale facts (300 to 450 lines). The host reads login state, key expiry, health, HTTPS, and MagicDNS. Clients show facts such as "Tailscale on studio is signed out" over any connected route. Add t3 tailscale status.
  2. A diagnosis for each route (about 250 lines). Tailscale failures get their own message and a help link.
  3. "This device is off the tailnet" (about 200 lines). Desktop reads its own login state. Mobile and web show a hint when every tailnet route fails but other routes work.
  4. Status dots in the composer picker and the sidebar (60 to 100 lines). The dots are static. The banner says "offline" only for a machine that is really offline.

Release 3: Tailscale sign-in and discovery

One command on each box

studio-vps $ npx t3 up

  Tailscale  signed in (studio-vps.tail1234.ts.net)
  Owner      theo@ (the owner of this box)
  Network    Tailscale only, LAN closed
  Sign-in    on for your own Tailscale devices
  Service    installed, starts on boot

  Scan to add this box on your phone (http://100.88.1.2:3773):
  [QR code]
  Your other devices find it on their own.

  Tip: this box is not tagged. If agents run here, tag it so they
  cannot sign in to your other machines. Add to your ACL:
    "tagOwners": { "tag:server": ["autogroup:admin"] }
  then run: sudo tailscale set --advertise-tags=tag:server

Discovery

What we build (rough: 2,300 to 3,300 lines with tests)

PartWorkLines
ServerThe sign-in endpoint with every check in the security model. whois through LocalAPI or the CLI, with single-flight and a rate limit300 to 400
ServerBlock and Unblock, revoke by subject, and one transaction for the grant, the session, and the block check150 to 250
Client runtimeA new tailnet DPoP profile kind that pins the direct address (today only t3-connect exists, catalog.ts:26). Renewal without a cloud session. Paired tailnet devices switch to Tailscale sign-in when their old session ends350 to 550
DesktopThe "On your tailnet" list, adding machines automatically, remembering removals, and the address-conflict warning250 to 350
Server and mobileThe peer list from connected machines, so phones find new boxes300 to 400
CLIt3 up: the Tailscale and userspace checks, the owner, settings, the service, the QR code, the tagging tip, and --https250 to 350
UIQR scan and add by name on mobile, sign-in states, Block in Sharing & access, and the desktop port warning200 to 300
Tests500 to 700

Security model

Trust comes from Tailscale. Any untagged device you own on your tailnet gets full control of your T3 boxes: terminal, files, and access. On a shared tailnet, the box still accepts only your own devices.

Parity with T3 Connect

CapabilityT3 ConnectTailscale todayAfter this plan
Connect with no codeYesNoYes, on your own devices
No 30-day lockoutYesNoYes, renewal is automatic
Machine listAccount listNoDesktop: automatic. Phone: one QR scan, then automatic
Works with no internet service upNo, needs the relayYesYes, no cloud in the path
Status with causes and fixesAbout 15 causesGenericDiagnosis for each route, plus host facts
Browser clients (hosted or self-hosted)YesNeed a codeStill need a code. Later (Serve identity)
Push notificationsYesNoLater (optional T3 Connect link)
Public webhooks, hosted outside agentsYesNoCannot match privately. We document it

Later

Do not build

IdeaReason
Tailscale API key or OAuth clientIt only lists devices, which tailscale status already does for free, and it authorizes nothing. Tailscale's new OAuth apps can only add devices
Approvals for each deviceOn a personal tailnet, Tailscale already says which devices are yours. Copying approvals between boxes had holes
tsnet / libtailscaleA second node for each machine, node keys in T3 state, and no Node binding
Tailscale Services, mDNS, port-range scansServices need admin setup and tags. Tailscale has no mDNS. Scans miss custom ports

Test first on real devices

PR queue (states on 2026-10-28)

"Conflicting" means the PR needs a rebase.

PRTopicState
#25529Keep healthy sessions on their route (gate)Conflicting
#24849Same diff as #25529. Close itConflicting
#15027The Serve switch follows the saved choice (gate)Conflicting
#26170Enable Serve while Network access is offCI fails "Agent context budget"
#23605Serve retry (gate, combine with #24943)Conflicting
#24943Serve ownership checkClean
#25351The startup QR uses the Serve URLClean
#25174Port conflict on update. Pick it and close #25171Clean
#25217Windows host-only adapters. Pick it and close #21056Clean
#25991Hotspot and VPN addresses are not LAN routesClean
#23030The WSL tailnet addressClean
#24064Fewer backoff resets on foregroundClean

Decisions so far

#Decision
1Your own untagged devices sign in with zero clicks on a personal tailnet. t3 up or the Settings switch is the opt-in. This replaces the one-tap approval for each device.
2The hosted web app keeps pairing codes until Serve identity is designed.
3The account fleet with no tunnel is a later add-on. If it ships, hosts opt in before their tailnet address goes to the relay.
4T3 overwrites or removes a Serve mapping only when it is ours or stale.
5Never close a healthy session to try a better route.
6A "Tailscale only" network mode. t3 up turns it on.
7Only personal tailnets matter. On a shared tailnet, the box still accepts only your own devices.
8Apps add the T3 machines they find on their own and show a notice. A machine you remove stays removed.
9On an untagged box, t3 up prints a short tip about tagging servers that run agents.
10Each box has Block and Unblock for each device.

Questions for you

None right now. Every decision is in the table above.