Thursday, May 28, 2026

Complete Tailscale Guide; Setup, Deployment, and Hardening

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 tailnetacross 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

  1. Download the official installer from tailscale.com/download/windows.

  2. Run the installer. The background Windows service is installed and set to run automatically at boot.

  3. Click the Tailscale icon in your system tray and select Log in....

  4. Your default browser will prompt you to complete authentication via your identity provider.

  5. Once authenticated, your machine receives a stable Tailscale IP inside the 100.64.0.0/10 CGNAT address range.

Verify via PowerShell:

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:

Bash
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

Bash
# 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

Bash
sudo dnf config-manager --add-repo https://pkgs.tailscale.com/stable/rhel/9/tailscale.repo
sudo dnf install tailscale -y

Initial Configuration & Systemd Activation

Bash
# 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).

  1. Navigate to the Proxmox Web GUI -> Select your LXC Container -> Options -> Features.

  2. Check the TUN box.

  3. 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.

  1. Configure sysctl (Enable Linux IP Forwarding): Edit /etc/sysctl.conf and uncomment or add net.ipv4.ip_forward = 1 (and net.ipv6.conf.all.forwarding = 1 for IPv6). Apply immediately with sudo sysctl -p.

  2. Advertise the Local LAN Range: Run sudo tailscale up --advertise-routes=192.168.10.0/24 using your exact physical network CIDR block.

  3. 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:

YAML
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:

YAML
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:

  1. Check Reusable if deploying multiple containers from the same template.

  2. Check Ephemeral so the node is auto-removed from the admin console when the container is destroyed.

  3. 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:

JSON
{
  "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

Jon Pienkowski runs Pacific Northwest Computers, providing IT services, networking, and cybersecurity support to SW Washington and the Portland metro area.



📞 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