# Tailscale HTTPS shows off and cannot be disabled in Settings when local DNS fails · Issue \#14746 · pingdotgg/t3code

[View on GitCafe](https://git.cafe/pingdotgg/t3code/issues/14746)

Repository: [pingdotgg/t3code](https://git.cafe/pingdotgg/t3code)

Visibility: public

State: backlog

Priority: 0

## Description

[Discussion and activity](https://git.cafe/pingdotgg/t3code/issues/14746)

---

### What happened

Settings → Connections shows Tailscale HTTPS as off, although it is enabled and Tailscale Serve is exposing the backend on port 443. Turning the switch on and confirming Setup does nothing, and Settings offers no way to turn it off. This happens when the machine can't resolve its own MagicDNS name (`tailscale set --accept-dns=false`).

### Diagnosis

The switch shows the result of a reachability probe instead of the saved setting, and the probe resolves the MagicDNS name through the OS resolver. Line numbers are from main @ 54084ae1; these files haven't changed since 99e08526.

- `apps/desktop/src/backend/tailscaleEndpointProvider.ts:82,93`: the endpoint is `available` only if Serve is enabled and the probe passes.
- `packages/tailscale/src/tailscale.ts:365-381`: the probe GETs `https://<MagicDNS>/.well-known/t3/environment` with the desktop Undici client (`apps/desktop/src/main.ts:216`), so it goes through the OS resolver. A failure or timeout returns `false`, and the endpoint becomes `unavailable`.
- `apps/web/src/components/settings/ConnectionsSettings.tsx:3181-3183`: `checked={tailscaleHttpsEndpoint.status === "available"}`.
- `apps/desktop/src/settings/DesktopAppSettings.ts:326-341`: re-enabling with the same port is a no-op, so `requiresRelaunch: false` (`apps/desktop/src/backend/DesktopServerExposure.ts:525-528`).
- Disable is offered only on the switch's checked → unchecked path. The endpoint-row Disable button also requires `available` (`ConnectionsSettings.tsx:1311-1313`), and the rendered endpoint list leaves Tailscale HTTPS out anyway (`:2568`, `:2838`).
- Unavailable endpoints are left out of pairing options (`ConnectionsSettings.tsx:641`), and Authorized clients is shown only for `network-accessible || HTTPS available` (`:3388`). Existing client authorizations are not revoked.
- Graceful backend shutdown tries to remove the mapping (`apps/server/src/server.ts:683`, release at `:717`), but the saved setting stays `true`, so the next launch configures it again.

Suggested fix:
1. Bind the switch to `tailscaleServeEnabled`. Keep Disable reachable when discovery or the probe fails, and show probe health as a separate note. Keep Authorized clients visible when Network access or the saved Serve setting is on. Keep endpoint health checks for pairing: a saved `true` means configured intent, so it should not mark the endpoint `available` by itself.
2. Optional: probe a parsed Tailscale IP (`tailnetIpv4Addresses` is parsed but unused) while keeping the MagicDNS name for SNI, Host and certificate checks, and validate the returned descriptor.
3. Regression test: saved enabled + failed or missing endpoint → Disable and client management stay reachable.

### Steps to reproduce

1. On Linux, join a tailnet with MagicDNS and HTTPS certificates enabled. Run `tailscale set --accept-dns=false` and check that the system resolver can't resolve this machine's `<host>.<tailnet>.ts.net` name.
2. In the desktop app, with Network access on, enable Tailscale HTTPS on port 443. After the relaunch, check that `tailscale serve status` proxies HTTPS to `http://127.0.0.1:3773`.
3. Reopen Settings → Connections. Tailscale HTTPS shows off.
4. Turn it on and confirm Setup. The dialog closes without a relaunch and the switch stays off.
5. Optional: turn Network access off while Tailscale HTTPS stays configured. Authorized clients disappears.

Expected: the switch is on with the MagicDNS URL, and turning it off removes the route (`docs/user/remote-access.md`: "Turn it off there to remove that route.").

### Version

0.0.45-nightly.20261002.2561

### Environment

Arch Linux (kernel 7.1), desktop app, Tailscale 1.98.8 with MagicDNS on tailnet-wide and `accept-dns=false`, Node v24.16.0 for the probe check

### Evidence

```shell
# tailscale serve status --json (host redacted)
{"TCP":{"443":{"HTTPS":true}},"Web":{"<host>.<tailnet>.ts.net:443":{"Handlers":{"/":{"Proxy":"http://127.0.0.1:3773"}}}}}

# desktop-settings.json (window bounds omitted)
"tailscaleServeEnabled": true

# tailscale dns status
Tailscale DNS: disabled.
MagicDNS: enabled tailnet-wide

# resolvectl query <host>.<tailnet>.ts.net
resolve call failed: '<host>.<tailnet>.ts.net' does not have any RR of the requested type

# dig +short @100.100.100.100 <host>.<tailnet>.ts.net
100.x.y.z

# curl https://<host>.<tailnet>.ts.net/.well-known/t3/environment
curl: (6) Could not resolve host: <host>.<tailnet>.ts.net

# same request with --resolve <host>.<tailnet>.ts.net:443:100.x.y.z
http_code=200

# Node 24: undici fetch (same client stack as the desktop probe) and dns.lookup
TypeError ENOTFOUND
dns.lookup: ENOTFOUND

# desktop.trace.ndjson: the probe span reports Success because the failure is recovered to false
{"name":"resolveTailscaleMagicDnsAdvertisedEndpoint","durationMs":432.4,"exit":{"_tag":"Success"}}
```

### Related issues

No open duplicate. #4919 and #4698 proposed binding the switch to the saved setting (both closed unmerged); this adds a DNS-failure repro. Related: #4028, #2830.

### Fix applied or workaround

On this machine, setting `"tailscaleServeEnabled": false` in `desktop-settings.json` and running `tailscale serve --https=443 off` removed the route, and the setting held after restart. Quit T3 Code completely before editing the file, because the running app keeps settings in memory and rewrites the whole file. `tailscale serve --https=443 off` removes every web handler on port 443, not only T3's.

Untested alternative: temporarily enable Tailscale DNS. If the name resolves and the probe passes, turn HTTPS off in Settings, then restore the DNS setting.

### Filed by

Claude Code (claude-opus-5-5), following `.github/triage/PLAYBOOK.md` but not launched through `t3 triage`. Findings cross-checked with Codex CLI (gpt-6.1-sol).

