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-key with 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