Comprehensive Tailscale VPN setup, configuration, and management for mesh networking, secure access, and zero-trust infrastructure. Covers installation, CLI commands, subnet routers, exit nodes, Tailscale SSH, ACL/grants configuration, MagicDNS, Tailscale Serve/Funnel, API automation, and production deployment best practices.
Sets up and manages Tailscale mesh VPN networks, including subnet routers, exit nodes, and Tailscale SSH. Claude will use this when you need secure device-to-device connectivity, remote access to private networks, or identity-based authentication without managing SSH keys.
/plugin marketplace add el-feo/ai-context/plugin install devops@jebs-dev-toolsThis skill inherits all available tools. When active, it can use any tool Claude has access to.
assets/example_asset.txtreferences/acl-examples.mdreferences/api-usage.mdreferences/api_reference.mdreferences/cli-reference.mdreferences/production-setup.mdreferences/troubleshooting.mdscripts/example.pyscripts/setup_exit_node.shscripts/setup_subnet_router.shTrigger 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:
Linux (one-liner):
curl -fsSL https://tailscale.com/install.sh | sh
macOS:
brew install tailscale
Windows/Other platforms: Download from https://tailscale.com/download
# 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
# 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
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:
On client devices:
# Linux needs explicit flag to accept routes
sudo tailscale up --accept-routes
# Other platforms accept routes automatically
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:
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=
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"]
}
]
}
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
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"]
}
]
}
# On home server
sudo tailscale up --advertise-routes=192.168.1.0/24
# From anywhere
ssh homeserver
# Access 192.168.1.* devices through homeserver
# Set home device as exit node before trip
tailscale set --exit-node=home-server
# All traffic now routes through home
# 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
# 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).
# 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:*"]
}
]
# 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"
# 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
✅ Use tags for servers: Never share with personal accounts
sudo tailscale up --advertise-tags=tag:server
✅ Disable key expiry for servers:
--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
✅ 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)
✅ 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
references/cli-reference.md - Complete CLI command reference with all flagsreferences/acl-examples.md - Detailed ACL and grants configuration examplesreferences/api-usage.md - Tailscale API integration and automationreferences/troubleshooting.md - Comprehensive troubleshooting guidereferences/production-setup.md - Best practices for production deploymentsscripts/setup_subnet_router.sh - Automated subnet router setup scriptscripts/setup_exit_node.sh - Automated exit node setup scriptThis skill should be used when the user asks to "create a slash command", "add a command", "write a custom command", "define command arguments", "use command frontmatter", "organize commands", "create command with file references", "interactive command", "use AskUserQuestion in command", or needs guidance on slash command structure, YAML frontmatter fields, dynamic arguments, bash execution in commands, user interaction patterns, or command development best practices for Claude Code.
This skill should be used when the user asks to "create an agent", "add an agent", "write a subagent", "agent frontmatter", "when to use description", "agent examples", "agent tools", "agent colors", "autonomous agent", or needs guidance on agent structure, system prompts, triggering conditions, or agent development best practices for Claude Code plugins.
This skill should be used when the user asks to "create a hook", "add a PreToolUse/PostToolUse/Stop hook", "validate tool use", "implement prompt-based hooks", "use ${CLAUDE_PLUGIN_ROOT}", "set up event-driven automation", "block dangerous commands", or mentions hook events (PreToolUse, PostToolUse, Stop, SubagentStop, SessionStart, SessionEnd, UserPromptSubmit, PreCompact, Notification). Provides comprehensive guidance for creating and implementing Claude Code plugin hooks with focus on advanced prompt-based hooks API.