Setting Up Tailscale VPN for Secure VPS Access
Complete guide to installing and configuring Tailscale for secure, encrypted access to multiple VPS instances with zero-knowledge networking.
Setting Up Tailscale VPN for Secure VPS Access
Tailscale is a zero-knowledge VPN built on WireGuard that provides encrypted, secure access to your infrastructure without complex configuration. This guide covers installation, setup, and best practices for accessing multiple VPS instances.
Why Tailscale?
Traditional VPNs require complex server setup and certificate management. Tailscale abstracts this complexity, providing instant encrypted networking between your devices. No port forwarding, no complex firewall rules, just secure peer-to-peer connections authenticated via your existing identity provider.
Prerequisites
- Tailscale account (free tier available)
- VPS running Linux (Ubuntu 20.04+ or Debian 11+)
- SSH access to VPS
- Personal devices (Mac, Linux, Windows, iOS, Android)
Step 1: Create Tailscale Account
- Visit tailscale.com
- Click "Sign Up"
- Authenticate with Google, GitHub, or Microsoft
- Create your Tailnet (virtual network)
Step 2: Install Tailscale on VPS
Connect via SSH to your VPS and install Tailscale:
curl -fsSL https://tailscale.com/install.sh | sh
Verify installation:
sudo tailscale --version
Step 3: Connect VPS to Tailnet
Start the Tailscale daemon:
sudo tailscale up
This command will output an authentication URL. Copy the link:
To authenticate, visit:
https://login.tailscale.com/a/xxxxxxx
Open the URL in your browser and authenticate. After authentication, the VPS is now part of your Tailnet.
Verify the connection:
sudo tailscale status
Output shows your VPS with an assigned Tailscale IP (typically 100.x.x.x).
Step 4: Install Tailscale on Local Machine
macOS:
brew install tailscale
brew services start tailscale
# Or use GUI from App Store
Connect to Tailnet:
tailscale up
Ubuntu/Debian:
curl -fsSL https://tailscale.com/install.sh | sh
sudo tailscale up
Windows:
- Download from tailscale.com/download
- Run installer
- Click "Connect" to authenticate
After authentication, check your Tailnet in the Tailscale admin console.
Step 5: Configure Tailscale on VPS
List connected devices:
sudo tailscale status
Configure as Exit Node (Optional)
If you want to route all traffic through your VPS:
sudo tailscale up --advertise-exit-node
Verify exit node is advertised:
sudo tailscale status
On your local machine, enable exit node in Tailscale settings.
Configure Subnet Router
To access internal networks through your VPS:
sudo tailscale up --advertise-routes=192.168.1.0/24
Replace 192.168.1.0/24 with your internal subnet.
Step 6: Configure Firewall Rules
By default, Tailscale is not affected by traditional firewalls, but you should set Tailscale-specific access control.
Go to admin console → Access Controls → Edit Policy File:
{
"acls": [
{
"action": "accept",
"src": ["group:developers"],
"dst": ["tag:production", "tag:database"]
},
{
"action": "accept",
"src": ["tag:app-servers"],
"dst": ["tag:database"]
}
],
"tagOwners": {
"tag:production": ["group:admins"],
"tag:database": ["group:admins"],
"tag:app-servers": ["group:admins"]
},
"groups": {
"group:developers": ["user1@example.com", "user2@example.com"],
"group:admins": ["admin@example.com"]
}
}
Step 7: Tag Your Machines
Tags help organize and control access to different machines.
Method 1: Via Admin Console
- Go to Machines
- Click on VPS machine
- Add tags:
tag:production,tag:app-server
Method 2: Via CLI
sudo tailscale up --advertise-tags=tag:production,tag:database
Step 8: Access Services via Tailscale
Once connected to Tailnet, access services using Tailscale IPs:
Connect to SSH on VPS
# Get your VPS Tailscale IP
sudo tailscale status
# Example output shows: vps-prod 100.64.1.23
# SSH directly:
ssh user@100.64.1.23
Connect to Database
PostgreSQL on VPS accessible only via Tailnet:
# From your local machine
psql -h 100.64.1.23 -U postgres -d mydb
Update Database Connection String
For applications:
DATABASE_URL="postgresql://user:password@100.64.1.23:5432/mydb"
Access Web Services
If you run a development server on VPS:
# On VPS, listen on Tailscale IP
./app --listen=100.64.1.23:3000
# From local machine, visit:
curl http://100.64.1.23:3000
Step 9: Enable Tailscale SSH
Use Tailscale for SSH without managing keys:
Go to Admin Console → Settings → Tailscale SSH → Enable
On VPS, enable SSH:
sudo tailscale up --ssh
From local machine, SSH without password:
# Get your Tailscale hostname
tailscale status
# SSH directly
ssh -l user 100.64.1.23
This uses Tailscale's built-in SSH authentication.
Step 10: Advanced Configuration
Funnel: Share Services with Non-Tailnet Users
Safely share services with people outside your Tailnet:
# On VPS running web service on :3000
sudo tailscale funnel 3000
Get shareable link from output. Anyone can access without Tailscale.
MagicDNS: Use Hostnames Instead of IPs
Enable MagicDNS in Admin Console → DNS:
# Instead of IP, use hostname
ping vps-prod.your-tailnet-name.ts.net
# In applications
DATABASE_URL="postgresql://user:pass@postgres-prod.your-tailnet-name.ts.net:5432/db"
Automating Tailscale Connection
Create systemd service to auto-connect on reboot:
sudo systemctl status tailscaled
Tailscale automatically reconnects on system startup.
Security Best Practices
Use Devices as Root for Updates: Only allow specific devices to update infrastructure
{
"acls": [
{
"action": "accept",
"src": ["user@example.com"],
"dst": ["tag:infrastructure"]
}
]
}
Enable Device Approval: Require admin approval for new devices
Admin Console → Settings → Device Approval
Revoke Lost Devices: Immediately remove compromised machines
# Or via Admin Console
tailscale logout # On the lost device
Use Groups: Organize users by role
{
"groups": {
"group:database-admins": ["dba1@example.com", "dba2@example.com"],
"group:developers": ["dev1@example.com", "dev2@example.com"]
}
}
Troubleshooting
Connection Failed:
# Check Tailscale status
sudo tailscale status
# Restart daemon
sudo systemctl restart tailscaled
# Check logs
sudo journalctl -u tailscaled -n 50
Can't Reach Other Machines:
# Verify connectivity
ping 100.x.x.x
# Check firewall rules
sudo ufw status
MagicDNS Not Working:
# Flush DNS cache
sudo systemctl restart systemd-resolved
# Test MagicDNS
nslookup machine-name.your-tailnet.ts.net
| Component | Purpose | Default Port |
|---|---|---|
| Tailscale Client | VPN endpoint on each device | 41641 UDP |
| Control Server | Manages network configuration | N/A |
| VPS | Backend infrastructure | Virtual IP |
| Local Machine | Development workstation | Virtual IP |
| Database | Accessible via VPN only | 5432 |
Performance Optimization
For high-throughput applications, optimize Tailscale:
# Increase UDP buffer size
sudo sysctl -w net.core.rmem_max=134217728
sudo sysctl -w net.core.wmem_max=134217728
# Make permanent
echo "net.core.rmem_max=134217728" | sudo tee -a /etc/sysctl.conf
sudo sysctl -p
Monitoring Tailscale
View active connections:
sudo tailscale status
Check certificate status:
sudo tailscale cert google.com
Monitor bandwidth usage in Admin Console.
Integration with Docker
Run container connected to Tailnet:
docker run -it \
--name postgres-tailscale \
-e POSTGRES_PASSWORD=password \
postgres:15
# Access from Tailnet
psql -h 100.64.1.23 -U postgres
For docker-compose:
version: '3.8'
services:
postgres:
image: postgres:15
environment:
POSTGRES_PASSWORD: password
networks:
- app-network
tailscale:
image: tailscale/tailscale:latest
environment:
TS_AUTHKEY: your-pre-auth-key
networks:
- app-network
networks:
app-network:
Deployment with Tailscale
Example GitHub Actions workflow:
name: Deploy
on: [push]
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Connect to Tailscale
uses: tailscale/github-action@v2
with:
authkey: ${{ secrets.TAILSCALE_AUTHKEY }}
- name: Deploy to VPS
run: |
ssh -l deploy 100.64.1.23 << 'EOF'
cd /app
git pull
npm install
npm run build
systemctl restart app
EOF
Useful Resources
Conclusion
Tailscale eliminates VPN complexity while providing enterprise-grade security. Use it to securely connect development machines to production infrastructure, manage access with granular controls, and simplify remote work infrastructure without sacrificing security.