TAILSCALE MESH VPN ARCHITECTURE Laptop 100.64.0.1 WireGuard Connected Linux Server 100.64.0.2 Subnet Router Connected Phone 100.64.0.3 WireGuard Connected Tailscale Coordination Key Exchange Only Direct peer-to-peer WireGuard tunnels — no central traffic relay

Setting up a secure VPN has traditionally required deep networking expertise, port forwarding, key management, and constant maintenance. Tailscale changes that entirely. Built on top of WireGuard, Tailscale creates a mesh VPN — called a tailnet — where every device connects directly to every other device through encrypted peer-to-peer tunnels. There is no central server bottleneck, no ports to open, and no certificates to manage. You install the client, authenticate, and your devices can talk to each other securely regardless of whether they are behind NAT, firewalls, or on different continents.

This guide covers everything from installation across Linux, Windows, and macOS to advanced features like subnet routing, exit nodes, Access Control Lists (ACLs), and MagicDNS.

What Is Tailscale?

Tailscale is a zero-configuration mesh VPN that uses WireGuard under the hood. Instead of setting up a central VPN server that all traffic flows through, Tailscale establishes direct, encrypted WireGuard tunnels between your devices. The Tailscale coordination server only handles key exchange and device authentication — it never sees your actual traffic.

Key characteristics of Tailscale:

  • Mesh topology: Every device connects directly to every other device. Traffic between your laptop and your server does not route through a central point.
  • WireGuard-based: Uses the WireGuard protocol for encryption, providing modern cryptography (ChaCha20, Curve25519) with minimal overhead.
  • NAT traversal: Tailscale automatically punches through firewalls and NAT using STUN, DERP relay servers, and other techniques. No port forwarding needed.
  • Identity-based: Authentication is tied to your existing identity provider (Google, Microsoft, GitHub), not to manually managed certificates or pre-shared keys.
  • 100.x.y.z addresses: Each device gets a stable Tailscale IP in the 100.64.0.0/10 range (CGNAT space) that does not change regardless of which physical network the device is on.

Tailscale vs Traditional VPNs

Understanding how Tailscale differs from traditional VPN setups helps you appreciate when and why to use it:

FeatureTailscaleTraditional VPN (OpenVPN/IPsec)Manual WireGuard
TopologyMesh (peer-to-peer)Hub-and-spoke (central server)Point-to-point or hub
ConfigurationZero-configComplex server + client setupManual key exchange
NAT traversalAutomaticRequires port forwardingRequires port forwarding
Key managementAutomatic via coordination serverManual PKI or pre-shared keysManual key pairs
IdentitySSO (Google, Microsoft, GitHub)Certificates or credentialsPre-shared keys
PerformanceDirect peer-to-peer, low latencyAll traffic through central serverDirect, but manual setup
ScalingAdd device in secondsReconfigure server for each clientEdit configs on all peers
Mobile supportNative apps (iOS, Android)Third-party clientsThird-party clients

When to choose Tailscale: When you want a VPN that connects all your devices with minimal effort, especially across different networks and NAT environments. It is ideal for remote access to home labs, connecting distributed teams, or creating a private overlay network across cloud instances.

When to stick with manual WireGuard: When you need full control over every aspect of the VPN, are operating in an air-gapped environment, or have compliance requirements that prohibit using a third-party coordination service.

Prerequisites

Before you begin, make sure you have:

  • A Tailscale account (free tier available at tailscale.com)
  • At least two devices you want to connect (Linux, Windows, macOS, iOS, or Android)
  • Root or sudo access on Linux servers
  • Administrator access on Windows (for installation)
  • Basic familiarity with the command line

Installing Tailscale on Linux

Tailscale provides official packages for all major Linux distributions. The recommended approach uses the official install script.

Ubuntu / Debian

# Add Tailscale's package signing key and repository
curl -fsSL https://tailscale.com/install.sh | sh

If you prefer to add the repository manually:

# Add the Tailscale GPG key
curl -fsSL https://pkgs.tailscale.com/stable/ubuntu/jammy.noarmor.gpg | sudo tee /usr/share/keyrings/tailscale-archive-keyring.gpg >/dev/null

# Add the Tailscale repository
curl -fsSL https://pkgs.tailscale.com/stable/ubuntu/jammy.tailscale-keyring.list | sudo tee /etc/apt/sources.list.d/tailscale.list

# Install Tailscale
sudo apt update
sudo apt install -y tailscale

Fedora / RHEL / CentOS

# Add the Tailscale repository
sudo dnf config-manager --add-repo https://pkgs.tailscale.com/stable/fedora/tailscale.repo

# Install Tailscale
sudo dnf install -y tailscale

# Enable and start the daemon
sudo systemctl enable --now tailscaled

Arch Linux

sudo pacman -S tailscale
sudo systemctl enable --now tailscaled

Verify the Installation

After installing on any distribution, verify that the Tailscale daemon is running:

# Check the tailscaled service status
sudo systemctl status tailscaled

# Verify the Tailscale CLI is available
tailscale version

You should see output similar to:

1.62.0
  tailscale commit: abcdef1234567890
  other commit: abcdef1234567890
  go version: go1.22.0

Installing on Windows and macOS

Windows

  1. Download the installer from tailscale.com/download/windows
  2. Run the .msi installer
  3. Tailscale appears in the system tray after installation
  4. Click the Tailscale icon and select Log in
  5. Authenticate with your identity provider in the browser

Alternatively, install via the command line with winget:

winget install Tailscale.Tailscale

macOS

Install via the Mac App Store or using Homebrew:

# Install via Homebrew
brew install --cask tailscale

Or download directly from tailscale.com/download/mac. After installation, open Tailscale from the Applications folder, and it will appear in the menu bar.

Docker

For containerized environments, Tailscale provides an official Docker image:

docker run -d \
  --name=tailscale \
  --hostname=my-container \
  --cap-add=NET_ADMIN \
  --cap-add=NET_RAW \
  -v /dev/net/tun:/dev/net/tun \
  -v tailscale-state:/var/lib/tailscale \
  -e TS_AUTHKEY=tskey-auth-xxxxxxxxxxxx \
  -e TS_STATE_DIR=/var/lib/tailscale \
  tailscale/tailscale:latest

Tip: Use a pre-authenticated auth key (TS_AUTHKEY) to avoid the manual login step in headless environments. Generate auth keys in the Tailscale admin console under Settings > Keys.

Connecting Devices to Your Tailnet

Once Tailscale is installed, connect each device to your tailnet:

Authenticate Your First Device

# Start Tailscale and authenticate
sudo tailscale up

This command prints a URL. Open it in your browser, sign in with your identity provider, and authorize the device. After authentication, the device joins your tailnet and receives a Tailscale IP address.

Check Your Connection Status

# View your Tailscale IP and connection status
tailscale status

Example output:

100.64.0.1   laptop           user@example.com  linux   -
100.64.0.2   server           user@example.com  linux   -
100.64.0.3   phone            user@example.com  iOS     -

Test Connectivity

Once two or more devices are connected, test connectivity:

# Ping another device by its Tailscale IP
tailscale ping 100.64.0.2

# Or by its MagicDNS name
tailscale ping server

The first tailscale ping may show traffic routed through a DERP relay. Subsequent pings typically establish a direct peer-to-peer connection:

pong from server (100.64.0.2) via DERP(nyc) in 45ms
pong from server (100.64.0.2) via 203.0.113.50:41641 in 12ms
pong from server (100.64.0.2) via 203.0.113.50:41641 in 11ms

Note: The DERP relay is used only when a direct connection cannot be established (rare). DERP stands for Designated Encrypted Relay for Packets, and it is a fallback, not the default path.

Subnet Routing

Subnet routing allows a Tailscale node to act as a gateway, giving other nodes on your tailnet access to devices on a local network that do not have Tailscale installed.

Why Use Subnet Routing?

  • Access printers, NAS devices, IoT devices, or other equipment that cannot run Tailscale
  • Reach an entire office or home LAN from any device on your tailnet
  • Avoid installing Tailscale on every single device in a network

Enable Subnet Routing

On the Linux machine that will serve as the subnet router:

# Enable IP forwarding (required for routing)
echo 'net.ipv4.ip_forward = 1' | sudo tee -a /etc/sysctl.d/99-tailscale.conf
echo 'net.ipv6.conf.all.forwarding = 1' | sudo tee -a /etc/sysctl.d/99-tailscale.conf
sudo sysctl -p /etc/sysctl.d/99-tailscale.conf

# Advertise the local subnet
sudo tailscale up --advertise-routes=192.168.1.0/24

If you have multiple subnets:

sudo tailscale up --advertise-routes=192.168.1.0/24,10.0.0.0/24

Approve the Route in the Admin Console

Subnet routes are not active until an admin approves them:

  1. Go to the Tailscale admin console
  2. Find the subnet router machine
  3. Click the three-dot menu and select Edit route settings
  4. Enable the advertised routes

Verify Subnet Access

From any other device on your tailnet:

# Ping a device on the remote LAN (e.g., a NAS at 192.168.1.100)
ping 192.168.1.100

# SSH to a device on the remote LAN
ssh admin@192.168.1.50

Exit Nodes

An exit node routes all internet traffic from a device through another device on your tailnet. This is useful for:

  • Routing traffic through a device in a specific geographic location
  • Using a trusted network’s internet connection when on untrusted Wi-Fi
  • Accessing geo-restricted content from your home IP

Configure an Exit Node

On the device that will serve as the exit node:

# Advertise this device as an exit node
sudo tailscale up --advertise-exit-node

Approve the exit node in the Tailscale admin console, just like subnet routes.

Use an Exit Node

On the device that should route traffic through the exit node:

# Route all traffic through a specific exit node
sudo tailscale up --exit-node=server

# Or use the Tailscale IP
sudo tailscale up --exit-node=100.64.0.2

To stop using the exit node:

sudo tailscale up --exit-node=

Verify Exit Node is Working

# Check your public IP -- it should match the exit node's public IP
curl -s https://ifconfig.me

# Check Tailscale status for exit node info
tailscale status

Important: When using an exit node, all DNS queries are also routed through that node by default. This prevents DNS leaks but means DNS resolution speed depends on the exit node’s DNS configuration.

Access Control Lists (ACLs)

Tailscale ACLs define which devices and users can communicate with each other. By default, all devices on a tailnet can reach all other devices. ACLs let you restrict this.

Understanding ACL Syntax

ACLs are defined in the Tailscale admin console under Access Controls. The policy file uses a JSON-like syntax called HuJSON (Human JSON) that supports comments:

{
  // Allow all users full access (default policy)
  "acls": [
    {
      "action": "accept",
      "src": ["*"],
      "dst": ["*:*"]
    }
  ]
}

Restrictive ACL Example

A more practical policy that segments access by role:

{
  "groups": {
    "group:admin": ["user@example.com"],
    "group:developers": ["dev1@example.com", "dev2@example.com"]
  },
  "tagOwners": {
    "tag:server": ["group:admin"],
    "tag:database": ["group:admin"]
  },
  "acls": [
    // Admins can access everything
    {
      "action": "accept",
      "src": ["group:admin"],
      "dst": ["*:*"]
    },
    // Developers can access servers on specific ports
    {
      "action": "accept",
      "src": ["group:developers"],
      "dst": ["tag:server:80,443,22"]
    },
    // Only admins can access databases
    {
      "action": "accept",
      "src": ["group:admin"],
      "dst": ["tag:database:5432,3306"]
    },
    // All users can ping all devices
    {
      "action": "accept",
      "src": ["*"],
      "dst": ["*:*"],
      "proto": "icmp"
    }
  ]
}

Apply Tags to Devices

Tags are applied when bringing a device up:

# Tag a device as a server
sudo tailscale up --advertise-tags=tag:server

# Tag a device with multiple tags
sudo tailscale up --advertise-tags=tag:server,tag:database

Note: Tagged devices are owned by the tag, not a user. This means they cannot be used for interactive logins and are ideal for infrastructure nodes.

Test ACL Rules

Use the ACL test feature in the admin console to verify your rules before applying them. You can also use tailscale ping and tailscale netcheck to verify connectivity after applying ACLs.

MagicDNS and Custom DNS

MagicDNS automatically assigns DNS names to your Tailscale devices, so you can refer to them by name instead of IP address.

Enable MagicDNS

MagicDNS is enabled by default on new tailnets. If it is not enabled:

  1. Go to the Tailscale admin console
  2. Navigate to DNS
  3. Enable MagicDNS

With MagicDNS enabled, you can use device names directly:

# Instead of:
ssh user@100.64.0.2

# You can use:
ssh user@server

# Or the fully qualified name:
ssh user@server.tailnet-name.ts.net

Add Custom DNS Nameservers

You can configure global or split DNS settings in the admin console:

# Global nameservers (used for all DNS queries)
# Set in admin console under DNS > Nameservers

# Split DNS (route specific domains to specific nameservers)
# Example: Route *.corp.example.com to your corporate DNS
# Set in admin console under DNS > Nameservers > Add Split DNS

Split DNS is especially useful when combined with subnet routing. For example, if you advertise a route to your office LAN, you can also configure split DNS so that *.office.local queries resolve through the office DNS server.

Override Local DNS

To force all DNS queries through Tailscale’s configured nameservers:

sudo tailscale up --accept-dns=true

To disable MagicDNS on a specific device:

sudo tailscale up --accept-dns=false

Sharing Nodes with Other Users

Tailscale allows you to share specific devices with users outside your tailnet. This is useful for giving a contractor access to a specific server without adding them to your entire network.

Share a Node

  1. Go to the Tailscale admin console
  2. Find the machine you want to share
  3. Click the three-dot menu and select Share
  4. Enter the email address of the external user

The shared node appears in the external user’s tailnet, but they can only access that specific device — not your entire network.

External User Access

The external user must:

  1. Have a Tailscale account
  2. Accept the share invitation
  3. The shared device appears in their tailscale status output
# External user sees the shared device
tailscale status
# 100.64.0.50   shared-server    shared by user@example.com  linux

Tip: Combine node sharing with ACLs to restrict which ports the external user can access on the shared device. For example, allow only SSH (port 22) and HTTP (port 80).

Tailscale Commands Reference

CommandDescription
tailscale upConnect to your tailnet and authenticate
tailscale downDisconnect from the tailnet
tailscale statusShow connected devices and their IPs
tailscale ping <host>Ping a device and show the connection path
tailscale netcheckRun a network diagnostic check
tailscale ipShow your Tailscale IP addresses
tailscale dns statusShow current DNS configuration
tailscale file send <file> <host>Send a file to another device using Taildrop
tailscale file get <directory>Receive files sent via Taildrop
tailscale ssh <user>@<host>SSH to a device using Tailscale SSH
tailscale cert <domain>Obtain a TLS certificate for a Tailscale domain
tailscale logoutLog out and remove device from tailnet
tailscale up --advertise-routes=<CIDR>Advertise subnet routes
tailscale up --advertise-exit-nodeAdvertise as an exit node
tailscale up --exit-node=<host>Use a specific exit node
tailscale up --advertise-tags=<tags>Apply ACL tags to the device
tailscale up --accept-dns=falseDisable MagicDNS on this device
tailscale bugreportGenerate a bug report for troubleshooting

Troubleshooting

Device Not Appearing in the Admin Console

# Verify the daemon is running
sudo systemctl status tailscaled

# Check for authentication errors in logs
sudo journalctl -u tailscaled --since "10 minutes ago"

# Force re-authentication
sudo tailscale up --force-reauth

Cannot Reach Other Devices

# Run a network diagnostic
tailscale netcheck

# Check if the connection is direct or relayed
tailscale ping <device-name>

# Verify firewall is not blocking Tailscale
sudo iptables -L -n | grep -i tailscale

# Check if UDP port 41641 is reachable (used for direct connections)
sudo ss -ulnp | grep tailscaled

Slow Connections (Relayed Traffic)

If tailscale ping shows traffic going through a DERP relay instead of a direct connection:

# Run netcheck to see NAT type and connectivity
tailscale netcheck

# Example output showing potential issues:
#   UDP: true
#   IPv4: yes, 203.0.113.50:41641
#   MappingVariesByDestAddr: false
#   PortMapping: UPnP
#   Nearest DERP: New York City

Common causes of relayed connections:

  • Symmetric NAT on one or both sides (MappingVariesByDestAddr: true)
  • Firewall blocking UDP on port 41641
  • Corporate firewalls doing deep packet inspection

Solutions:

# On Linux, ensure UDP is not blocked
sudo ufw allow 41641/udp

# If behind a strict corporate firewall, Tailscale will fall back to DERP relay
# DERP is encrypted and functional, just slightly slower

Subnet Routes Not Working

# Verify IP forwarding is enabled
sysctl net.ipv4.ip_forward
# Should return: net.ipv4.ip_forward = 1

# Check that routes are advertised
tailscale status --json | grep -A5 "AllowedIPs"

# Verify routes are approved in the admin console
# Unapproved routes will not work

MagicDNS Not Resolving

# Check DNS status
tailscale dns status

# Verify resolv.conf is managed by Tailscale
cat /etc/resolv.conf

# If using systemd-resolved, check its configuration
resolvectl status

# Force DNS refresh
sudo tailscale down && sudo tailscale up

Summary

Tailscale transforms the complexity of VPN setup into a near-zero-configuration experience. By building on WireGuard’s cryptographic foundations and adding automatic NAT traversal, identity-based authentication, and a mesh topology, Tailscale lets you connect all your devices securely in minutes rather than hours.

Key takeaways from this guide:

  • Installation is trivial: One command to install, one command to connect
  • Mesh networking eliminates bottlenecks: Devices communicate directly without a central server
  • Subnet routing extends reach: Access devices that cannot run Tailscale through a subnet router
  • Exit nodes provide flexible traffic routing: Route all traffic through any device on your tailnet
  • ACLs enforce least-privilege access: Control who can reach what at a granular level
  • MagicDNS simplifies addressing: Use device names instead of IP addresses

For related security and networking guides, see our articles on setting up a WireGuard VPN server on Ubuntu for manual WireGuard configuration, and SSH hardening for Linux servers to secure the SSH connections to your Tailscale-connected servers.