[Bug]: --tailscale-serve leaves headless backend classified as local-only
Nobody has claimed this yet.
Assessment
- Difficulty
- 2/5
- Estimated time
- 1-3 hours
- Newbie friendliness
- 76/100
- Issue type
- Bug
- Clarity
- Clearly specified
- Activity status
- Quiet
- Tech stack
- typescript
- Domain
- authentication, backend
Research direction
Start with EnvironmentAuthPolicy.ts and trace how the bind host determines the remote-reachable policy, then inspect ConnectionsSettings.tsx to see how that policy controls pairing and authorized-client actions. Reproduce with --tailscale-serve on a loopback bind and verify that the controls become available without requiring --host 0.0.0.0.
Written by the indexing model from the issue text.
Description
Before submitting
- I searched existing issues and did not find a duplicate.
- I included enough detail to reproduce or investigate the problem.
Area
apps/server
Steps to reproduce
-
Start T3 Code:
npx t3@nightly serve --tailscale-serve --tailscale-serve-port 443 -
Confirm that T3 reports both:
Listening on http://127.0.0.1:3773
Tailscale Serve configured -
Open the Tailscale Serve URL from another device:
https://<machine>.<tailnet>.ts.net -
Navigate to Settings → Connections.
-
Attempt to manage remote pairing or authorized clients.
Expected behavior
A backend exposed through --tailscale-serve should be treated as remotely reachable.
Settings → Connections should allow pairing links and authorized clients to be managed while the
underlying HTTP server remains bound securely to 127.0.0.1.
Actual behavior
Settings → Connections reports:
This backend is only reachable on this machine. Restart it with a non-loopback host to enable remote
pairing.
The remote pairing and authorized-client controls are unavailable, even though the backend is reachable
through its Tailscale Serve HTTPS URL.
The apparent cause is that EnvironmentAuthPolicy.ts determines remote reachability solely from the
bind host:
const isRemoteReachable = isWildcardHost(config.host) || !isLoopbackHost(config.host);
For a headless browser, ConnectionsSettings.tsx then relies on that policy:
const isLocalBackendNetworkAccessible = currentAuthPolicy === "remote-reachable";
Unlike the desktop application, the headless browser has no desktopBridge providing Tailscale endpoint
discovery.
It may be appropriate for tailscaleServeEnabled to affect the server auth policy:
const isRemoteReachable =
config.tailscaleServeEnabled ||
isWildcardHost(config.host) ||
!isLoopbackHost(config.host);
Related but distinct: #2834 concerns advertising the Tailscale HTTPS URL in headless pairing output.
Impact
Major degradation or frequent failure
Version or commit
0.0.29-nightly.20260724.893 / ece05087a70e94efcd57441337fa1249559362b
Environment
NixOS, Chromium-based browser, Tailscale 1.98.5, Node.js 24.15.0, npm 11.12.1
Logs or stack traces
INFO: Listening on http://127.0.0.1:3773
INFO: Tailscale Serve configured
{ localPort: 3773, servePort: 443 }
T3 Code server is ready.
Connection string: http://localhost:3773
Screenshots, recordings, or supporting files
No response
Workaround
Starting T3 with --host 0.0.0.0 causes it to use the remote-reachable auth policy and enables the
pairing controls:
npx t3@nightly serve \
--host 0.0.0.0 \
--tailscale-serve \
--tailscale-serve-port 443
However, this unnecessarily binds port 3773 to every network interface and requires the host firewall to
prevent direct access. The preferred behavior is to retain the loopback bind and expose the backend only
through Tailscale Serve.
- Dominant language
- TypeScript
- Stars
- 23.3k
- Forks
- 6k
- Avg merge
- 10h 57m
- Merged PRs (30d)
- 365
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
More from pingdotgg/t3code
-
bug via-triage
Difficulty 2/5 1-3 hours Newbie friendliness 74/100
-
accepted bug via-triage
Difficulty 2/5 1-3 hours Newbie friendliness 85/100
-
accepted bug via-triage
Difficulty 2/5 1-3 hours Newbie friendliness 84/100
-
accepted bug via-triage
Difficulty 2/5 1-3 hours Newbie friendliness 88/100
-
Difficulty 2/5 1-3 hours Newbie friendliness 72/100
All issues in pingdotgg/t3code
Similar issues
-
Difficulty 2/5 1-3 hours Newbie friendliness 84/100
Eynzof/Hermes-CN-Desktop#610 ·
-
bug clawsweeper:linked-pr-open clawsweeper:needs-live-repro clawsweeper:no-new-fix-pr impact:message-loss issue-rating: 🐚 platinum hermit P2 regression
Difficulty 2/5 1-3 hours Newbie friendliness 78/100
-
enhancement
Difficulty 2/5 1-3 hours Newbie friendliness 68/100
-
calcite-components needs triage refactor
Difficulty 2/5 1-3 hours Newbie friendliness 75/100
Esri/calcite-design-system#15203 ·
-
Difficulty 2/5 1-3 hours Newbie friendliness 90/100
danielmiessler/LifeOS#2218 ·