Documentation

Getting started

Keep more than one Tailscale tailnet reachable from a single Mac, and route every request by hostname suffix — with no cross-profile fallback.

View as Markdown

What is TailMux#

TailMux is a developer tool for keeping multiple isolated Tailscale tailnets reachable at the same time and routing traffic by hostname suffix. A typical setup runs a work tailnet for company infrastructure alongside a personal tailnet for private servers — with browser, API, SSH, and diagnostic access to both, without switching the official Tailscale client account. On macOS it's a menu bar app (with the CLI included); on Linux it's a CLI.

The core promise is strict isolation:

  • A hostname owned by one profile never falls back to another profile.
  • The official Tailscale GUI account and session are never touched or mutated.
  • No second native macOS VPN route — routing stays at the proxy layer, loopback-only.
TailMux is not affiliated with, endorsed by, or sponsored by Tailscale Inc. It is an independent CQ Fabrication developer tool.

Before configuring a workflow, read the limitations and routing model. TailMux provides application-layer paths for supported clients; it does not create a second native system-wide VPN interface.

Mental model#

Each tailnet is a profile: an embedded userspace Tailscale node with its own identity and state. Each profile owns hostname suffixes (e.g. .home-lab.ts.net). The hostname is the routing key — the decision happens while the original hostname is still intact, before it can collapse into an ambiguous IP address.

routing path
1client keeps hostname2        |3        |  PAC / HTTP_PROXY / tailmux connect / tunnel4        v5TailMux router  127.0.0.1:431006        |7        |  hostname suffix match8        v9profile-owned embedded node  →  selected tailnet

A request that has already become a raw IP is denied by default, because profile ownership is no longer obvious. Every suffix belongs to exactly one profile — overlaps are rejected — which is what makes “no cross-profile fallback” a guarantee rather than a hope.

Prerequisites#

  • macOS (menu bar app + CLI) or Linux (CLI).
  • At least one tailnet you can authenticate against, with its DNS suffix (e.g. .home-lab.ts.net).
  • A TailMux license — see pricing.

Quick start (macOS app)#

No YAML required.

  • Install the app from the download page and launch it. The TailMux icon appears in the menu bar and the routing service starts.
  • Add a profile per tailnet: menu bar → Open Profiles. Give each profile its tailnet's suffixes — e.g. a work profile owning .work.ts.net and a personal profile owning .home-lab.ts.net. Save, and restart the router when prompted (routing changes apply on restart).
  • Log each profile in. Each login opens that tailnet's standard Tailscale approval page. Both profiles are then live at the same time — there is nothing to switch.
  • Browse. The app points the system proxy at its PAC automatically, so Safari (and anything honoring the system proxy) already reaches grafana.home-lab.ts.net while public browsing stays direct.

From here: expose a database or RDP host on a fixed local port under Tunnels (guide), check any hostname under Diagnostics, and install the bundled CLI from Settings → Command Line if you want the terminal too. A full tour lives at the app.

Quick start (CLI / Linux)#

Install from the download page or with Homebrew, then generate a starter config:

zsh — install
$brew install cq-fabrication/tap/tailmux   # or download a binary$tailmux init$tailmux config validate

Edit ~/.config/tailmux/config.yaml to replace the example suffixes with your real tailnet DNS suffixes (full reference: configuration), then start TailMux in the foreground:

zsh — tailmux
$tailmux up

Two loopback listeners come up — router 127.0.0.1:43100 and PAC 127.0.0.1:43180. Authenticate each profile against its tailnet:

zsh — tailmux
$tailmux profile login personal

For browser routing without the app, point your system's automatic proxy configuration at http://127.0.0.1:43180/proxy.pac — see browser routing.

Verify routing#

Works the same from either path. In the app, open Diagnostics (or the menu bar's Diagnose button), enter a hostname, and read off the owning profile plus DNS, ping, and HTTP probe results.

From the command line:

zsh — tailmux
$tailmux test nas.home-lab.ts.net          # which profile owns it$tailmux connect nas.home-lab.ts.net 8080  # raw reachability

For a full report — owning profile, peer visibility, direct vs. DERP path, HTTP timing:

zsh — tailmux
$tailmux diag path \$  http://nas.home-lab.ts.net:8080/dashboard \$  --netcheck

Next steps#

  • The app — the menu bar and window, section by section.
  • Tunnels — databases, RDP, SMB on fixed local ports.
  • SSHtailmux ssh <host> for interactive shells.
  • Configuration — the full config.yaml reference.
  • Commands — the complete CLI surface.
  • Limitations and routing model — supported access paths, raw IP behavior, DNS boundaries, and isolation guarantees.