# Tailscale: A Mesh VPN for Your Servers and Homelab

> How to connect servers, laptops, and a homelab into a single private network with Tailscale's WireGuard mesh, then self-host the control plane with Headscale.

URL: https://www.matthewswong.com/en/blog/tailscale-mesh-vpn-self-hosted/

- Author: Matthews Wong (https://www.matthewswong.com/en/about/)
- Published: 2026-07-09
- Updated: 2026-07-09
- Category: DevOps

Every developer eventually hits the same wall: a database sitting on a VPS that should never touch the public internet, a homelab NAS behind a residential router with no static IP, and a laptop that needs to reach both without opening a single port. Traditional VPNs solve this with a central gateway that becomes a bottleneck and a single point of failure. Tailscale takes a different approach entirely.

Tailscale builds a mesh network on top of WireGuard, where every device gets a stable private IP and talks directly to every other device over an encrypted tunnel, no matter where it physically sits. This post walks through installing it across servers and a homelab, locking traffic down with access control lists, exposing whole subnets through a router node, and finally replacing Tailscale's hosted coordination server with your own self-hosted Headscale instance.

## Why a mesh beats a hub and spoke VPN

Classic VPNs route every packet through one gateway. That gateway has to scale with your total traffic, it is the one thing that takes the whole network down if it fails, and it adds a hop of latency to every single connection even between two machines sitting in the same data center. A mesh network flips this: the control server only handles authentication and exchanges public keys, while the actual data travels peer to peer whenever a direct path exists.

- Direct peer to peer connections mean two servers in the same region talk to each other with almost no added latency, since the packets never leave the local network segment.
- There is no single gateway to overload, so adding a hundred more devices to the tailnet does not degrade throughput between the devices already connected.
- If the coordination server goes offline temporarily, existing peer connections keep working because the WireGuard keys were already exchanged and cached locally.

> Start by installing Tailscale on exactly two machines, a home laptop and one cloud server, and confirm you can ping the server by its assigned private IP before adding anything else. Getting the smallest possible mesh working first makes every later step, ACLs, subnet routes, self-hosting, much easier to debug.

## Installing Tailscale and joining the tailnet

The client installs the same way on Linux, macOS, and Windows, and the first run walks you through browser based authentication against your identity provider. Once authenticated, the device is assigned a stable IP in the 100.64.0.0 to 100.127.255.255 range that never changes even if you rejoin the network later. MagicDNS then gives every device a human readable hostname like homelab-nas dot your tailnet name, so you almost never need to memorize the IP addresses at all.

## Reaching a whole subnet with a subnet router

Installing the client on every single device in a homelab is not always practical, especially for embedded devices, printers, or a NAS appliance that does not run a general purpose operating system. A subnet router solves this by advertising an entire local network range to the tailnet from one machine that does run the client, letting every other device on the mesh reach anything on that subnet without installing anything extra.

1. Enable IPv4 and IPv6 forwarding on the machine that will act as the router, since Tailscale relies on the kernel forwarding packets between the tailnet interface and the local network interface.
2. Run the client with the advertise routes flag set to the CIDR range of the local subnet, for example the router's own LAN, so the control server knows this device can reach that range.
3. Approve the advertised route from the admin console, since unapproved routes are ignored by default as a safety measure against accidentally exposing an unintended network.

> A subnet router that advertises 0.0.0.0/0 or an overly broad range can accidentally expose far more of your network than intended. Always advertise the narrowest CIDR block that covers only the devices you actually want reachable, and double check the approved routes list in the admin console after every change.

## Locking down traffic with access control lists

By default every device on a tailnet can reach every other device, which is fine for a two machine test but is not what you want once servers, laptops, and a partner's contractor account all share the same mesh. The tailnet policy file, written in a JSON flavored syntax called HuJSON, lets you define tags for groups of devices and then write explicit accept rules describing exactly which tagged group can reach which ports on which other tagged group.

Concept

What it does

Practical note

Tag

Labels a device by role instead of by owner, such as server or homelab.

Tags survive device re-registration, unlike per user rules.

ACL rule

An explicit accept statement naming a source, a destination, and allowed ports.

Everything not explicitly accepted is denied once any rule exists.

Autogroup

Built in groups like members or admin that reference account roles.

Useful for rules that should apply to every human user, not a specific tag.

SSH check

A policy block that gates SSH access through Tailscale's own SSH feature.

Removes the need to distribute separate SSH keys to every server.

## Self-hosting the control plane with Headscale

Tailscale's hosted coordination server is free for personal use and handles authentication, key exchange, and DERP relay fallback for you, but some teams want the control plane itself running on infrastructure they own, whether for compliance, cost at scale, or simple curiosity. Headscale is an open source, community maintained reimplementation of that control server that speaks the same protocol as the official Tailscale clients, so the same install script and CLI commands work unmodified against it.

- Headscale ships as a single Go binary or a container image, and a minimal deployment needs only a config file, a SQLite or Postgres database, and an exposed HTTPS endpoint.
- Official Tailscale clients connect to a Headscale server by passing the login server flag with your server's URL instead of the default Tailscale coordination endpoint.
- Headscale does not include a hosted DERP relay network by default, so devices behind strict NAT without direct connectivity may need you to run your own relay or point at Tailscale's public DERP servers.

Headscale is community maintained and not an official Tailscale product, but it deliberately targets protocol compatibility with the real Tailscale clients, so you keep the same install experience your team already knows while owning the control plane yourself.

## A rollout checklist before you commit

Before treating any mesh VPN as production infrastructure for real servers, work through a short checklist so a misconfiguration does not turn into an outage or, worse, an accidental exposure.

- Confirm the tailnet policy file denies traffic by default and every accept rule references a tag rather than an individual device, so removing one server does not silently open a hole.
- Test that a subnet router's advertised route survives a reboot of that machine, since forwarding settings written only to the running kernel state disappear on restart.
- Verify MagicDNS resolves every hostname you plan to reference in scripts or deployment tooling, since a typo in a hostname fails silently as a DNS lookup error rather than a clear permission denial.
- If self-hosting Headscale, set up automated backups of its database, because losing that database means every device must re-register and re-authenticate from scratch.

A mesh VPN built on WireGuard removes an entire category of networking pain: no more manually punching holes in firewalls, no more juggling dynamic residential IPs, and no more single point of failure sitting between your laptop and the server you need to SSH into at two in the morning. Whether you stick with Tailscale's hosted control plane or move to a self-hosted Headscale instance, the underlying mesh behaves the same way, which makes it a rare piece of infrastructure you can adopt gradually without locking yourself into one vendor's control plane forever.

## Sources

- Tailscale Docs — Terminology and concepts
- Tailscale Docs — Subnet routers
- Headscale on GitHub (juanfont/headscale)
- Wikipedia — WireGuard

> **Key takeaway:** Tailscale builds an encrypted mesh network on top of WireGuard, giving every server, laptop, and homelab device a stable private IP and direct peer-to-peer connections instead of routing through a single VPN gateway. This guide covers installing Tailscale, exposing a homelab subnet through a router node, locking down access with ACLs, and self-hosting the control plane with Headscale.

## Source links

- https://tailscale.com/kb/1155/terminology-and-concepts
- https://tailscale.com/docs/features/subnet-routers
- https://github.com/juanfont/headscale
- https://en.wikipedia.org/wiki/WireGuard

## FAQ

### What is Tailscale and how does it differ from a traditional VPN?

Tailscale is a mesh VPN built on the WireGuard protocol that gives every device a stable private IP and connects devices directly to each other whenever possible. Unlike a traditional VPN that routes all traffic through one central gateway, Tailscale only uses its coordination server for authentication and key exchange, so actual data can travel peer to peer with lower latency and no single point of failure.

### Why would I self-host Headscale instead of using Tailscale directly?

Headscale is an open source, community maintained reimplementation of Tailscale control server that speaks the same protocol as official Tailscale clients. Teams choose it when they want the coordination plane running on infrastructure they fully own, whether for compliance requirements, cost control at large device counts, or simply to avoid depending on a third party service for core connectivity.

### How do subnet routers let me reach devices that cannot run the Tailscale client?

A subnet router is a regular tailnet device that advertises a whole local network range, such as a homelab LAN, to the rest of the mesh. Other devices on the tailnet can then reach anything on that advertised subnet, including printers, NAS appliances, or embedded devices, without installing the Tailscale client on each of them individually.

### Can I use access control lists to restrict which devices talk to each other?

Yes, Tailscale enforces access control through a tailnet policy file written in a JSON flavored syntax. You tag devices by role, such as server or homelab, and write explicit accept rules naming the source tag, destination tag, and allowed ports, so once any rule exists everything not explicitly permitted is denied by default.

### What happens to my devices if the Headscale server goes down temporarily?

Existing peer to peer connections continue working because the WireGuard keys were already exchanged and cached on each device before the outage. New device registrations and fresh key exchanges will fail until the control server is back online, but already connected machines keep talking to each other over their established encrypted tunnels.

---

- HTML version: https://www.matthewswong.com/en/blog/tailscale-mesh-vpn-self-hosted/
- Bahasa Indonesia: https://www.matthewswong.com/id/blog/tailscale-mesh-vpn-self-hosted/
- Site index for agents: https://www.matthewswong.com/llms.txt
- Sitemap: https://www.matthewswong.com/sitemap.xml
- API description (OpenAPI): https://www.matthewswong.com/openapi.json
