Logo

Tailscale: zero-config mesh VPN for multi-VPS fleet

Tailscale: zero-config mesh VPN for multi-VPS fleet

Connect all your servers, workstations and mobile devices into a private network without configuring NAT, ports or keys. Tailscale (based on WireGuard) automates everything: SSO authentication, NAT traversal, routing. The modern standard for managing distributed infrastructure.

Introduction

When managing 5 VPS, 2 workstations, 1 NAS and 3 Raspberry Pis spread across multiple networks, configuring a classic VPN (OpenVPN, manual WireGuard) becomes hell: keys, NAT, port forwarding, hub-and-spoke...

Tailscale radically simplifies:

  • You install an agent on each machine
  • You log in with your Google/Microsoft/Github account
  • All your machines appear in a virtual private network
  • Each machine has a stable private IP (100.x.x.x or Tailnet IPv6)
  • Automatic NAT traversal (WebRTC-style)
  • No central server to manage (Tailscale hosts the control plane)

Architecture: peer-to-peer mesh. Each machine establishes a direct WireGuard tunnel with others. Tailscale is just the "ID card" that lets them find each other.

Prerequisites

  • Free Tailscale account (up to 100 machines, 3 users)
  • Linux/Windows/macOS/iOS/Android machines to connect
  • Admin/root access on each machine

Step 1: Create a Tailscale account

  1. Sign up at https://tailscale.com (free for personal/small-pro use)
  2. You get a tailnet (personal network): e.g. mathys.github.ts.net
  3. Log in with Google, Microsoft, GitHub, or Okta

Step 2: Install Tailscale on a Linux VPS

curl -fsSL https://tailscale.com/install.sh | sh

Start and authenticate:

sudo tailscale up

A URL appears: open it in your browser, validate. Machine appears in your tailnet.

Check:

sudo tailscale status

Typical output:

100.64.0.1  srv-web-01  mathys@  linux  -
100.64.0.2  srv-db-01   mathys@  linux  -
100.64.0.3  laptop      mathys@  macos  active; direct...

Step 3: Connect other machines

Windows

Download installer: https://tailscale.com/download

macOS

Mac App Store or: brew install --cask tailscale

iOS / Android

App Store / Play Store → "Tailscale"

On each machine, log in with the same account (otherwise they don't see each other).

Step 4: Communication between machines

Once two machines are in the tailnet:

# From srv-web-01
ping 100.64.0.2

# SSH connection
ssh [email protected]

You can also use MagicDNS (enabled by default):

ping srv-db-01
ssh user@srv-db-01

Names are Tailscale hostnames, accessible from any tailnet machine.

Step 5: Disable periodic auth (personal keys)

By default, machines must re-authenticate every 180 days. For servers, you want permanent:

  1. In Tailscale admin → Machines
  2. Click the machine → Disable key expiry

Or in CLI:

sudo tailscale up --advertise-tags=tag:server

Combined with reusable auth keys (see step 6).

Step 6: Auth Keys (to automate deployment)

To install Tailscale on 20 VPS without clicking 20 auth links:

  1. In Tailscale → Settings → Keys → Generate auth key
  2. Check:
    • Reusable (usable on multiple machines)
    • Ephemeral: no (otherwise machine deleted on disconnect)
    • Pre-authorized: yes
    • Expiration: 90 days for example
  3. Tags: tag:server

You get tskey-auth-XXXXXX.

On each new VPS:

curl -fsSL https://tailscale.com/install.sh | sh
sudo tailscale up --authkey=tskey-auth-XXXXXX --advertise-tags=tag:server

Machine auto-appears in your tailnet, no interaction.

Step 7: ACLs (who can access who)

In Tailscale admin → Access controls. Language is JSON.

Example: isolate servers from clients

{
    "tagOwners": {
        "tag:server": ["mathys@github"],
        "tag:client":  ["mathys@github"]
    },
    "acls": [
        // Mathys (admin) accesses everything
        {
            "action": "accept",
            "src":    ["mathys@github"],
            "dst":    ["*:*"]
        },
        
        // Servers can see each other
        {
            "action": "accept",
            "src":    ["tag:server"],
            "dst":    ["tag:server:*"]
        },
        
        // Clients do NOT see servers (default deny)
    ]
}

Click Save. ACLs applied in <10 seconds.

Step 8: Subnet Router (extend access to a site's LAN)

You have a home VPN with a NAS at 192.168.1.50. You want all your tailnet to access the NAS without installing Tailscale on the NAS itself.

On a LAN machine (e.g. Raspberry Pi at 192.168.1.10):

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

Enable IP forwarding:

echo "net.ipv4.ip_forward = 1" | sudo tee -a /etc/sysctl.conf
sudo sysctl -p

In Tailscale admin → Machines → Raspberry Pi → Edit route settings → check 192.168.1.0/24.

Now all your other tailnet machines can reach 192.168.1.50 directly.

Step 9: Exit Node (route all your traffic via a VPS)

To use a VPS as internet exit (like a classic VPN):

On VPS:

sudo tailscale up --advertise-exit-node

Enable in admin → Edit → Use as exit node.

On a client (laptop, mobile):

sudo tailscale up --exit-node=srv-web-01

All your traffic now goes through the VPS. Ideal for bypassing wifi restrictions or anonymizing.

Step 10: Tailscale SSH (replaces SSH keys)

Tailscale can act as an SSH bastion: no key management.

On servers:

sudo tailscale up --ssh

Now, from your tailnet laptop:

ssh root@srv-web-01

No password, no key: Tailscale auto-authenticates with your identity (Google/Microsoft).

ACLs for SSH

{
    "ssh": [
        {
            "action": "check",
            "src":    ["mathys@github"],
            "dst":    ["tag:server"],
            "users":  ["root", "ubuntu", "mathys"]
        }
    ]
}

"check" requires auth re-validation every 12h. "accept" allows without check.

Step 11: Funnel (expose a service to internet via Tailscale)

Tailscale Funnel exposes a tailnet service to internet (like Cloudflare Tunnel):

# Activate on machine
sudo tailscale serve --bg --https=443 http://localhost:3000

# Expose to internet
sudo tailscale funnel 443 on

Your service is accessible at https://srv-web-01.mathys.github.ts.net. SSL cert auto-managed by Tailscale.

⚠️ Funnel is limited to ports 443, 8443, 10000. Not for exposing everything in prod.

Step 12: Stats and monitoring

# Detailed status
sudo tailscale status

# Network stats (latency, throughput, direct peer or via DERP relay)
sudo tailscale netcheck

# Machine's Tailscale IPs
sudo tailscale ip -4
sudo tailscale ip -6

# Verify connectivity with a peer
sudo tailscale ping srv-db-01

# Detailed logs
sudo journalctl -u tailscaled -f

Step 13: Tailnet config backup

To export your config (ACLs, machines, tags):

  1. Settings → Tailnet policy file → Export button
  2. Download the JSON

To automate (via Tailscale API):

curl -H "Authorization: Bearer YOUR_API_TOKEN" \
    https://api.tailscale.com/api/v2/tailnet/mathys.github.ts.net/acl > acl-backup.json

Troubleshooting

"no route to host" between 2 tailnet machines

Check status:

sudo tailscale status

If you see idle; relay "derp...", NAT traversal failed → traffic goes through Tailscale relays (DERP), slower but works. To force direct, open UDP 41641 on firewall.

"tailscaled.service failed to start"

sudo systemctl status tailscaled
sudo journalctl -u tailscaled -n 50

Often an initial network issue. Reset:

sudo tailscale down
sudo tailscale up

Machine appears expired

Go to admin → Disable key expiry on the machine.

IP conflicts with your local LAN

Tailscale uses 100.64.0.0/10 by default. If your LAN uses this range, conflict. Solution: change Tailscale range (Settings → Network) or change your LAN.

Degraded performance

sudo tailscale netcheck

If JustOK or Bad, no direct peering is possible. Causes: double symmetric NAT, firewall, MTU mismatch.

Useful commands

# Up / Down
sudo tailscale up
sudo tailscale down

# Status
sudo tailscale status
sudo tailscale status --json

# Detailed info
sudo tailscale netcheck

# List peers
sudo tailscale status --peers

# Disable DNS (if conflict)
sudo tailscale up --accept-dns=false

# Set custom hostname
sudo tailscale up --hostname=my-custom-name

# Full reset
sudo tailscale logout
sudo tailscale up

# Remove Tailscale
sudo apt purge tailscale -y

Conclusion

Tailscale eliminates VPN complexity:

  • Setup: 1 command to join the tailnet
  • Security: WireGuard + enterprise SSO auth
  • Performance: direct peer-to-peer when possible
  • ACLs: fine control by tag/user
  • Free tier: 100 machines, 3 users

Ideal for:

  • Multi-VPS fleet administration
  • Lab access from anywhere
  • Inter-site/client connection
  • Replacement of corporate OpenVPN

Going further:

  • Headscale: open-source implementation of Tailscale control plane (self-hosted, free unlimited)
  • NetBird: similar alternative, open-source mesh
  • Pure WireGuard: if you want 100% self-hosted without agent (see dedicated guide)

Resources

  • Headscale (self-host alternative): https://github.com/juanfont/headscale
  • VeryCloud guide — WireGuard VPN: /docs/article/wireguard
  • VeryCloud guide — Reverse SSH: /docs/article/reverse-ssh
  • VeryCloud guide — SSH hardening: /docs/article/ssh-hardening

Join our Discord community server

For any questions, suggestions, or just to chat with the community, join us on Discord!

900+Members