Tailscale for Homelab Networking
There is a particular kind of homelab frustration that every operator eventually hits. You have a NAS, a Proxmox cluster, a self-hosted Gitea instance, a monitoring stack, maybe a few Raspberry Pis scattered around — and you want to reach all of it from your laptop at a coffee shop or your phone on a cellular connection. The naive solution is to open ports. Port 22 for SSH, port 443 for the reverse proxy, maybe a non-standard port here or there to feel safer. You set up a DDNS record so your dynamic residential IP stays resolvable. You add fail2ban. You tell yourself it’s fine.
It is not fine.
Every open port is a surface. The internet will find it within minutes, bots will probe it relentlessly, and one misconfigured service or unpatched CVE away from a very bad day. The DDNS record leaks your residential IP. The port exposures grow over time as you add services — entropy wins eventually. The right answer is to keep all of your services off the public internet entirely and use a secure tunnel to reach them. Tailscale makes that so low-friction that there is no longer a good excuse for the port-forwarding approach.
This post is a thorough walk through every part of Tailscale that matters for a homelab: how it actually works at the protocol level, how to set up subnet routers to reach devices that can’t run Tailscale, how exit nodes work, how to get split DNS and MagicDNS to make your internal services reachable by name, how to write proper ACL policy files, and when you might want to run Headscale as a self-hosted control plane instead. We will also be honest about the trust model — what Tailscale the company can see, and what they cannot.
The Homelab Connectivity Problem
The old approach to remote homelab access was built around two assumptions that no longer hold: that you have a static IP, and that open ports are acceptable. Neither is really true for most residential setups.
Dynamic DNS patches the IP problem, barely. You register a hostname with a DDNS provider, run a client that updates the record whenever your ISP reassigns your address. The latency between your IP changing and the record updating can leave your connection broken for minutes. More importantly, your home IP is now semi-publicly associated with your domain — something ISPs, data brokers, and anyone running passive DNS collection can correlate. This is a real concern if your homelab hosts anything sensitive, or if you simply value privacy.
The port forwarding problem is worse. Every service you expose requires a firewall hole. Your router’s NAT table gets entries. Anything with a vulnerability scanner — which is every internet-connected device within a week of being stood up — finds those ports and starts throwing exploits at them. SSH on port 22 gets hundreds of login attempts per hour from botnets. Your Nextcloud on port 443 gets probed for known PHP CVEs. Your “secure” admin panel on port 8443 with HTTP basic auth is one credential stuffing attack away from compromise. You are playing permanent defense against the entire internet.
Traditional VPN solutions like OpenVPN or IPsec do solve the exposure problem, but they introduce their own friction. You need a server with a static IP to act as the VPN endpoint. You need to provision and distribute certificates or pre-shared keys. Clients need to be configured with that server’s address. If the server goes down, everyone loses access. Key rotation is a manual operation. Adding a new device means generating credentials, distributing them, and updating server configuration. None of this is catastrophic, but it is operational overhead that compounds over time — and most homelabbers are running these things in their spare time, not as a day job.
Tailscale’s pitch is direct: install a package, log in with your identity provider, and every device gets a stable IP in the 100.64.0.0/10 range. Every device can reach every other device. No central server to maintain. No manual key exchange. No firewall rules to punch. Close all your exposed ports.
That pitch is accurate. The question is what it costs and how it actually works.
How WireGuard Works
Tailscale is built on WireGuard, and understanding WireGuard’s design is necessary to understand both what Tailscale adds and what limitations it’s working around.
WireGuard is a modern VPN protocol built into the Linux kernel (since 5.6) and available as a userspace implementation (wireguard-go) everywhere else. Its design philosophy is radical simplicity: a single UDP socket, no TCP, no complex state machine, no certificate hierarchy. Authentication is pure public-key cryptography — each peer has a Curve25519 keypair, and routing decisions are made based on which public keys are in the configuration.
The core concept in WireGuard is cryptokey routing. Every WireGuard interface (wg0, wg1, etc.) has a list of peers. Each peer entry contains a public key and an AllowedIPs list. When a packet arrives on the WireGuard interface, WireGuard checks which peer entry claims that source IP — if the packet decrypts successfully with that peer’s key, it’s accepted and routed to the IP stack. When a packet is sent, WireGuard looks up the destination IP against all peers’ AllowedIPs lists, finds the matching peer, encrypts the packet with that peer’s key, and sends it as a UDP datagram to the peer’s endpoint.
This is elegant, stateless, and fast. The kernel integration means packet processing happens in kernel space with very low overhead. WireGuard’s cryptography (Curve25519, ChaCha20-Poly1305, BLAKE2s) is modern and well-audited.
But WireGuard’s simplicity is also its limitation for a dynamic deployment. WireGuard itself is a pure data plane. It does not know how to discover peers, distribute keys, or handle peers whose IP addresses change. Every peer endpoint must be statically configured. If you have ten devices and you want all-to-all connectivity, you need ten configuration files, each listing nine peers with their public keys, allowed IPs, and endpoints. Adding an eleventh device means updating all ten existing configurations. Key rotation means coordinating updates across all peers simultaneously. This is manageable at small scale; it becomes untenable fast.
The second problem is NAT traversal. WireGuard uses UDP exclusively. This is a deliberate choice — UDP has much lower latency than TCP for VPN tunneling because there is no kernel-level retransmission logic fighting with the application’s own transport protocol. But UDP and NAT are historically difficult. NAT (Network Address Translation) maintains a state table mapping internal IP:port pairs to external IP:port pairs. For outbound connections, NAT works fine — the client sends a packet, the NAT device records the mapping, and replies are correctly forwarded back. For inbound connections, there is no existing mapping, so the NAT device drops the packet.
WireGuard itself has no NAT traversal logic. The PersistentKeepalive option helps keep an existing NAT mapping alive, but only if the connection was initiated from behind the NAT. Two peers both behind NAT — a common situation for any two home users trying to connect — cannot establish a direct WireGuard connection without external assistance.
Tailscale’s Architecture: What It Adds on Top of WireGuard
Tailscale solves both of WireGuard’s limitations — key distribution and NAT traversal — by adding a control plane and a relay infrastructure on top of WireGuard’s data plane. Understanding the separation between these two layers is the most important thing to grasp about Tailscale’s trust model.
Control plane vs. data plane: The control plane is Tailscale’s coordination server (or Headscale, if you self-host). It handles device registration, public key distribution, IP address assignment, and policy (ACLs). When a new device joins your tailnet, it authenticates to the coordination server, which assigns it a 100.x.x.x address, records its public key, and distributes that key plus address mapping to all other devices in your tailnet. Devices periodically check in with the coordination server to get updated peer information. This is the only part of the system that involves Tailscale’s infrastructure for ongoing operation.
The data plane — the actual encrypted traffic between your devices — flows directly between nodes over WireGuard. Tailscale’s servers are not in the path for data. This is a critical design choice and the basis for Tailscale’s security guarantees: even if Tailscale’s coordination server were compromised or compelled to cooperate with an adversary, they could not decrypt traffic between your nodes.
NAT traversal: Tailscale implements an ICE-like hole-punching mechanism to establish direct connections through NAT. The process roughly works as follows. Both peers report their local network addresses and their observed external addresses (gathered from STUN servers) to the coordination server. The coordination server relays these address candidates to each peer. The peers then simultaneously send probe packets to each other’s addresses — this simultaneous sending is the “hole punch.” Many NAT types, including most residential routers using full-cone or address-restricted cone NAT, will allow a reply to pass through if an outbound packet from that address was recently seen. When both sides punch simultaneously, both see a reply, and a direct UDP path is established.
Symmetric NAT — common in some corporate environments and certain ISPs — assigns a different external port for each destination, making hole-punching unreliable. When direct connection fails, Tailscale falls back to DERP.
DERP — Designated Encrypted Relay for Packets: DERP servers are Tailscale’s relay infrastructure. They are geographically distributed and are used as a fallback when direct connections cannot be established. Crucially, DERP relays are not decryption points. Traffic relayed through DERP is still WireGuard-encrypted end-to-end. A DERP server sees only ciphertext — it cannot read the content of your traffic. Tailscale operates DERP servers in multiple regions; you can also run your own.
As of early 2026, Tailscale has introduced Peer Relays (generally available since February 2026) as a complement to DERP. Peer relays run on your own infrastructure — they are WireGuard-based relay nodes you operate within your tailnet, designed for high-throughput scenarios where you need lower latency than a Tailscale-operated DERP server can provide and want to keep traffic fully on your own hardware. Peer relays require Tailscale 1.86 or later.
NAT traversal and relay fallback:
[Laptop] [Home Server]
100.64.x.1 100.64.x.2
| |
[NAT/Router A] [NAT/Router B]
| |
|------- STUN: learn external addr -------->|
|<------ STUN: learn external addr ---------|
| |
| Coordination server exchanges |
| address candidates for both peers |
| |
|------- UDP hole punch attempt ----------->|
|<------ UDP hole punch attempt ------------|
| |
SUCCESS (most residential NAT types)
|<=========== Direct WireGuard ===========>>|
If hole punch fails (symmetric NAT, corporate firewall):
|----> DERP relay (ciphertext only) ------->|
|<---- DERP relay (ciphertext only) --------|
(Tailscale can see metadata; NOT content)
After reconnect or when path improves, Tailscale
continuously retries direct connection in background.
The tailscaled daemon: On Linux, Tailscale runs as tailscaled, a userspace service that manages the WireGuard keys, maintains the WireGuard interface (via wireguard-go or the kernel module), communicates with the coordination server, and handles DNS if MagicDNS is enabled. Configuration persists in a state directory (default /var/lib/tailscale/). The daemon exposes a local socket that the tailscale CLI uses to send commands.
The 100.64.0.0/10 address space: Tailscale assigns addresses from the CGNAT (Carrier-Grade NAT) range defined in RFC 6598. This range was standardized for use by ISPs deploying large-scale NAT but is otherwise non-routable on the public internet and unlikely to conflict with typical RFC 1918 private address ranges (10.x.x.x, 172.16-31.x.x, 192.168.x.x). Your tailnet IPs are stable — they don’t change when you move between networks. This is what makes them useful as stable identifiers.
What Tailscale the company can and cannot see:
This question deserves a direct answer rather than marketing language. The coordination server, operated by Tailscale, sees:
- The list of nodes in your tailnet and their 100.x.x.x IP assignments
- Every node’s WireGuard public key (by definition — it distributes them)
- The hostnames and metadata of your devices
- Your ACL policy file
- Connection metadata: which nodes are online, approximately when they last connected
- Your DERP relay usage patterns (which DERP region, not content)
Tailscale cannot see:
- The actual traffic between your nodes (WireGuard-encrypted, end-to-end)
- The content of any application data
- What services you’re running on your nodes (unless you tell them via node metadata)
This is a meaningful distinction. Tailscale’s threat model is similar to that of a DNS provider: they see metadata about your infrastructure, not the contents of your communications. For a homelab operator, this is an acceptable trade-off for most people. If your requirement is zero trust of any external party — including the control plane operator — that is the use case for Headscale, covered later.
Installation and Basic Setup
Linux installation is a single command followed by authentication:
|
|
The tailscale up command opens a URL in a browser (or prints one for headless systems) for OAuth login via Google, GitHub, Microsoft, or any configured OIDC provider. Once authenticated, the device appears in your admin console at login.tailscale.com/admin.
macOS, Windows, iOS, and Android all have app store clients. The macOS and Windows clients are full system integrations with a menu bar icon. The iOS and Android clients use the OS’s VPN framework. All use the same underlying WireGuard data plane.
As of mid-2026, the current stable Tailscale client version is in the 1.96.x series. The client updates approximately every four weeks on the stable track; a release-candidate track is available for those who want earlier access.
Essential diagnostic commands:
|
|
The tailscale ping output is particularly useful. It will tell you whether a connection is using a DERP relay and which region, or whether it has achieved a direct WireGuard path:
pong from homeserver (100.64.22.5) via DERP(nyc) in 45ms
pong from homeserver (100.64.22.5) via 203.0.113.45:41392 in 8ms
The second line shows a direct path established — the public endpoint and a sub-10ms round trip typical of a direct connection within the same geographic area.
Auth keys and device provisioning: The admin console lets you generate auth keys with varying properties:
| Key Type | Description |
|---|---|
| One-time | Single device registration, expires after use |
| Reusable | Multiple devices can use the same key |
| Pre-authorized | Device joins without requiring admin approval |
| Tagged | Device joins with a specific tag: applied |
| Ephemeral | Device is automatically removed when it goes offline |
Ephemeral keys are the right choice for CI/CD runners, containers, and any workload that should not accumulate as stale entries in your tailnet. Tagged + pre-authorized keys are ideal for automated infrastructure — a cloud-init script or Ansible role can bring up a new VM and have it fully joined to your tailnet without human interaction.
Subnet Routers
Not every device in your homelab can run Tailscale. Printers, NAS boxes with locked-down firmware, managed switches, smart home hubs, older embedded devices, IP cameras — these exist on your LAN but have no mechanism for installing a VPN client. Subnet routers solve this cleanly.
A subnet router is a Tailscale node that advertises one or more of your LAN subnets to the rest of your tailnet. Packets destined for 192.168.1.0/24 get routed through the subnet router and emerge on your LAN. From the perspective of the device you’re reaching, traffic looks like it’s coming from the subnet router’s LAN IP — no Tailscale configuration required on the target.
Subnet Router Architecture:
[Laptop at coffee shop]
Tailscale IP: 100.64.10.5
|
| WireGuard tunnel (direct or via DERP)
|
[Proxmox VM / Raspberry Pi] <-- Subnet Router
Tailscale IP: 100.64.10.1
LAN IP: 192.168.1.50
|
| Normal LAN routing
|
+----+----------+----------+----------+
| | | |
[NAS] [Printer] [IP Camera] [Old NVR]
192.168.1.10 192.168.1.20 192.168.1.30 192.168.1.40
(no Tailscale required on any of these)
Setting up a subnet router:
|
|
After running this command, the routes appear as “pending” in the admin console. You must approve them — either manually by clicking in the console, or automatically via autoApprovers in your ACL policy file (covered in the ACL section).
On every client that should be able to use the subnet routes:
|
|
This flag is not set by default for a deliberate reason: accepting routes is a meaningful change to your machine’s routing table, and a device should opt in explicitly. On a managed fleet you would set this via ACL tags and a configuration management system.
High-availability subnet routing works by having two separate nodes advertise the same subnet. Both must be approved. Tailscale automatically selects the best path — if the primary subnet router is offline or unreachable, traffic is routed through the secondary. This requires no additional configuration beyond both nodes advertising the same prefix.
|
|
A practical note on firewall rules: The subnet router’s host firewall needs to allow forwarded traffic. On systems using nftables or iptables with a default DROP policy for forwarding, you will need to explicitly allow forwarding between the Tailscale interface and your LAN interface:
|
|
Exit Nodes
Exit nodes extend the subnet router concept to cover all internet-bound traffic. When you configure a Tailscale node as an exit node and route through it, your internet traffic appears to originate from that node’s public IP rather than wherever you physically are.
The use cases for homelab operators are practical: using your home router or a trusted VPS as an exit node on untrusted public WiFi, routing around ISP-level filtering, and having your traffic appear to come from a stable known IP for services that block residential IP ranges (certain APIs, databases, streaming content for testing, etc.).
|
|
The difference between an exit node and a traditional VPN is architectural. A traditional VPN requires dedicated server infrastructure, a static IP, and active management of the VPN service. An exit node is just any Tailscale peer that has been designated as an exit — it can be your home Raspberry Pi, your Proxmox cluster’s gateway VM, or a $5/month VPS. No VPN server software to manage, no certificates to rotate, no separate tunnel configuration. It’s the same WireGuard mesh you already have, with one additional routing flag.
Note that exit node traffic routes through Tailscale’s coordination server for control plane purposes but the data plane still follows the WireGuard paths — direct to the exit node if a direct connection is available, through DERP if not. In both cases the traffic between your device and the exit node is encrypted.
MagicDNS and Split DNS
DNS is where homelab Tailscale setups either work beautifully or become a constant source of friction. Getting it right is worth spending time on.
MagicDNS is Tailscale’s automatic DNS feature. When enabled in the admin console (DNS tab), every node in your tailnet gets a DNS name in the format <hostname>.<tailnet-name>.ts.net. The tailscaled daemon runs a local DNS resolver (listening on 100.100.100.100, a special Tailscale-controlled address) that handles resolution of these names. Queries for *.ts.net return the appropriate 100.x.x.x Tailscale IP.
This means you can reach homeserver.my-tailnet.ts.net from any device in your tailnet, anywhere in the world, without knowing the 100.x.x.x IP. It also works for services: if your Proxmox node is named pve1, you reach it at pve1.my-tailnet.ts.net — Tailscale handles the DNS translation.
Split DNS is the more powerful feature for homelabbers. It lets you point specific DNS domains at your own resolver — typically a Pi-hole, AdGuard Home, or an authoritative DNS server running internally — while everything else resolves normally.
Split DNS flow:
[Tailscale Client]
|
| DNS query for nas.home.arpa
v
[100.100.100.100 - tailscaled local resolver]
|
| Domain "home.arpa" matches split DNS rule
| Route to Pi-hole at 100.64.10.3
v
[Pi-hole / Internal DNS at 100.64.10.3]
|
| Returns 192.168.1.10 (local LAN IP)
v
[Client has 192.168.1.10]
|
| 192.168.1.0/24 matches advertised subnet route
| Route through subnet router
v
[NAS at 192.168.1.10] <-- reached by name, from anywhere
For everything else (google.com, github.com, etc.):
|
| No split DNS match
v
[Normal upstream resolvers]
Configuration is done in the admin console under DNS > Nameservers. You add a nameserver IP (your internal DNS server’s Tailscale IP) and specify which domains it should handle. The nameserver must be reachable via the tailnet — either because it has Tailscale installed or because it’s accessible via a subnet router.
A typical homelab split DNS setup might look like:
| Domain | Resolver | Purpose |
|---|---|---|
home.arpa |
100.64.10.3 (Pi-hole) |
All internal hostnames |
internal.corp |
100.64.10.3 |
Internal services |
ts.net |
Tailscale-handled | MagicDNS (automatic) |
| Everything else | Default upstream | Public internet |
Override local DNS is an option that replaces your device’s system DNS with Tailscale’s resolver entirely. This is useful when you want Pi-hole ad blocking to apply to all your traffic regardless of which network you’re on. The caveat is that it can break captive portals — the landing pages on hotel and airport WiFi that require you to accept terms before Internet access is granted. Those portals depend on DNS hijacking, which conflicts with Tailscale’s DNS override. Keep this in mind when troubleshooting “my VPN works but I can’t connect to hotel WiFi.”
|
|
ACL Policy Files
Tailscale’s default access control model is permissive: every node in your tailnet can reach every other node on any port. For a single-person homelab where you own every device, this is probably fine. For tailnets that include family members’ phones, work laptops that Tailscale installed on, guest devices, or CI/CD systems, the default is too open.
ACL policy files are Tailscale’s answer to zero-trust network access. They are written in HuJSON (JSON with comments and trailing commas allowed) and define exactly which sources can reach which destinations on which ports. The policy file lives in your admin console but can also be managed via Tailscale’s API for GitOps workflows.
Tags are the primary organizational primitive. Instead of writing rules that reference individual email addresses or IPs (which change), you tag devices and write rules against tags. A server gets tag:server, your personal devices get tag:client, CI runners get tag:ci. Tags are applied when generating auth keys or can be assigned from the admin console.
Groups let you organize users. group:admins might contain the email addresses of people who should have full access, while group:family contains accounts for household members who should reach only media services.
Here is a complete, realistic ACL policy file for a homelab:
|
|
The tests block is executable in the admin console — Tailscale evaluates your policy against the test cases and tells you whether the expected allow/deny decisions match. This is invaluable before pushing a policy change that could lock yourself out.
GitOps for ACL management: Tailscale exposes an API endpoint for reading and writing the policy file. A practical pattern is to keep the policy file in a Git repository, run a CI pipeline that validates it with the Tailscale API’s --dry-run equivalent, and then apply it on merge to main. This gives you version history, review workflow, and rollback capability for network policy changes.
|
|
Headscale: Self-Hosted Control Plane
Headscale is an open-source reimplementation of the Tailscale coordination server. It gives you full ownership of the control plane — you run the server, you hold the data, and you owe nothing to Tailscale’s SaaS infrastructure.
The current stable release as of this writing is v0.28.0 (February 2026), with a v0.29.0 beta available that adds SSH check actions, policy testing as a first-class feature, and full grants support for application-level capabilities. The minimum supported Tailscale client version for Headscale 0.28+ is v1.80.0.
Headscale connects to official, unmodified Tailscale clients. You do not need a forked or special client — the same package you would install for Tailscale SaaS works with Headscale; you just point it at your server.
Why you might want Headscale:
- Regulatory or compliance requirements that prohibit sending device metadata to a third-party SaaS
- Airgapped environments where nodes should never reach Tailscale’s servers
- Distrust of any external coordination server, even one that can’t read your traffic
- Organizations that need full audit control over tailnet join/leave events
- No Tailscale account required — useful for scenarios where Google/GitHub/Microsoft SSO is not acceptable
What you give up by running Headscale:
- The Tailscale admin console UI (Headscale has a basic headscale-ui third-party frontend)
- Tailscale SSH session recording
- Tailscale Funnel (exposing services to the public internet via Tailscale’s infrastructure)
- Some newer ACL features that Headscale tracks with a lag of a quarter or two
- Tailscale’s DERP infrastructure (you must run your own DERP servers or lose relay fallback)
- Automatic client updates and the Tailscale support relationship
Docker Compose installation:
|
|
Minimal config/config.yaml:
|
|
Basic Headscale operations:
|
|
Connecting a Tailscale client to Headscale:
|
|
The coordination server handshake is redirected to your Headscale instance. The client’s WireGuard key exchange, IP assignment, and peer discovery all flow through Headscale rather than Tailscale’s servers.
Comparison: Tailscale SaaS vs Headscale vs Plain WireGuard
| Feature | Tailscale SaaS | Headscale | Plain WireGuard |
|---|---|---|---|
| Control plane | Tailscale-operated | Self-hosted | Manual (you manage all keys) |
| Setup complexity | Very low | Medium | High |
| Peer discovery | Automatic | Automatic (via Headscale) | Manual per-peer config |
| NAT traversal | Yes (DERP fallback) | Yes (requires DERP) | No (manual PersistentKeepalive) |
| MagicDNS | Yes | Yes (basic) | No |
| ACL / policy | Yes (full feature set) | Yes (trailing feature parity) | Via AllowedIPs only |
| Tailscale SSH | Yes | No | N/A |
| Funnel | Yes | No | No |
| Subnet routers | Yes | Yes | Manual routing config |
| Exit nodes | Yes | Yes | Manual default route config |
| Peer Relays | Yes | No | N/A |
| Admin UI | Full web console | Limited (third-party) | wg show / wg-quick |
| Max free devices | 100 (Personal plan) | Unlimited | Unlimited |
| Data sent to vendor | Metadata (keys, IPs, policy) | None | None |
| Traffic privacy | E2E encrypted | E2E encrypted | E2E encrypted |
| Your availability SLA | Tailscale’s uptime | Yours | Yours (no control plane) |
| DERP relay fallback | Tailscale-operated DERPs | Self-hosted or Tailscale DERPs | None |
The honest recommendation: use Tailscale SaaS for most homelabs. The free Personal plan supports 100 devices, which is more than enough for any homelab short of a medium-sized datacenter. The metadata exposure is acceptable for personal use. The operational overhead you avoid by not running Headscale is real — you have no coordination server to update, monitor, back up, or troubleshoot. Headscale is the right call when you have specific compliance requirements, are building something that must not depend on any external SaaS, or have an airgapped environment where Tailscale’s servers are not reachable at all.
Plain WireGuard remains the right choice when you have a small, static set of peers and want zero external dependencies — a site-to-site tunnel between two servers you control is a case where setting up a full tailnet is overkill.
Practical Homelab Patterns
Pattern 1: Laptop anywhere, reach any LAN device. Install Tailscale on your laptop and on one Linux machine on your home LAN (a Proxmox VM, a Raspberry Pi, an old mini PC). Configure the Linux machine as a subnet router advertising 192.168.1.0/24. Run tailscale up --accept-routes on your laptop. You now have complete access to every device on your LAN from anywhere — including your NAS, printer, smart home hub, and anything else that has a LAN IP. No port forwarding. No exposed services.
Pattern 2: Proxmox cluster + PBS via Tailscale. Install Tailscale on each Proxmox host and on Proxmox Backup Server. Your Proxmox nodes can reach PBS for backups without any external network path. You can access the PBS and Proxmox web UIs from your laptop via their Tailscale IPs. VM replication between nodes traverses the Tailscale mesh. Add ACL rules so that Proxmox hosts can reach PBS on port 8007 and the backup storage ports, but external devices cannot reach the Proxmox nodes directly.
Pattern 3: VPS exit node. Spin up a minimal VPS (Hetzner, Vultr, DigitalOcean) with a static IP. Install Tailscale, advertise it as an exit node. When traveling or on a network you do not trust, route through your VPS. Your traffic appears to come from the VPS IP. For services that block residential IP ranges — certain SaaS APIs, some media services, authentication flows with IP reputation checks — routing through a datacenter IP solves the problem without buying a dedicated VPN subscription.
Pattern 4: Pi-hole + split DNS for all clients. Run Pi-hole on a machine that has Tailscale installed. Configure split DNS in the Tailscale admin console to route queries for your internal domain to Pi-hole. Enable “Override local DNS” if you want Pi-hole’s ad blocking to apply to all traffic from all tailnet clients. Your phone gets ad blocking at the DNS layer even on cellular — the DNS queries tunnel through Tailscale to your home Pi-hole, which filters ads before resolving. The combined benefit is internal name resolution and network-level ad blocking from any location.
Pattern 5: CI/CD runners accessing internal services. GitHub Actions runners (or Gitea Actions, Woodpecker CI, etc.) need to reach internal resources — a private container registry, an internal Maven proxy, a staging database, a Kubernetes cluster. Install Tailscale in your CI workflow using the official Tailscale GitHub Action, authenticate with an ephemeral tagged key. The runner joins your tailnet for the duration of the job, accesses internal resources directly, and the ephemeral node is automatically removed when the runner disconnects. No inbound ports on your internal services; no special network configuration on the CI platform.
|
|
tailscale serve — private TLS without certificates. The serve command lets you expose a local service on your tailnet with automatic TLS, routed through your Tailscale hostname. No certificate management, no reverse proxy configuration, no open ports on the host firewall. The TLS certificate is issued by Tailscale’s own CA, trusted by other tailnet members.
|
|
tailscale funnel — careful public exposure. Funnel extends serve to the public internet — your service becomes accessible at https://hostname.your-tailnet.ts.net to anyone on the internet. This runs through Tailscale’s infrastructure, so it has bandwidth implications and the traffic is visible to Tailscale (as a relay, not encrypted end-to-end for the public HTTPS portion). Use it for webhooks, temporary demos, development testing. Do not use it for sensitive internal services or as a long-term production exposure mechanism — that is not its design intent.
|
|
Monitoring and observability. A few things to track in a mature homelab Tailscale setup:
|
|
If you are running Peer Relays for high-throughput internal routing, the metrics tailscaled_peer_relay_forwarded_packets_total and tailscaled_peer_relay_forwarded_bytes_total are available for scraping with Prometheus and visualization in Grafana.
Closing Thoughts
Tailscale is one of the few pieces of infrastructure that genuinely delivers on its promise without hidden complexity. The WireGuard foundation is solid. The control plane adds exactly the automation that WireGuard deliberately left out. The result is a mesh VPN that scales from one device to a hundred without any per-peer configuration work.
For a homelab operator, the right path is clear: close your exposed ports, stand up a subnet router, configure split DNS against your internal resolver, and write a modest ACL policy that reflects who actually owns what in your infrastructure. The operational savings are permanent — you stop playing defense against the internet and start building things instead.
The trust question is the only nuanced decision. Tailscale’s architecture means the company cannot read your traffic, but they do hold metadata about your infrastructure. For personal use, that trade-off is reasonable. For anything where that metadata is sensitive — enterprise environments, regulated industries, or high-threat-model personal setups — Headscale puts the control plane in your hands at the cost of running and maintaining it yourself.
Whichever direction you choose, the WireGuard data plane beneath everything is the same. Your traffic is encrypted. Your devices talk directly. The ports are closed.
Comments