This guide explains how to spawn multiple instances of tailscaled
on a single system using a systemd.service(5)
template and, optionally, customized configurations.
By setting "netfilterMode": "off"
in all configurations (or by manually configuring them using tailscale up --netfilter-mode off
), you can connect to multiple Tailnets simultaneously without resorting to SOCKS proxy–based userspace networking, while preserving functionalities like Magic DNS integration with systemd-resolved
(i.e. you can simutaneously have direct access to other machines in BOTH tailnets via their hostnames).
DISCLAIMER: This method completely disables Tailscale’s automatic (
iptables
/nftables
)netfilter
firewall rule creation and management. As firewall rules from an earlier tailscaled instance would be wiped out by a new one, potentially locking you out.
Thus, features that rely on kernel firewall integration (such as Exit-Node functionality, which depends on NAT masquerading, and MSS clamping to PMTU, which is implemented by a custom firewall rule mangling the TCP options in the packet header) may not work correctly. Additionally, IP conflicts can occur, potentially disrupting in-kernel IP routing. So use this method with caution.
Note: This hack also completely breaks Tailscale IPv6 address handling, as the table based routes for IPv6 are added as whole CIDR blocks rather than per host (as in the IPv4 scenario). You can validate this by using following commands
# Linux rule based routing
sudo ip rule show
sudo ip -6 rule show
# Tailscale only use route table 52
sudo ip route show table 52
sudo ip -6 route show table 52
-
A Linux system using systemd.
-
A working installation of Tailscale.
-
Basic knowledge of
systemd
unit files and configuration editing.
Create a template unit file that will be used to launch multiple tailscaled instances. Save the following content as /etc/systemd/system/[email protected]
:
# Systemd Template Service Unit for tailscaled
# should be placed at /etc/systemd/system/[email protected]
[Unit]
Description=Tailscale node agent instance #%i
Documentation=https://tailscale.com/kb/
Wants=network-pre.target
After=network-pre.target NetworkManager.service systemd-resolved.service
[Service]
EnvironmentFile=/etc/tailscale.d/tailscale%i.env
ExecStart=/usr/sbin/tailscaled --config=/etc/tailscale.d/tailscale%i.json --state=/var/lib/tailscale%i/tailscaled.state --socket=/run/tailscale%i/tailscaled.sock --tun tailscale%i --port=${PORT} $FLAGS
ExecStopPost=/usr/sbin/tailscaled --cleanup --config=/etc/tailscale.d/tailscale%i.json --state=/var/lib/tailscale%i/tailscaled.state --socket=/run/tailscale%i/tailscaled.sock --tun tailscale%i
Restart=on-failure
RuntimeDirectory=tailscale%i
RuntimeDirectoryMode=0755
StateDirectory=tailscale%i
StateDirectoryMode=0700
CacheDirectory=tailscale%i
CacheDirectoryMode=0750
Type=notify
[Install]
WantedBy=multi-user.target
This template uses %i
as an instance identifier, allowing you to run multiple, independent tailscaled instances.
It also utilizes the optional Declarative Configuration (as the --config=/etc/tailscale.d/tailscale%i.json
in ExecStart
and ExecStop
properties, find details in following sections) for easier configration process. But if you find this confusing or preventing your specific use case, just remove the configuration flags and config the instance manually with tailscale
after starting the new instance.
The declarative configuration for tailscaled
is currently in its alpha0
stage and may change over time. Below is an extract of the configuration template (from ConfigVAlpha):
{
"version": "alpha0",
"locked": false,
"serverURL": "https://controlplane.tailscale.com",
"authKey": null,
"enabled": true,
"operatorUser": null,
"hostname": null,
"acceptDNS": true,
"acceptRoutes": null,
"allowLANWhileUsingExitNode": false,
"advertiseRoutes": [],
"disableSNAT": false,
"netfilterMode": "off",
"postureChecking": false,
"runSSHServer": null,
"runWebClient": null,
"shieldsUp": false,
"autoUpdate": {
"check": true,
"apply": false
},
"serveConfigTemp": null
}
Ensure that "netfilterMode": "off"
is set in every instance configuration if you want to disable firewall rule management for simultaneous multiple instance spawning.
Follow these steps to create and start a new tailscaled
instance:
-
Create the systemd Service Template: Save the unit file provided above as
/etc/systemd/system/[email protected]
. -
Prepare the Configuration Directory: Create a dedicated directory for instance configurations:
sudo mkdir -p /etc/tailscale.d
-
Add Instance Configuration: Create a declaritive configuration file for the new instance at
/etc/tailscale.d/tailscale1.json
and modify it as needed. -
Set Up Environment Variables: Copy the default environment variable file from
/etc/default/tailscaled
to/etc/tailscale.d/tailscale1.env
, then adjust its content (at a minimum, change the listening port):
sudo cp /etc/default/tailscaled /etc/tailscale.d/tailscale1.env
sudo nano /etc/tailscale.d/tailscale1.env
- Enable and Start the Instance: Enable and start the new instance with the following command:
sudo systemctl enable --now [email protected]
- (Optional) Migrate the State Directory:
If you need to migrate an existing state, modify the state storages
/var/lib/tailscale/tailscaled.state
and/var/lib/tailscale1/tailscaled.state
(with all the involved instances stopped), then restart the service:
sudo systemctl stop tailscaled.service [email protected]
sudo nano /var/lib/tailscale/tailscaled.state
sudo nano /var/lib/tailscale1/tailscaled.state
sudo systemctl start tailscaled.service [email protected]
# Be careful: these state file contains sensitive values like node private key, so don't disclose their contents!
Once the new instance is running, you can manage it with the tailscale command by specifying the corresponding socket:
tailscale --socket /run/tailscale1/tailscaled.sock <command>
This tutorial demonstrated how to run multiple tailscaled instances simultaneously by using a systemd service template and custom JSON configurations with "netfilterMode": "off"
. This setup allows you to connect to multiple Tailnets concurrently while keeping Magic DNS functionality intact via systemd-resolved. However, keep in mind the limitations regarding firewall management and IP routing.
Happy networking!
Feel free to contribute improvements or raise issues if you encounter any problems with this setup.
This guide is originally written by myself, then polished by GPT, and checked by me again.