Configuration
Everything TailMux does is driven by a single YAML file. Profiles own suffixes; the router turns those suffixes into routes.
View as MarkdownLocation#
TailMux loads its config from ~/.config/tailmux/config.yaml. Generate a starter file with tailmux init and validate any edits before starting:
$tailmux init$tailmux config validateUse examples/tailmux.example.yaml as the canonical reference. A trimmed version:
1version: 12 3router:4 http_proxy: "127.0.0.1:43100"5 socks5_proxy: "127.0.0.1:43101"6 pac_listen: "127.0.0.1:43180"7 profile_http_proxy_base: 431108 profile_socks5_proxy_base: 431119 profile_udp_port_base: 0 # 0 lets tsnet choose UDP ports10 profile_hostname_base: "tailmux"11 12profiles:13 work:14 display_name: "Work"15 backend: "tsnet"16 auth_key_env: "" # e.g. TAILMUX_WORK_AUTHKEY17 accept_routes: false18 suffixes:19 - ".acme-corp.ts.net"20 - ".corp.example.com"21 match_root: true22 ip_routes: []23 24 personal:25 display_name: "Home lab"26 backend: "tsnet"27 suffixes:28 - ".home-lab.ts.net"29 - ".home.example.com"30 match_root: true31 32security:33 require_loopback_listeners: true34 allow_cross_profile_fallback: false35 allow_ip_literals: false36 allow_unknown_tsnet: falseRouter#
The router block defines the single public-facing endpoints and the per-profile bases:
http_proxy— the one TailMux HTTP/CONNECT proxy endpoint clients talk to.socks5_proxy— SOCKS5 endpoint for domain CONNECT dispatch.pac_listen— local endpoint serving/proxy.pac.profile_*_base— bases used to derive each profile's internal runtime ports and hostname.profile_udp_port_base— set0to let tsnet choose UDP ports, or a fixed base for more stable peer-to-peer path discovery.
Profiles#
Each entry under profiles is one tailnet identity. Key fields:
backend—tsnet(recommended) ortailscaled.display_name— human label shown in the GUI and menu bar.auth_key_env— name of an environment variable holding an auth key for non-interactive login.accept_routes— settrueonly for profile-owned app connectors or subnet routes.control_url— optional custom control server.ip_routes— advanced: explicit profile-owned IP/CIDR destinations for raw TCP tools. Keep empty unless the range cannot overlap any other profile.
Suffixes & ownership#
suffixes is the heart of routing: each profile owns a list of DNS suffixes. The router matches an incoming hostname against these lists and dispatches to the owning profile. With match_root: true, the bare apex of a suffix is also owned.
Backends#
tsnet (recommended) embeds a Tailscale node inside TailMux. TailMux starts one embedded server per profile, each with its own state directory, hostname, and node key. No external process, no second native VPN route.
tailscaled (compatibility) runs one external userspace tailscaled process per profile and forwards through profile-specific listeners. Keep it for comparison and low-level debugging — it is not the primary path.
Security block#
The security block makes the hard isolation constraints explicit and enforceable:
require_loopback_listeners: true— bind all proxy/control ports to loopback.allow_cross_profile_fallback: false— never retry on a different tailnet.allow_ip_literals: false— deny raw-IP destinations by default.allow_unknown_tsnet: false— deny unclassified.ts.nethosts.