Skip to content

[Bug]: Settings says "Only this machine can connect" for a t3 serve --tailscale-serve server that remote devices reach over Tailscale HTTPS #35521

Closed

Description

@coygeek

Before submitting

  • I searched existing issues and did not find a duplicate.
  • I included enough detail to reproduce or investigate the problem.

Area

apps/web

Steps to reproduce

  1. Scratch test run against the server's classifier, placed next to apps/server/src/auth/EnvironmentAuthPolicy.ts and run with node_modules/.bin/vp test run --silent=false apps/server/src/auth/<scratch>.test.ts:
import { describe, expect, it } from "vite-plus/test";
import { resolveServerAuthPolicy } from "./EnvironmentAuthPolicy.ts";

describe("tailscale serve auth policy", () => {
  it("t3 serve --tailscale-serve (no --host, no --lan) is classified loopback-browser", () => {
    const policy = resolveServerAuthPolicy({ mode: "web", host: undefined });
    console.log(`policy for mode=web host=undefined: ${policy}`);
    expect(policy).toBe("loopback-browser");
  });
});
  1. Reported path, not run here (no Tailscale on the test machine): on a tailnet with HTTPS certificates enabled, run t3 serve --tailscale-serve, pair a second device through https://<machine>.<tailnet>.ts.net/, open Settings → Sharing & access in that device's browser, and read the Network access row.

The classifier result is deterministic for this configuration; the row text follows from the source lines cited above for every browser session with the maintain permission on such a server.

Expected behavior

docs/user/remote-access.md:169-186 documents t3 serve --tailscale-serve as the way to give a command-line server Tailscale HTTPS access, with pairing links at https://machine.tailnet.ts.net/. For a server published that way, the Network access row should not say that only this machine can connect, should not show remote access as off, and should not advise restarting on a non-loopback host to enable remote pairing; it should reflect that the server is reachable from the tailnet through Tailscale HTTPS. The open PR #10083 states the same expectation for this row.

Actual behavior

Source-only for the rendered row; the server classification it depends on was reproduced by a run. A command-line server started as documented for Tailscale HTTPS, t3 serve --tailscale-serve, keeps its listener on loopback and reaches the tailnet through Tailscale Serve's https://<machine>.<tailnet>.ts.net proxy to http://127.0.0.1:<port>. The server classifies that configuration as auth policy loopback-browser, because resolveServerAuthPolicy looks only at the bind host (apps/server/src/auth/EnvironmentAuthPolicy.ts:22-26) and the default host for t3 serve without --host or --lan is undefined, which means 127.0.0.1 (apps/server/src/cli/config.ts:441-443). In a browser client (no desktop bridge) with a session that has the environment maintain permission, Settings → Sharing & access renders renderDisabledNetworkAccessRow for that server (apps/web/src/components/settings/ConnectionsSettings.tsx:1225-1233). For policy loopback-browser that row says "Only this machine can connect. Restart with a non-loopback host for remote pairing." and shows the Network access switch off (apps/web/src/components/settings/ConnectionsSettings.tsx:1095-1115, with isLocalBackendNetworkAccessible false at :440-442). The user sees this while reading the page from another device over the Tailscale HTTPS URL, so the row contradicts the connection they are using, and its advice to restart on a non-loopback host would expose the plain-HTTP listener on every interface even though Tailscale HTTPS pairing already works.

Impact and scope: Impact: P3 - the row shows the wrong state and misleading advice; pairing and client management keep working because they are gated on session permissions, not this row.

Affects browser clients of command-line servers started with --tailscale-serve and without --host or --lan. Following the row's advice (restarting with --host 0.0.0.0 or --lan) is unnecessary and widens the plain-HTTP listener to every interface. Desktop clients are not affected, since they render the desktop Network access and Tailscale HTTPS rows instead. Workaround: ignore the row; Tailscale HTTPS pairing works as is.

Impact

Cosmetic issue

Version or commit

main @ 86ff9d0

Environment

Scratch test run with the repository's Vite+ test runner (Vitest 5.0.5) on Linux x64. The row itself is platform-independent web UI.

Logs or stack traces

Scratch test output (run as above):

stdout | src/auth/zzrepro-ui-authpolicy.test.ts > zzrepro ui auth policy > t3 serve --tailscale-serve (no --host, no --lan) is classified loopback-browser
policy for mode=web host=undefined: loopback-browser
 Test Files  1 passed (1)
      Tests  1 passed (1)

Source references at the pinned commit: apps/web/src/components/settings/ConnectionsSettings.tsx:1104 holds the row text "Only this machine can connect. Restart with a non-loopback host for remote pairing."; apps/server/src/auth/EnvironmentAuthPolicy.ts:26 returns loopback-browser for a non-desktop server on a loopback host; apps/server/src/cli/config.ts:441-443 leaves the host undefined for t3 serve without --host or --lan; packages/tailscale/src/tailscale.ts:452-453 runs tailscale serve --bg --https=<port> http://127.0.0.1:<localPort>, so Serve keeps the loopback listener reachable from the tailnet.

Screenshots, recordings, or supporting files

No response

Workaround

See Impact and scope under Actual behavior.

Additional details

  • Interface: UI: Settings → Sharing & access, Network access row (browser client)
  • Earliest failure stage: Output or presentation

Additional context

The server descriptor carries no Tailscale Serve signal today (ServerAuthDescriptor and ServerConfig in packages/contracts/src have no Serve field), so the web row has no input that distinguishes this server from a truly local-only one. The fix may therefore cross apps/server and apps/web, as PR #10083 does on the server side.

References

#4462 (closed by its reporter as no longer seen; it reported the same loopback classification hiding pairing controls, which are now gated on session permissions, so this report covers only the Network access row that still shows the wrong state and advice); open PR #10083 changes the server's auth policy for Serve and awaits maintainer approval, with no open issue tracking the symptom; #25348 (open, CLI prints a localhost pairing URL for the same server, a different surface); #16238 (open, Serve setup failures are silent, a different failure).


Found by reading T3 Code's Tailscale integration against the Tailscale source (tailscale/tailscale@071bf947, v1.105.0); written up with AI assistance (Claude Code).

Activity

  1. added a commit that references this issue on Nov 12, 2026
    bf801eb
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions