Skip to content

fix: survive target reinstalls, surface unapplied serves, dial 127.0.0.1 (1.102.4:1) - #14

Merged
MattDHill merged 1 commit into
masterfrom
fix/serve-routes
Sep 20, 2026
Merged

MattDHill merged 1 commit into
masterfrom
fix/serve-routes

Conversation

@helix-a

@helix-a helix-a commented Sep 20, 2026 •

Copy link
Copy Markdown
Member

Summary

  • A serve route reads its target's host reactively, in main and in the url-v0 export, so a target that is reinstalled gets its forwarder and its address row back on its own. Adding a serve that already exists refreshes it instead of failing, and a port held by a route whose target was uninstalled is released to the new serve.
  • A standalone Tailscale Serve health check compares tailscale serve status --json against every saved route whose target still resolves and fails naming any that are not applied. tailscale serve --bg exits 0 without applying anything when HTTPS Certificates are not enabled for the tailnet (enableFeatureInteractive prints the enablement URL and os.Exit(0)s), so the apply oneshots prove nothing on their own. The check is disabled with no routes and waiting until the node is signed in, and requires only tailscaled: requiring the apply oneshots would leave a hard-failing apply as a bare "waiting" forever.
  • Serve targets dial 127.0.0.1 instead of localhost, so no SNI reaches a target's SSL bridge port on StartOS 0.4.0.2 (the part of fix: dial a target's SSL bridge port without SNI; move to start-sdk 3.0 #11 that does not need start-sdk 3.0).
  • 1.102.4:0 → 1.102.4:1; README and instructions updated.

Closes #8. Closes #9. Refs #7, #11.

Verified

On a 0.4.0.2 box with no tailnet, with a MagicDNS name seeded into ts-status.json: add, re-add, live-port collision and orphaned-port release through the actions; the address row returning after the target package was uninstalled and reinstalled; the forwarder relaunching with it; the health check's disabled and waiting states.

Not verified: the check's signed-in states (success, and failure naming the route). That needs a signed-in node.

…0.1; 1.102.4:0 → 1.102.4:1

A serve route now reads its target's host reactively, in main and in the
url-v0 export, so a target that is reinstalled gets its forwarder and its
address row back on its own (#8). Adding a serve that already exists
refreshes it instead of failing, and a port held by a route whose target
was uninstalled is released to the new serve.

`tailscale serve --bg` exits 0 without applying anything when HTTPS
Certificates are not enabled for the tailnet (enableFeatureInteractive
prints the enablement URL and os.Exit(0)s), so the apply oneshots prove
nothing. A standalone "Tailscale Serve" health check compares
`tailscale serve status --json` against the saved routes and fails naming
the ones missing; disabled with no routes, waiting until signed in (#9).
It requires only tailscaled: requiring the apply oneshots would leave a
hard-failing apply as a bare "waiting" forever.

Serve targets dial 127.0.0.1 instead of localhost: an IP literal sends no
SNI, which is all a target's SSL bridge port answers on StartOS 0.4.0.2
(#7, taken from #11).

Verified on a 0.4.0.2 box with no tailnet: add, re-add, live-port
collision and orphaned-port release through the actions; the address row
returning after the target was uninstalled and reinstalled; the health
check's disabled and waiting states. The check's signed-in states
(success, failure naming the route) are unverified.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
@MattDHill
MattDHill merged commit c05a9d3 into master Sep 20, 2026
3 checks passed
@MattDHill
MattDHill deleted the fix/serve-routes branch September 20, 2026 19:08
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

2 participants