Documentation

Route browser traffic by tailnet (PAC)

Send only your owned tailnet suffixes through TailMux and leave all other web traffic DIRECT, decided by a PAC file — so Safari can reach a second tailnet by hostname without a system-wide VPN.

View as Markdown

The idea#

You want a browser dashboard on a tailnet host — a Grafana on grafana.home-lab.ts.net, an internal app on app.corp.example.com — without routing your entire browser through Tailscale and without switching the official client's account. The trick is a PAC file (proxy auto-configuration): the browser asks it, per request, whether a hostname should go through a proxy or straight out.

TailMux serves a PAC that sends only your configured profile-owned suffixes through the TailMux router and leaves everything else as DIRECT. Public browsing is untouched; only names you own get proxied, and each is dialed through the one profile that owns its suffix — there is no cross-profile fallback.

The PAC URL#

Bring TailMux up — this starts the router and the PAC listener together — then authenticate the profiles whose hosts you want to reach in the browser:

zsh — up
$tailmux up$tailmux profile login personal

You should see the two loopback listeners come up:

  • router: 127.0.0.1:43100
  • PAC: 127.0.0.1:43180

The PAC is served on the loopback PAC listener at this URL:

PAC URL
1http://127.0.0.1:43180/proxy.pac

Automatic setup#

With the TailMux menu-bar app there is nothing to paste: on launch it points your active macOS network service at the PAC URL above and turns automatic proxy configuration on, then clears it again when you quit. Safari — and any browser that honors the system proxy, like Chromium-based ones — picks it up automatically. You can disable this under Settings → “Configure system PAC automatically”, and TailMux only ever touches a service whose PAC it set, so it won't clobber a proxy you configured yourself.

For a CLI-only setup (no app), point the active network service at the PAC URL yourself: System Settings → Network → your active service (Wi-Fi or Ethernet) → Details → Proxies → Automatic Proxy Configuration, and paste the URL above.

Either way the PAC sends only configured profile-owned suffixes to TailMux while public web traffic stays DIRECT — see getting started for the same setup in context.

How it behaves#

Once the PAC is set, routing happens silently on every request, keyed on the hostname suffix while the original hostname is still intact:

  • A request to a profile-owned suffix (e.g. grafana.home-lab.ts.net) is sent to the TailMux router and dialed through the owning tailnet.
  • Every other request — example.com, your bank, a search engine — returns DIRECT and never touches TailMux. Public browsing is untouched.
  • A name owned by one profile never falls back to another, and routing stays loopback-only. The official Tailscale account and session are never touched.

This pairs naturally with a multi-tailnet setup: see work & personal tailnet for declaring the profiles and suffixes, and configuration for the full config.yaml reference.

Verify#

First confirm a hostname is classified to the profile you expect, then open the host in Safari:

zsh — test
$tailmux test grafana.home-lab.ts.net$tailmux status

If the page does not load, run a path diagnostic for a full report — which profile owns the host, whether the peer is visible, direct vs. DERP path, and HTTP timing:

zsh — diag
$tailmux diag path \$  http://grafana.home-lab.ts.net:3000/ \$  --netcheck
An in-app or embedded browser — Electron, a desktop app's built-in webview, and similar — may resolve traffic through the active environment directly and bypass the system proxy. That is not proof Safari is configured. Verify Safari specifically through the PAC path before concluding routing works.

New to TailMux? Start with getting started, or see pricing.