tailmix

Connect to multiple tailnets at once

tailmix replaces your Tailscale client to let you connect to multiple tailnets simultaneously.

curl -fsSL https://tailmix.net/install.sh | sudo sh

Command line · macOS · Linux with systemd · Open source
Disconnect the Tailscale client before installing.

Three tailnets, work, home, and lab, connected at once to a terminal on your machine where tailmix status shows all three running. work home lab your machine $ tailmix statuswork runninghome runninglab running

No switching

One embedded Tailscale node per profile. No signing in and out, no switching.

Routes you choose

Bind subnets to a profile and pick one exit node across all of them.

DNS that follows

MagicDNS from every profile, plus custom suffixes and search domains.

Up in a minute

Install, run tailmix ts login --shields-up, and open the login link it prints. That tailnet gets a profile named default.

Full guide →
# install
curl -fsSL https://tailmix.net/install.sh | sudo sh

# log in to your first tailnet
sudo tailmix ts login --shields-up

# check
tailmix status

Add another tailnet

Give it a profile name and log in. With more than one profile, choose one with -p.

sudo tailmix profiles add work
sudo tailmix ts -p work login --shields-up

Use short names

Add a tailnet’s MagicDNS suffix as a search domain so ssh mybox works. list shows each tailnet’s suffix.

tailmix dns search list
sudo tailmix dns search add tailnet.ts.net

How traffic picks a tailnet

For each destination, tailmix checks these in order and uses the first match.

  1. PeersEach node is reached through the tailnet it belongs to.
  2. Subnet routesThe most specific route you accepted wins.
  3. Exit nodeEverything else, if you picked one.
  4. Your networkOtherwise, traffic leaves normally.

Subnet routes

Nothing is accepted until you ask. Accept everything a tailnet advertises, or pin a single prefix to one tailnet. A pinned prefix beats accept-all, and if two tailnets advertise the same prefix, tailmix waits for you to pin one.

# see what each tailnet advertises
tailmix routes list --available

# accept all of work’s routes
sudo tailmix routes set -p work --accept-all=true

# send 10.20.0.0/16 through lab
sudo tailmix routes bind -p lab 10.20.0.0/16

Exit nodes

Pick one exit node from any tailnet. It carries your default traffic and answers DNS for names no other route covers. Peers and subnet routes keep using their own tailnets.

# list exit nodes across tailnets
tailmix exit-node list

# use home’s gateway for everything else
sudo tailmix exit-node set -p home gateway

# go back to your normal internet
sudo tailmix exit-node clear

How tailmix handles overlapping addresses

Two tailnets can hand out the same 100.x address. tailmix gives every node and Service its own local address and rewrites packets as they enter and leave each tailnet.

Your app sends from 192.168.58.1 to 192.168.58.8. tailmix rewrites it to come from 100.64.0.1, your address in the work tailnet, and go to 100.64.0.42, then hands it to its embedded tsnet node for work. A packet to 192.168.58.9 instead goes to 100.64.0.42 in the home tailnet, from 100.64.0.7, through the home tsnet node. Replies are rewritten back.

Address rewriting your machine work home your app192.168.58.1 tailmix tsnet100.64.0.1 tsnet100.64.0.7 printer100.64.0.42 nas100.64.0.42 src 192.168.58.1dst 192.168.58.8src 100.64.0.1dst 100.64.0.42src 100.64.0.42dst 100.64.0.1src 192.168.58.8dst 192.168.58.1src 192.168.58.1dst 192.168.58.9src 100.64.0.7dst 100.64.0.42src 100.64.0.42dst 100.64.0.7src 192.168.58.9dst 192.168.58.1 Address rewriting your machine work home your app192.168.58.1 tailmix tsnet100.64.0.1 tsnet100.64.0.7 printer100.64.0.42 nas100.64.0.42 src 192.168.58.1dst 192.168.58.8src 100.64.0.1dst 100.64.0.42src 100.64.0.42dst 100.64.0.1src 192.168.58.8dst 192.168.58.1src 192.168.58.1dst 192.168.58.9src 100.64.0.7dst 100.64.0.42src 100.64.0.42dst 100.64.0.7src 192.168.58.9dst 192.168.58.1
Tailmix IP vs Tailnet Addresses
TailnetNodeTailnet IPTailmix IP
workyou100.64.0.1192.168.58.1
workprinter100.64.0.42192.168.58.8
homeyou100.64.0.7192.168.58.1
homenas100.64.0.42192.168.58.9

Each node keeps its Tailnet IP inside its tailnet. On your host it gets a unique Tailmix IP, so overlapping addresses don't clash. You have one Tailmix IP, whichever tailnet you're talking to.

Life of a packet
StepFromTo
Your app sendsyour app192.168.58.1printer192.168.58.8
tailmix hands to workyour app100.64.0.1printer100.64.0.42
printer repliesprinter100.64.0.42your app100.64.0.1
Your app receivesprinter192.168.58.8your app192.168.58.1

192.168.58.1 is your host’s local address. Its own addresses in the tailnets are 100.64.0.1 (work) and 100.64.0.7 (home). Addresses are examples. IPv6 works the same way, using fd6d:6e65:7400::/56.

FAQ

Is tailmix a client or a server?

A client. It runs on your Mac or Linux machine and signs in to your tailnets like the Tailscale client does. There’s nothing to host.

Does it replace the Tailscale client?

Yes, on that machine. tailmix runs its own background service, tailmixd, which runs one built-in Tailscale node per tailnet. Disconnect the Tailscale client first; the two compete for routes and DNS.

Is there a GUI?

No, it’s command line only. tailmix ts -p work … runs any Tailscale CLI command against one tailnet.

How do I enable Tailscale SSH on my Mac?

Run this on your Mac for the profile you want to accept SSH connections through. That tailnet’s network and SSH policies control who can log in.

sudo tailmix ts -p work set --ssh --shields-up=false

Our quick start enables shields-up. Turning it off allows inbound connections on that profile, not just SSH, subject to the tailnet’s policy.

How do ACLs work?

Each tailnet’s policy applies exactly as it would to a regular Tailscale client. Each profile is its own device in its tailnet, and Tailmix IPs are rewritten before packets leave, so policy only sees tailnet IPs and identities. tailmix never forwards traffic from one tailnet into another.

Why enable --shields-up?

Depending on a tailnet’s policy, its devices may be able to connect to services on your machine, like SSH or a dev server. With several tailnets, that can include tailnets other people manage. Shields-up blocks those incoming connections for one tailnet. Your own outbound connections to other tailnets still work as per tailnet policy.

Do I need to change anything in my tailnets?

No. Each profile joins its tailnet as a normal device, so ACLs, device approval, and admin settings work as usual.

How does it update?

Installs from install.sh check for new releases daily, verify checksums, and restart the service. tailmix update status shows where it stands.

Is it made by Tailscale?

No. tailmix is an independent open-source project, not affiliated with or endorsed by Tailscale Inc.