Skip to main content

Tailscale Practical Guide

Tailscale is a modern VPN solution built on WireGuard that creates secure, encrypted mesh networks with zero configuration. It simplifies networking by treating the entire internet as hostile and creating a private overlay network that's easy to manage and scale. This guide serves as a comprehensive quick reference for administrators, developers, and users who need to quickly deploy, configure, and troubleshoot Tailscale networks.

When to use this guide
  • Setting up Tailscale for the first time across multiple devices
  • Configuring advanced networking features like subnet routers and exit nodes
  • Implementing secure remote access for teams and infrastructure
  • Troubleshooting connectivity and performance issues
  • Integrating Tailscale with existing infrastructure and workflows
Who this guide is for
  • Network administrators and IT professionals
  • DevOps engineers and system administrators
  • Security professionals implementing zero-trust networks
  • Remote teams needing secure connectivity
  • Developers working with distributed systems
  • Anyone seeking to replace traditional VPNs with modern mesh networking

Installation & Setup

Quick Installation Commands

# Ubuntu/Debian
curl -fsSL https://tailscale.com/install.sh | sh

# CentOS/RHEL/Fedora
curl -fsSL https://tailscale.com/install.sh | sh

# Arch Linux
sudo pacman -S tailscale

# macOS (Homebrew)
brew install tailscale

# Windows (Chocolatey)
choco install tailscale

# Direct Go installation (any platform)
go install tailscale.com/cmd/tailscale{,d}

Platform-Specific Installation

# Ubuntu/Debian with APT
curl -fsSL https://pkgs.tailscale.com/stable/ubuntu/jammy.noarmor.gpg | sudo tee /usr/share/keyrings/tailscale-archive-keyring.gpg >/dev/null
curl -fsSL https://pkgs.tailscale.com/stable/ubuntu/jammy.tailscale-keyring.list | sudo tee /etc/apt/sources.list.d/tailscale.list
sudo apt update && sudo apt install tailscale

# CentOS/RHEL with YUM
sudo yum install yum-utils
sudo yum-config-manager --add-repo https://pkgs.tailscale.com/stable/centos/8/tailscale.repo
sudo yum install tailscale

# Enable and start daemon
sudo systemctl enable --now tailscaled

First Time Setup

Basic Connection

# Connect to Tailscale (opens browser for authentication)
sudo tailscale up

# Connect with specific options
sudo tailscale up --accept-routes --accept-dns

# Connect with hostname
sudo tailscale up --hostname=my-server

# Connect without browser (get URL for manual auth)
sudo tailscale up --qr

Authentication & Auth Keys

# Create auth key (from admin console)
# Use pre-auth key for unattended setup
sudo tailscale up --authkey=tskey-auth-xxxxxx

# One-time auth key for ephemeral nodes
sudo tailscale up --authkey=tskey-auth-xxxxxx --ephemeral

# Tagged node authentication
sudo tailscale up --authkey=tskey-auth-xxxxxx --advertise-tags=tag:server

Basic Operations

Connection Management

# Connect to Tailscale
sudo tailscale up

# Disconnect (but keep daemon running)
sudo tailscale down

# Check connection status
tailscale status

# Detailed status with IPs and last seen
tailscale status --peers

# JSON output for scripting
tailscale status --json

# Show current device IP
tailscale ip

# Show specific IP version
tailscale ip -4 # IPv4 only
tailscale ip -6 # IPv6 only

Network Information

# Check network connectivity
tailscale netcheck

# Ping another device
tailscale ping hostname-or-ip

# Test SSH connectivity
tailscale nc hostname 22

# DNS query through Tailscale
tailscale dns status
tailscale dns query hostname.example.com

Advanced Configuration

Exit Nodes

# Enable as exit node (route all internet traffic)
sudo tailscale up --advertise-exit-node

# Enable IP forwarding for exit node (Linux)
echo 'net.ipv4.ip_forward = 1' | sudo tee -a /etc/sysctl.d/99-tailscale.conf
echo 'net.ipv6.conf.all.forwarding = 1' | sudo tee -a /etc/sysctl.d/99-tailscale.conf
sudo sysctl -p /etc/sysctl.d/99-tailscale.conf

# Use another device as exit node
sudo tailscale up --exit-node=exit-server
sudo tailscale up --exit-node=100.64.0.1

# Allow local network access while using exit node
sudo tailscale up --exit-node=exit-server --exit-node-allow-lan-access

# Disable exit node
sudo tailscale up --exit-node=

# List available exit nodes
tailscale exit-node list

Subnet Routers

# Advertise subnet routes
sudo tailscale up --advertise-routes=10.0.0.0/24,192.168.1.0/24

# Single subnet
sudo tailscale up --advertise-routes=192.168.1.0/24

# Multiple subnets
sudo tailscale up --advertise-routes=10.0.0.0/8,172.16.0.0/12,192.168.0.0/16

# Accept routes from other subnet routers
sudo tailscale up --accept-routes

# Enable IP forwarding for subnet router (Linux)
echo 'net.ipv4.ip_forward = 1' | sudo tee -a /etc/sysctl.conf
echo 'net.ipv6.conf.all.forwarding = 1' | sudo tee -a /etc/sysctl.conf
sudo sysctl -p

# Check if routes are approved (admin console required)
tailscale status | grep "offers"

SSH Configuration

# Enable Tailscale SSH server
sudo tailscale up --ssh

# Connect via Tailscale SSH
tailscale ssh user@hostname

# SSH with port forwarding
tailscale ssh -L 8080:localhost:80 user@hostname

# Check SSH host keys
tailscale ssh --check-host-keys user@hostname

# Use traditional SSH through Tailscale (userspace networking)
ssh -o ProxyCommand='tailscale nc %h %p' user@hostname.tailnet.ts.net

Service Sharing

Tailscale Serve (Internal Sharing)

# Share a local web server within tailnet
tailscale serve 3000

# Share with custom path
tailscale serve --https=443 --set-path=/app localhost:3000

# Share static files
tailscale serve --https=443 /home/user/public_html

# Share text content
tailscale serve --https=443 text:"Hello from Tailscale"

# TCP forwarding
tailscale serve --tcp=2222 localhost:22

# TLS-terminated TCP
tailscale serve --tls-terminated-tcp=443 localhost:8080

# View serve status
tailscale serve status

# Turn off specific serve
tailscale serve --https=443 --set-path=/app off

Tailscale Funnel (Public Sharing)

# Share publicly on the internet
tailscale funnel 3000

# Share with specific port
tailscale funnel --https=443 localhost:3000

# Share files publicly
tailscale funnel --https=443 /home/user/website

# TCP funnel (limited ports: 443, 8443, 10000)
tailscale funnel --tcp=443 localhost:8080

# View funnel status
tailscale funnel status

# Turn off funnel
tailscale funnel --https=443 off

Device Management

Device Information

# Show device information
tailscale whois 100.64.0.1
tailscale whois hostname.tailnet.ts.net

# Show current device details
tailscale status --self

# Update Tailscale client
sudo tailscale update

# Check for updates
tailscale update --check

# View version information
tailscale version

Authentication & Logout

# Manual login (if needed)
tailscale login

# Login with specific login server
tailscale login --login-server=https://headscale.example.com

# Switch between tailnets
tailscale switch

# Logout from current tailnet
tailscale logout

# Force re-authentication
tailscale logout && tailscale up

Security & Access Control

Device Security

# Enable shields up (block incoming connections)
sudo tailscale up --shields-up

# Reset to default settings
sudo tailscale up --reset

# Disable specific features
sudo tailscale up --disable-magic-dns

# Run with minimal privileges
sudo tailscale up --operator=tailscale

Key Management

# Show node key
tailscale debug daemon-logs

# Generate new machine key (requires re-auth)
tailscale logout && tailscale up

# Lock tailnet (requires admin)
tailscale lock init

# Sign node key
tailscale lock sign

DNS Configuration

MagicDNS

# Check DNS status
tailscale dns status

# Query through Tailscale DNS
tailscale dns query hostname.tailnet.ts.net

# Enable/disable DNS
sudo tailscale up --accept-dns=true
sudo tailscale up --accept-dns=false

# Custom DNS servers
sudo tailscale up --accept-dns=false

Monitoring & Debugging

Network Diagnostics

# Network connectivity check
tailscale netcheck

# Detailed network report
tailscale netcheck --verbose

# Monitor real-time logs
tailscale debug daemon-logs

# Connection ping with details
tailscale ping --verbose hostname

# Port connectivity test
tailscale nc hostname 22
tailscale nc hostname 80

Performance Monitoring

# Show metrics
tailscale debug metrics

# Connection info
tailscale debug connectivity

# Peer connection details
tailscale status --peers --verbose

# Check for direct connections
tailscale status | grep "direct"

Troubleshooting

# Generate bug report
tailscale bugreport

# Reset networking state
sudo tailscale down && sudo tailscale up

# Force DERP relay usage (troubleshooting)
sudo tailscale up --advertise-tags=tag:derp-only

# Check firewall rules (Linux)
sudo iptables -L -n | grep tailscale
sudo ufw status

# Verify daemon status
sudo systemctl status tailscaled
sudo journalctl -u tailscaled -f

Advanced Features

File Sharing (Taildrop)

# Send file to another device
tailscale file cp myfile.txt hostname:

# Send to specific user
tailscale file cp document.pdf username@hostname:

# Receive files (check inbox)
tailscale file get

# List pending files
tailscale file list

Kubernetes Integration

# Deploy Tailscale operator
kubectl apply -f https://github.com/tailscale/tailscale/raw/main/cmd/k8s-operator/deploy/manifests/operator.yaml

# Create auth secret
kubectl create secret generic tailscale-auth --from-literal=TS_AUTHKEY=tskey-auth-xxxxxx

# Configure RBAC
export SA_NAME=tailscale
export TS_KUBE_SECRET=tailscale-auth
make rbac | kubectl apply -f-

# Deploy subnet router
make subnet-router | kubectl apply -f-

# Deploy proxy
export TS_DEST_IP="$(kubectl get svc nginx -o=jsonpath='{.spec.clusterIP}')"
make proxy | kubectl apply -f-

Docker Integration

# Run Tailscale in Docker
docker run -d \
--name=tailscale \
--cap-add=NET_ADMIN \
--cap-add=SYS_MODULE \
-v /dev/net/tun:/dev/net/tun \
-v tailscale-data:/var/lib/tailscale \
-e TS_AUTHKEY=tskey-auth-xxxxxx \
tailscale/tailscale

# Use as sidecar
docker run -d \
--name=app-with-tailscale \
--network=container:tailscale \
my-app:latest

Environment Variables

Common Environment Variables

# Authentication
export TS_AUTHKEY=tskey-auth-xxxxxx

# State directory
export TS_STATE_DIR=/var/lib/tailscale

# Socket path
export TS_SOCKET=/var/run/tailscale/tailscaled.sock

# Hostname override
export TS_HOSTNAME=my-custom-name

# Routes for subnet router
export TS_ROUTES=10.0.0.0/8,172.16.0.0/12

# Kubernetes-specific
export TS_KUBE_SECRET=tailscale-auth
export TS_DEST_IP=10.0.0.1

# Userspace mode
export TS_USERSPACE=true

# Debug logging
export TS_DEBUG=true

System Integration

Systemd Configuration

# Enable automatic start
sudo systemctl enable tailscaled

# Start service
sudo systemctl start tailscaled

# Check service status
sudo systemctl status tailscaled

# View logs
sudo journalctl -u tailscaled -f

# Restart service
sudo systemctl restart tailscaled

# Custom service flags (edit /etc/default/tailscaled)
sudo echo 'FLAGS="--port=41641"' >> /etc/default/tailscaled

Firewall Configuration

# UFW (Ubuntu)
sudo ufw allow in on tailscale0
sudo ufw allow out on tailscale0

# Firewalld (CentOS/RHEL)
sudo firewall-cmd --permanent --add-interface=tailscale0 --zone=trusted
sudo firewall-cmd --reload

# iptables (manual)
sudo iptables -A INPUT -i tailscale0 -j ACCEPT
sudo iptables -A OUTPUT -o tailscale0 -j ACCEPT

Cloud Platform Integration

AWS Integration

# Install on EC2 instance
curl -fsSL https://tailscale.com/install.sh | sh
sudo tailscale up --authkey=tskey-auth-xxxxxx

# Subnet router for VPC
sudo tailscale up --advertise-routes=10.0.0.0/16 --authkey=tskey-auth-xxxxxx

# Security group rules
# Allow UDP 41641 for Tailscale traffic
# Allow TCP 22 for SSH (optional)

Google Cloud Platform

# Install on GCE instance
curl -fsSL https://tailscale.com/install.sh | sh
sudo tailscale up --authkey=tskey-auth-xxxxxx

# Advertise GCP subnet
sudo tailscale up --advertise-routes=10.128.0.0/20

# Firewall rule for Tailscale
gcloud compute firewall-rules create allow-tailscale \
--allow udp:41641 \
--source-ranges 0.0.0.0/0 \
--target-tags tailscale

Azure Integration

# Install on Azure VM
curl -fsSL https://tailscale.com/install.sh | sh
sudo tailscale up --authkey=tskey-auth-xxxxxx

# Network Security Group rule
# Allow UDP 41641 inbound from Internet
# Priority: 1000, Action: Allow

Common Use Cases

Remote Development

# Developer machine setup
sudo tailscale up --hostname=dev-laptop --ssh

# Access development server
tailscale ssh dev-server

# Port forwarding for web apps
tailscale serve --https=443 localhost:3000

# Share development environment
tailscale funnel --https=8443 localhost:3000

Home Lab Access

# Home router/gateway setup
sudo tailscale up --advertise-routes=192.168.1.0/24 --advertise-exit-node

# Access home services
sudo tailscale up --accept-routes --exit-node=home-gateway

# Secure NAS access
tailscale ssh nas.local
tailscale serve --https=443 localhost:5000 # Synology DSM

Synology NAS Remote Access

# Install Tailscale on Synology NAS
# Download package from Tailscale website for your Synology model
# Upload via Package Center > Manual Install

# Initial setup via SSH to Synology
ssh admin@synology-ip
sudo tailscale up --hostname=synology-nas

# Enable subnet router for local network access
sudo tailscale up --advertise-routes=192.168.1.0/24 --hostname=synology-nas

# For foreign country access - set up as exit node
sudo tailscale up --advertise-exit-node --advertise-routes=192.168.1.0/24

# Access DSM from anywhere
# https://synology-nas.tailnet-name.ts.net:5001

# Secure file sharing without opening ports
tailscale serve --https=443 localhost:5000 # DSM
tailscale serve --https=8443 localhost:5001 # DSM HTTPS

# Share specific services
tailscale serve --tcp=22 localhost:22 # SSH
tailscale serve --tcp=21 localhost:21 # FTP (if enabled)
tailscale serve --https=9443 localhost:9000 # Portainer (if installed)

# Mobile access from foreign countries
# 1. Install Tailscale mobile app
# 2. Connect to tailnet
# 3. Use exit node for local IP access
# 4. Access: http://192.168.1.100:5000 (local IP through exit node)

# Alternative: Direct access via Tailscale IP
# Access: https://100.x.x.x:5001 (Tailscale IP)

Synology Advanced Configuration

# Enable IP forwarding on Synology (for subnet router)
# Via Control Panel > Terminal & SNMP > Enable SSH
# Then SSH in and run:
echo 'net.ipv4.ip_forward = 1' | sudo tee -a /etc/sysctl.conf
sudo sysctl -p

# Or via DSM Task Scheduler (Control Panel > Task Scheduler)
# Create triggered task -> Boot-up -> User: root
# Command: echo 'net.ipv4.ip_forward = 1' >> /etc/sysctl.conf && sysctl -p

# Automatic startup script (Control Panel > Task Scheduler)
# Create triggered task -> Boot-up -> User: root
# Command: /usr/local/bin/tailscale up --authkey=tskey-auth-xxxxx --advertise-exit-node

# QuickConnect alternative via Tailscale
# Disable QuickConnect in DSM
# Use Tailscale hostname instead: synology-nas.tailnet.ts.net

# VPN Server replacement
# Disable Synology VPN Server
# Use Tailscale exit node functionality instead

Synology Security & Access Control

# Secure access from foreign countries
# 1. Disable all port forwarding on router
# 2. Disable QuickConnect
# 3. Use Tailscale ACLs for access control

# Example ACL for Synology access
{
"acls": [
{
"action": "accept",
"src": ["tag:mobile", "tag:laptop"],
"dst": ["tag:synology:5000", "tag:synology:5001", "tag:synology:22"]
},
{
"action": "accept",
"src": ["tag:admin"],
"dst": ["tag:synology:*"]
}
],
"hosts": {
"synology-dsm": "100.x.x.x"
}
}

# Two-factor authentication
# Enable 2FA in Synology DSM (Control Panel > User & Group > Advanced)
# Tailscale provides additional security layer

# Restrict SSH access
# Control Panel > Terminal & SNMP > Advanced Settings
# Enable "Enable SSH service" only when needed
# Use Tailscale SSH instead: tailscale ssh admin@synology-nas

Synology Mobile Apps Configuration

# DS file app access from abroad
# 1. Install Tailscale on mobile device
# 2. Connect to tailnet and enable exit node
# 3. In DS file app settings:
# - Server: 192.168.1.100 (local IP via exit node)
# - Port: 5000 (HTTP) or 5001 (HTTPS)
# - Account: your DSM username/password

# Alternative: Use Tailscale IP directly
# Server: 100.x.x.x (Tailscale IP of Synology)
# Port: 5000 or 5001

# DS photo, DS video, DS audio apps
# Same configuration as DS file
# Use local IP via exit node or direct Tailscale IP

# Synology Drive client
# Configure sync client with:
# Server: synology-nas.tailnet-name.ts.net
# Or: 100.x.x.x:5001

# Photo backup from abroad
# Enable Tailscale on mobile
# Configure DS photo with Synology Tailscale IP
# Photos upload securely without exposing NAS to internet

Foreign Country Specific Setup

# Laptop/mobile setup while traveling
# Connect to local WiFi abroad
tailscale up --accept-routes --exit-node=synology-nas

# Access home network as if you're local
# All traffic routes through home connection
ping 192.168.1.1 # Home router accessible
curl http://192.168.1.100:5000 # DSM accessible

# Selective routing (more efficient)
tailscale up --accept-routes # Accept only subnet routes, not exit node
# Then access via Tailscale IPs: 100.x.x.x:5000

# Split tunneling approach
# Use exit node only for home network access
tailscale up --exit-node=synology-nas --exit-node-allow-lan-access
# Local internet traffic stays local for better performance

# Troubleshooting abroad
# Check Tailscale connectivity
tailscale ping synology-nas
tailscale netcheck

# If connection issues in restrictive countries
# Try different DERP servers
tailscale netcheck --verbose

# Alternative: Use Tailscale Funnel for external access
# On Synology (for emergency access):
tailscale funnel --https=8443 localhost:5001
# Access via: https://synology-nas.tailnet-name.ts.net:8443

Site-to-Site Connectivity

# Office A subnet router
sudo tailscale up --advertise-routes=10.1.0.0/24 --hostname=office-a-router

# Office B subnet router
sudo tailscale up --advertise-routes=10.2.0.0/24 --hostname=office-b-router

# Client machines
sudo tailscale up --accept-routes

Container Orchestration

# Kubernetes cluster access
sudo tailscale up --advertise-routes=10.244.0.0/16,10.96.0.0/12

# Docker Swarm integration
docker service create \
--name tailscale-gateway \
--cap-add NET_ADMIN \
--mount type=bind,src=/dev/net/tun,dst=/dev/net/tun \
-e TS_AUTHKEY=tskey-auth-xxxxxx \
tailscale/tailscale

# Nomad job integration
job "tailscale" {
datacenters = ["dc1"]
type = "system"

task "tailscale" {
driver = "docker"
config {
image = "tailscale/tailscale:latest"
cap_add = ["NET_ADMIN"]
devices = [{ host_path = "/dev/net/tun" }]
}
env {
TS_AUTHKEY = "tskey-auth-xxxxxx"
}
}
}

Configuration Management

Infrastructure as Code

# Terraform example
resource "tailscale_tailnet_key" "example_key" {
reusable = false
ephemeral = true
preauthorized = true
expiry = 3600
description = "Example key for servers"
tags = ["tag:server"]
}

# Ansible playbook
- name: Install Tailscale
shell: curl -fsSL https://tailscale.com/install.sh | sh

- name: Connect to Tailscale
shell: tailscale up --authkey={{ tailscale_auth_key }}

GitOps ACL Management

# GitHub Actions for ACL sync
name: Tailscale ACL syncing
on:
push:
branches: [ "main" ]
pull_request:
branches: [ "main" ]

jobs:
acls:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Setup Go environment
uses: actions/setup-go@v3.2.0
- name: Install gitops-pusher
run: go install tailscale.com/cmd/gitops-pusher@latest
- name: Deploy ACL
if: github.event_name == 'push'
env:
TS_API_KEY: ${{ secrets.TS_API_KEY }}
TS_TAILNET: ${{ secrets.TS_TAILNET }}
run: |
~/go/bin/gitops-pusher --policy-file ./policy.hujson apply

Security Best Practices

Access Control Policies

{
"acls": [
{
"action": "accept",
"src": ["tag:admin"],
"dst": ["*:*"]
},
{
"action": "accept",
"src": ["tag:developer"],
"dst": ["tag:development:*"]
}
],
"ssh": [
{
"action": "accept",
"src": ["tag:admin"],
"dst": ["tag:server"],
"users": ["root", "admin"]
}
]
}

Key Rotation

# Rotate machine key
tailscale logout
tailscale up --authkey=tskey-auth-new-xxxxxx

# Rotate auth keys regularly
# Generate new keys in admin console
# Update automation scripts

# Enable key expiry
# Set appropriate expiry times in admin console

Troubleshooting Common Issues

Connectivity Problems

# Basic connectivity test
tailscale ping 8.8.8.8

# Check if using DERP relay
tailscale status | grep relay

# Force direct connection
tailscale debug set-derp-map null

# Reset connection state
sudo tailscale down && sudo tailscale up --reset

Performance Issues

# Check for direct connections
tailscale status | grep direct

# Network performance test
tailscale netcheck --verbose

# Enable verbose logging
sudo tailscaled --verbose=1

# Check CPU/memory usage
top -p $(pgrep tailscaled)

DNS Resolution Issues

# Test MagicDNS
nslookup hostname.tailnet.ts.net

# Check DNS configuration
tailscale dns status

# Bypass MagicDNS temporarily
sudo tailscale up --accept-dns=false

# Flush DNS cache
sudo systemctl restart systemd-resolved # Linux
sudo dscacheutil -flushcache # macOS
ipconfig /flushdns # Windows

References