How to Deploy a Zero‑Trust WireGuard VPN with Tailscale on Ubuntu Server (2025 Guide)

Overview

This step-by-step guide shows how to deploy a zero-trust VPN using Tailscale (built on WireGuard) on Ubuntu Server. You will install the Tailscale client, log in with SSO, enable secure SSH, configure access control lists (ACLs), expose a private subnet, and optionally offer an exit node. The result is a modern, fast, and secure VPN with minimal maintenance and strong identity-based access controls—perfect for homelabs and production servers in 2025.

Why Tailscale (WireGuard) for Zero Trust

Tailscale uses the WireGuard protocol for speed and strong cryptography while removing the operational pain of traditional VPNs. Devices authenticate using your identity provider (Google, Microsoft, Okta, GitHub, and others) and connect peer-to-peer where possible. You gain per-device keys, automatic NAT traversal, policy-based access (ACLs), MagicDNS, and optional Tailscale SSH that replaces inbound firewall holes.

Prerequisites

You need an Ubuntu Server 22.04 or 24.04 host with sudo access. Ensure outbound HTTPS (TCP 443) and UDP 41641 are allowed. No inbound ports are strictly required. Have a browser handy to authenticate to your identity provider or prepare a reusable auth key from the Tailscale admin console for headless systems.

Install Tailscale on Ubuntu

Run these commands to add the official repository and install Tailscale. The snippet auto-detects your Ubuntu codename:

curl -fsSL https://pkgs.tailscale.com/stable/ubuntu/$(. /etc/os-release; echo $VERSION_CODENAME).noarmor.gpg | sudo tee /usr/share/keyrings/tailscale-archive-keyring.gpg >/dev/null

curl -fsSL https://pkgs.tailscale.com/stable/ubuntu/$(. /etc/os-release; echo $VERSION_CODENAME).tailscale-keyring.list | sudo tee /etc/apt/sources.list.d/tailscale.list

sudo apt-get update && sudo apt-get install -y tailscale

Authenticate and bring the node online

For interactive login, start Tailscale and enable Tailscale SSH. This avoids exposing port 22 to the internet and lets you restrict SSH via ACLs:

sudo tailscale up --ssh --operator=$USER --accept-dns=true --accept-routes=true --advertise-tags=tag:server

If the server is headless, generate an auth key in the Tailscale admin console (preferably tagged and reusable or ephemeral) and run:

sudo tailscale up --ssh --authkey=tskey-******** --advertise-tags=tag:server

Verify connectivity with tailscale status, view the device IPs via tailscale ip -4, and test pings to another node using tailscale ping <device-or-name>.

Enable zero-trust access controls (ACLs)

Open the Tailscale admin console and switch to the ACLs page. Keep policies simple and human-readable. Example: allow your admin group to SSH to servers and let developers access staging web ports:

{
  "groups": { "group:admins": ["[email protected]"], "group:devs": ["[email protected]"] },
  "tagOwners": { "tag:server": ["group:admins"] },
  "acls": [
    { "action": "accept", "users": ["group:admins"], "ports": ["tag:server:22,2222"] },
    { "action": "accept", "users": ["group:devs"], "ports": ["tag:server:80,443,8080"] }
  ],
  "ssh": [
    { "action": "check", "src": ["group:admins"], "dst": ["tag:server"], "users": ["root", "ubuntu"] }
  ]
}

This policy makes tag:server devices manageable by admins, grants controlled port access, and restricts Tailscale SSH to authorized identities. Commit and save to enforce instantly.

Expose your LAN with a Subnet Router (optional)

If the Ubuntu host can reach a private LAN (e.g., 192.168.10.0/24), you can advertise that subnet to Tailscale peers without opening your firewall. First, enable IP forwarding:

echo 'net.ipv4.ip_forward=1' | sudo tee /etc/sysctl.d/99-tailscale.conf

echo 'net.ipv6.conf.all.forwarding=1' | sudo tee -a /etc/sysctl.d/99-tailscale.conf

sudo sysctl --system

Now advertise the subnet routes:

sudo tailscale up --advertise-routes=192.168.10.0/24 --accept-routes=true

Approve the routes in the admin console. For UFW, permit forwarding within the LAN and from the Tailscale interface (typically tailscale0):

sudo ufw route allow in on tailscale0 out on eth0 to 192.168.10.0/24

sudo ufw reload

Set up an Exit Node (optional)

An exit node lets approved devices send all internet traffic through your Ubuntu server. This is useful for securing devices on public Wi‑Fi or egressing from a fixed IP. Enable it on the server:

sudo tailscale up --advertise-exit-node=true

In the admin console, allow the exit node and then, from a client, choose “Use exit node”. Optionally permit local LAN access while using the exit node by enabling “Allow LAN access” on the client.

Security hardening and best practices

Restrict who can reach what by tags and groups; avoid broad *:* policies. Prefer Tailscale SSH over public SSH. Disable password auth in OpenSSH (sudoedit /etc/ssh/sshd_config, set PasswordAuthentication no) and restart SSH. Keep the system current and enable unattended upgrades:

sudo apt-get install -y unattended-upgrades

sudo dpkg-reconfigure --priority=low unattended-upgrades

If you use UFW, you generally do not need to open inbound ports for Tailscale. Traffic arrives over the encrypted tunnel and is handled by tailscaled. For large fleets, use ephemeral auth keys for CI/CD runners (--ephemeral) and shorter key lifetimes. Consider using device posture checks and auto-approvers in ACLs where appropriate.

Troubleshooting quick checks

Run sudo tailscale bugreport to gather diagnostics if needed. Use tailscale netcheck to verify NAT traversal, tailscale status to view peers, and tailscale ping to test reachability. If subnets are not reachable, confirm routes are approved and that IP forwarding and UFW rules allow routed traffic. If speeds seem low, ensure direct connections are established (not relayed) and verify that CPU scaling or virtualization offloads are not limiting WireGuard throughput on the server.

What you achieved

You installed a production-ready, zero-trust WireGuard VPN with Tailscale on Ubuntu, authenticated it with SSO, enabled Tailscale SSH, enforced fine-grained ACLs, and optionally provided subnet routing and exit-node functionality. This approach is simpler, faster, and safer than legacy site-to-site or username/password VPNs, and it scales from a single VPS to a multi-site enterprise network with minimal toil.

Comments