The Complete Tailscale Guide:
Setup, Deployment, and Hardening
If you've ever wrestled with port forwarding, dynamic DNS, or a clunky traditional VPN just to reach a device at home or a server at work, Tailscale is about to change your life. It creates a private mesh network (called a tailnet) across all your devices, wherever they are, with no open ports and no complex firewall rules. It just works.
This guide covers everything: creating and securing your account, installing Tailscale on Windows, Linux, virtual machines, and Docker containers, and hardening your tailnet so it's both maximally secure and actually pleasant to use.
What Is Tailscale (Why Should You Care)?
Tailscale is built on WireGuard®; a state-of-the-art open-source VPN protocol known for its security and speed, and layers a zero-trust architecture with end-to-end encryption on top of it. Unlike traditional VPNs that route all traffic through a central gateway (creating a bottleneck when many users are connected), Tailscale handles the heavy lifting of NAT traversal to create a peer-to-peer mesh network where nodes connect directly to each other.
The result: ultra-low latency, instant setup, and a network that scales from a personal homelab to a multi-user enterprise without altering your physical architecture.
Free Tier (Personal Plan) Highlights:
Up to 100 devices and 3 users
MagicDNS: Human-readable hostnames for all your devices
Subnet Routing & Exit Nodes: Access legacy LANs and route internet traffic securely
Tailscale SSH: Secure, keyless terminal access managed entirely by identity
Part 1: Creating Your Tailscale Account
Step 1: Sign Up
Go to tailscale.com and click Get Started. You'll authenticate using an existing identity provider (IdP); Google, Microsoft, GitHub, Apple, or a custom OIDC/SAML provider. Tailscale never stores your password directly; it entirely delegates authentication to your chosen provider.
Tip: Use a Google Workspace or Microsoft 365 tenant if you are deploying for a business. This allows you to naturally onboard teammates from your organization using identity-based access control without manual user creation.
Step 2: Navigate the Admin Console
After logging in, you land at the Tailscale Admin Console. This is your central control plane.
Machines: View every connected node, its Tailscale IP, and connection status.
Access Controls: Your central Access Control List (ACL) policy file.
DNS: Toggle MagicDNS, set split-DNS nameservers, or manage global search domains.
Settings: Generate authentication keys, manage webhooks, set device expiry rules, and toggle advanced security features like Tailnet Lock.
Part 2: Installing Tailscale on Windows
Download the official installer from
.tailscale.com/download/windows Run the installer. The background Windows service is installed and set to run automatically at boot.
Click the Tailscale icon in your system tray and select Log in....
Your default browser will prompt you to complete authentication via your identity provider.
Once authenticated, your machine receives a stable Tailscale IP inside the 100.64.0.0/10 CGNAT address range.
Verify via PowerShell:
tailscale status
tailscale ping <remote-device-hostname-or-IP>
Key Windows Features:
Unattended Mode: Allows Tailscale to stay connected even when you log out of your Windows user session (essential for local servers/media boxes).
Exit Node Usage: Right-click tray icon -> Exit Node -> Select a node to securely route all public internet traffic through it.
Part 3: Installing Tailscale on Linux
Tailscale provides automated and manual repository management across all major distributions. The fastest cross-distro deployment uses the official bootstrap script:
curl -fsSL https://tailscale.com/install.sh | sh
For production systems where pinning repositories or managing supply-chain risks matters, use the manual package manager setups below.
Debian / Ubuntu
# Create the keyrings directory if it doesn't exist
sudo mkdir -p /usr/share/keyrings
# Fetch the armored signing key safely
curl -fsSL https://pkgs.tailscale.com/stable/ubuntu/jammy.noarmor.gpg | sudo tee /usr/share/keyrings/tailscale-archive-keyring.gpg >/dev/null
# Add the repository source pointing explicitly to the armored key
curl -fsSL https://pkgs.tailscale.com/stable/ubuntu/jammy.tailscale-keyring.list | sudo tee /etc/apt/sources.list.d/tailscale.list
# Install the client
sudo apt update && sudo apt install tailscale -y
RHEL / Rocky Linux / AlmaLinux / Fedora
sudo dnf config-manager --add-repo https://pkgs.tailscale.com/stable/rhel/9/tailscale.repo
sudo dnf install tailscale -y
Initial Configuration & Systemd Activation
# Enable and immediately start the background daemon
sudo systemctl enable --now tailscaled
# Bring the interface up and execute the interactive OAuth CLI login flow
sudo tailscale up
Crucial 'tailscale up' Flags Reference
--advertise-exit-node: Declares this machine as a secure proxy gateway to the public internet.--advertise-routes=192.168.1.0/24: Turns this machine into a subnet router to expose an un-agentable physical LAN segment.--accept-routes: Commands this Linux node to honor subnet routes published by other nodes on the tailnet.--ssh: Hands over host SSH execution directly to Tailscale's identity-based cryptographic layer.--reset: Resets all previously set flags back to default configurations before applying new arguments.
Part 4: Virtual Machines & Hypervisors
Tailscale treats Virtual Machines exactly like bare-metal endpoints. Giving each VM its own distinct 100.x.x.x address is the ultimate architecture for avoiding network collisions across development environments.
Proxmox VE Hosts & LXC Containers
Running Tailscale directly on the Proxmox host provides out-of-band management to the web GUI without exposing port 8006 to the WAN.
When running inside Proxmox LXC Containers, Tailscale needs direct access to the kernel's virtual network interface driver (/dev/net/tun).
Navigate to the Proxmox Web GUI -> Select your LXC Container -> Options -> Features.
Check the TUN box.
If using an unprivileged container, also check the Nesting box to allow proper container environment containment.
Deploying a High-Availability Subnet Router
If you want to access legacy devices (IoT, printers, industrial switches, or firewall web interfaces like OPNsense) that cannot run a local Tailscale client, configure a dedicated subnet router.
Critical Requirement: Linux will drop routed packets by default. You must enable IP forwarding on the host OS before advertising the route.
Configure sysctl (Enable Linux IP Forwarding): Edit
/etc/sysctl.confand uncomment or addnet.ipv4.ip_forward = 1(andnet.ipv6.conf.all.forwarding = 1for IPv6). Apply immediately withsudo sysctl -p.Advertise the Local LAN Range: Run
sudo tailscale up --advertise-routes=192.168.10.0/24using your exact physical network CIDR block.Approve the CIDR Routes: Go to the Tailscale Admin Console -> Machines. Locate your router node, click the menu, select Edit route settings, and explicitly toggle on the checkbox next to the advertised subnet.
Part 5: Docker Container Networks
Placing Docker workloads on Tailscale completely mitigates the security risk of dangling exposed ports on public cloud instances.
Option A: The Sidecar Design Pattern (Recommended)
By leveraging Docker's native network namespace sharing capabilities, you can place an application directly behind Tailscale. The application behaves as though it is running on localhost inside the Tailscale container.
docker-compose.yml:
version: "3.9"
services:
ts-sidecar:
image: tailscale/tailscale:latest
container_name: ts-nginx-sidecar
hostname: secure-web-app
environment:
- TS_AUTHKEY=tskey-auth-XXXX # Ephemeral, tagged pre-auth key
- TS_EXTRA_ARGS=--advertise-tags=tag:container
- TS_STATE_DIR=/var/lib/tailscale
- TS_USERSPACE=false # Set to false to leverage host kernel networking via dev/net/tun
volumes:
- ts-state:/var/lib/tailscale
- /dev/net/tun:/dev/net/tun
cap_add:
- NET_ADMIN
- SYS_MODULE
restart: unless-stopped
web-app:
image: nginx:alpine
network_mode: "service:ts-sidecar" # Share the tailscale container's network namespace
depends_on:
- ts-sidecar
restart: unless-stopped
volumes:
ts-state:
Option B: Standalone Bridge Subnet Router
If you want to map an entire isolated internal Docker overlay network to your Tailscale environment without managing individual sidecars:
version: "3.9"
services:
ts-docker-router:
image: tailscale/tailscale:latest
container_name: ts-bridge-router
hostname: prod-docker-subnet
environment:
- TS_AUTHKEY=tskey-auth-XXXX
- TS_ROUTES=172.20.0.0/16 # Custom Docker bridge network range
- TS_STATE_DIR=/var/lib/tailscale
volumes:
- ts-router-state:/var/lib/tailscale
- /dev/net/tun:/dev/net/tun
cap_add:
- NET_ADMIN
networks:
- app_internal_network
restart: unless-stopped
networks:
app_internal_network:
ipam:
config:
- subnet: 172.20.0.0/16
volumes:
ts-router-state:
Production Unattended Authentication Keys
For containers and automated deployments, you don't want to manually authenticate in a browser. Navigate to Settings -> Keys and generate a scoped Auth Key:
Check Reusable if deploying multiple containers from the same template.
Check Ephemeral so the node is auto-removed from the admin console when the container is destroyed.
Add tags (e.g.,
tag:container) to apply zero-trust ACL permissions automatically.
Store the key in a .env file or secrets manager; never hardcode it in your compose files.
Part 6: Hardening and Zero-Trust Architecture
Tailscale's default out-of-the-box configuration allows complete connectivity between all connected nodes. To implement a true zero-trust stance, you must restrict these permissions:
6.1 Account-Level Security
Enforce MFA on Your Identity Provider: Because your Tailscale security topology is linked to your primary IdP, enforce hardware security keys (like YubiKeys) on your primary account.
Set a Passkey for Tailscale Itself: Proactively set up an admin user that can log in with a passkey. This mitigates the risk of a total tailnet lockout if your SSO provider experiences an outage.
6.2 Device Management
Set Device Expiry: In Settings -> Expiry, enable device key expiry. 90 days is a sensible default. This ensures a stolen or forgotten device can't maintain access indefinitely.
Enable Tailscale SSH: Enable it on Linux nodes. Then, grant specific users SSH access to specific machines via your ACL, entirely eliminating the need to manage authorized_keys across your fleet.
6.3 Access Control Policies (ACLs): The Most Important Step
Replace the default permit-all ACL with explicit port-specific rules, add deny tests that block ACL changes from accidentally exposing production systems, and map your permissions to tags.
Here's a practical ACL for a homelab or small business with distinct zones:
{
"tagOwners": {
"tag:server": ["autogroup:admin"],
"tag:container": ["autogroup:admin"],
"tag:personal": ["autogroup:admin"]
},
"acls": [
// Admins can reach everything
{
"action": "accept",
"src": ["autogroup:admin"],
"dst": ["*:*"]
},
// Personal devices can reach servers on common web and SSH ports
{
"action": "accept",
"src": ["tag:personal"],
"dst": ["tag:server:22,80,443,8080,8443"]
},
// Containers are strictly sandboxed to communicate only amongst themselves
{
"action": "accept",
"src": ["tag:container"],
"dst": ["tag:container:*"]
}
],
"tests": [
// CI/CD Assertion: Verify a personal device CAN reach a server on 443
{
"src": "tag:personal",
"accept": ["tag:server:443"]
},
// CI/CD Assertion: Verify a container CANNOT reach a personal device's SSH port
{
"src": "tag:container",
"deny": ["tag:personal:22"]
}
],
"ssh": [
{
"action": "accept",
"src": ["autogroup:admin"],
"dst": ["tag:server"],
"users": ["autogroup:nonroot"]
}
]
}
6.4 Tailnet Lock (Advanced)
Tailnet Lock lets you control which nodes are signed and verified by trusted nodes in your tailnet. This means you don't need to trust the Tailscale coordination server for distributing public node keys. Enable it in the admin console under Settings -> Tailnet Lock to ensure that a compromise of external infrastructure cannot add unauthorized nodes to your network.
Part 7: Making It Easy to Use
Security theater is useless if nobody uses the tool correctly. Here's how to make Tailscale frictionless.
Enable MagicDNS
In the admin console under DNS -> MagicDNS, turn this on. Now instead of an IP address, you just use my-nas or secure-web-app from any Tailscale-connected device.
Set a Custom DNS Suffix
Under DNS -> Nameservers, you can set a tailnet-wide DNS suffix like home.yourname.com and point it at an internal DNS server. Your devices then resolve as myserver.home.yourname.com from anywhere.
Use Exit Nodes Strategically
Set up a home or cloud server as an exit node, approve it in the console, and use it from your phone or laptop when on untrusted Wi-Fi. This routes all internet traffic through your trusted node.
Share Specific Nodes with Others
You can share a single node with someone outside your tailnet without giving them access to your whole network. Machines -> [select machine] -> Share sends them an invite restricted solely to that host.
Conclusion
Tailscale removes the single biggest barrier to self-hosting and remote access: the networking layer. Once your devices are on the tailnet, you spend your time actually using your infrastructure instead of fighting with firewall rules and VPN configurations.
The key takeaways:
Start simple. Install, log in, and you're on the network.
Enable Linux IP Forwarding anytime you deploy a subnet router.
Add ACLs early. The default allow-all policy is fine for day one, but lock it down before you add more devices.
Use tags and ephemeral auth keys for any automated deployment (Docker, Proxmox templates).
Enable MagicDNS immediately! It makes everything far more pleasant.
If you're running a homelab or managing IT for a small business in the Pacific Northwest, feel free to reach out! I'm happy to help design and deploy a Tailscale setup that fits your environment.
Created & Maintained by Pacific Northwest Computers
📞 Pacific Northwest Computers offers Remote & Onsite Support Across:
SW Washington including Vancouver WA, Battle Ground WA, Camas WA, Washougal WA, Longview WA, Kelso WA, and Portland OR


No comments:
Post a Comment