Tailscale Network Management
Trigger Keywords: tailscale, tailnet, wireguard vpn, mesh vpn, tailscale ssh, exit node, subnet router, tailscale acl, magicDNS, tailscale serve, tailscale funnel
What is Tailscale? A mesh VPN service built on WireGuard that creates secure, encrypted peer-to-peer connections between devices without complex configuration. Unlike traditional VPNs with central gateways, Tailscale creates direct connections between devices (or uses relay servers when needed).
Key Benefits:
- •Zero-config networking: Works seamlessly across NAT and firewalls
- •Direct connections: Peer-to-peer mesh reduces latency vs traditional hub-and-spoke VPNs
- •WireGuard encryption: State-of-the-art cryptographic security
- •Identity-based access: Integrates with SSO providers (Google, Okta, GitHub, etc.)
- •Cross-platform: Works on Linux, macOS, Windows, iOS, Android, and more
Quick Start
Installation
Linux (one-liner):
curl -fsSL https://tailscale.com/install.sh | sh
macOS:
brew install tailscale
Windows/Other platforms: Download from https://tailscale.com/download
Initial Setup
# Start Tailscale and authenticate sudo tailscale up # Check status tailscale status # Get your Tailscale IP tailscale ip -4 # Connect via MagicDNS hostname ssh user@machine-name
Common Operations
Basic Connection Management
# Connect to your tailnet tailscale up # Disconnect but keep daemon running tailscale down # Check connection status and peers tailscale status # View detailed network map tailscale status --json | jq # Ping another tailnet device (TSMP ping) tailscale ping machine-name # Test connectivity including ACLs (ICMP ping) tailscale ping --icmp machine-name
Subnet Router Setup
What it does: Allows devices without Tailscale to be accessible via a gateway device that does have Tailscale installed.
On the router device:
# Enable IP forwarding (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 # Advertise routes to your local network sudo tailscale up --advertise-routes=192.168.1.0/24,10.0.0.0/24
In the admin console:
- •Go to Machines → find your subnet router
- •Click menu → "Edit route settings"
- •Enable the advertised routes
On client devices:
# Linux needs explicit flag to accept routes sudo tailscale up --accept-routes # Other platforms accept routes automatically
Exit Node Configuration
What it does: Routes ALL internet traffic through a specific device on your tailnet (like a traditional VPN).
Setup exit node:
# Enable IP forwarding (same as subnet router) 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 # Advertise as exit node sudo tailscale up --advertise-exit-node
In admin console:
- •Go to Machines → find exit node
- •Click menu → "Edit route settings"
- •Enable "Use as exit node"
Use exit node from another device:
# Use specific exit node tailscale set --exit-node=exit-node-name # Use suggested exit node (auto-selects best) tailscale set --exit-node=auto:any # Allow LAN access while using exit node tailscale set --exit-node=exit-node-name --exit-node-allow-lan-access # Stop using exit node tailscale set --exit-node=
Tailscale SSH Setup
What it does: SSH without managing keys, using your Tailscale identity for authentication.
Enable SSH on server:
# Enable Tailscale SSH server sudo tailscale set --ssh
Configure access in admin console: Go to Access Controls and add to the policy file:
{
"grants": [
{
"src": ["user@example.com"],
"dst": ["tag:servers"],
"ip": ["22"]
}
],
"ssh": [
{
"action": "accept",
"src": ["user@example.com"],
"dst": ["tag:servers"],
"users": ["root", "ubuntu", "autogroup:nonroot"]
}
]
}
Connect from client:
# No special setup needed on client! ssh machine-name # Or use specific user ssh ubuntu@machine-name # Works with SCP and SFTP too scp file.txt machine-name:/tmp/
Check mode (for high-security connections):
{
"ssh": [
{
"action": "check", // Requires recent SSO re-auth
"src": ["user@example.com"],
"dst": ["tag:servers"],
"users": ["root"]
}
]
}
Serve and Funnel
Tailscale Serve (share within your tailnet):
# Serve local web server to tailnet tailscale serve 3000 # Serve specific path tailscale serve --https=443 --set-path=/app 8080 # Serve static files tailscale serve --https=443 /var/www/html # Serve with TLS-terminated TCP tailscale serve --tls-terminated-tcp=5432 localhost:5432 # Check status tailscale serve status # Turn off tailscale serve off
Tailscale Funnel (expose to public internet):
# Share to entire internet (must be on ports 443, 8443, or 10000) tailscale funnel 3000 # Turn off tailscale funnel off
Access Control Lists (ACLs)
Default policy (allows all):
{
"acls": [
{
"action": "accept",
"src": ["*"],
"dst": ["*:*"]
}
]
}
Role-based access example:
{
"groups": {
"group:engineering": ["user1@example.com", "user2@example.com"],
"group:ops": ["ops@example.com"]
},
"tagOwners": {
"tag:dev": ["group:engineering"],
"tag:prod": ["group:ops"]
},
"acls": [
{
"action": "accept",
"src": ["group:engineering"],
"dst": ["tag:dev:*"]
},
{
"action": "accept",
"src": ["group:ops"],
"dst": ["tag:prod:*"]
}
]
}
Modern Grants syntax (recommended):
{
"grants": [
{
"src": ["group:engineering"],
"dst": ["tag:dev"],
"ip": ["*"]
},
{
"src": ["group:ops"],
"dst": ["tag:prod"],
"ip": ["22", "443", "80"]
}
]
}
Common Scenarios
Home Lab Access
# On home server sudo tailscale up --advertise-routes=192.168.1.0/24 # From anywhere ssh homeserver # Access 192.168.1.* devices through homeserver
Secure Travel
# Set home device as exit node before trip tailscale set --exit-node=home-server # All traffic now routes through home
Multi-Site Connectivity
# Site A router sudo tailscale up --advertise-routes=10.0.0.0/24 # Site B router sudo tailscale up --advertise-routes=10.1.0.0/24 --accept-routes # Now Site B can reach Site A's 10.0.0.0/24 network
Troubleshooting
Connection Issues
# Check if devices can establish connection (ignores ACLs) tailscale ping --tsmp peer-name # Check end-to-end including ACLs tailscale ping --icmp peer-name # View network map and connection details tailscale netcheck # Debug daemon logs tailscale debug daemon-logs # Check DERP relay status tailscale netcheck
If TSMP succeeds but ICMP fails: ACL policy is blocking the connection.
If both fail: Network connectivity issue (firewall, NAT, routing problem).
ACL Testing
# Preview rules for specific user (in admin console)
# Access Controls → Preview rules → select user
# Test ACL in policy file
# Add to policy:
"tests": [
{
"src": "user@example.com",
"accept": ["tag:server:22"],
"deny": ["tag:prod:*"]
}
]
Subnet Router Not Working
# Verify IP forwarding enabled cat /proc/sys/net/ipv4/ip_forward # Should be 1 # Check firewall isn't blocking sudo iptables -L -v -n sudo iptables -t nat -L -v -n # Verify routes advertised tailscale status | grep "subnet router" # On client, ensure routes accepted tailscale status | grep "routes accepted"
MagicDNS Not Resolving
# Check MagicDNS enabled tailscale status | grep MagicDNS # In admin console: DNS → Enable MagicDNS # Flush DNS cache # macOS sudo dscacheutil -flushcache # Linux (systemd-resolved) sudo systemd-resolve --flush-caches
Best Practices
Security
✅ Use tags for servers: Never share with personal accounts
sudo tailscale up --advertise-tags=tag:server
✅ Disable key expiry for servers:
- •Admin console → Machines → menu → "Disable key expiry"
- •Or use
--auth-keywith reusable key
✅ Use check mode for root access: Requires recent SSO re-authentication
✅ Principle of least privilege: Grant only necessary ports in ACLs
{
"grants": [{
"src": ["group:devs"],
"dst": ["tag:dev"],
"ip": ["22", "80", "443"] // Only SSH and HTTP(S)
}]
}
✅ Enable Tailnet Lock (enterprise): Cryptographically prevent unauthorized device additions
Operations
✅ Use auth keys for automation:
# Generate in admin console → Settings → Keys sudo tailscale up --auth-key=tskey-auth-...
✅ Tag infrastructure servers: Enables service accounts instead of personal ownership
✅ Set up high-availability:
# Multiple subnet routers with same routes = automatic failover # Router 1 sudo tailscale up --advertise-routes=10.0.0.0/24 # Router 2 sudo tailscale up --advertise-routes=10.0.0.0/24
✅ Use GitOps for ACLs: Version control your policy file with GitHub/GitLab
✅ Monitor with logging: Enable network flow logs (Enterprise feature)
Performance
✅ Enable UDP GRO forwarding (Linux subnet routers):
NETDEV=$(ip -o route get 8.8.8.8 | cut -f 5 -d " ") sudo ethtool -K $NETDEV rx-udp-gro-forwarding on rx-gro-list off
✅ Prefer direct connections: Check with tailscale status - look for "direct"
✅ Use appropriate MTU: Usually auto-detected correctly, but can tune if needed
Reference Files
- •
references/cli-reference.md- Complete CLI command reference with all flags - •
references/acl-examples.md- Detailed ACL and grants configuration examples - •
references/api-usage.md- Tailscale API integration and automation - •
references/troubleshooting.md- Comprehensive troubleshooting guide - •
references/production-setup.md- Best practices for production deployments - •
scripts/setup_subnet_router.sh- Automated subnet router setup script - •
scripts/setup_exit_node.sh- Automated exit node setup script