Setting Up Tailscale VPN for Secure VPS Access
Back to blog
vpntailscalesecuritynetworkingdevops

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.

February 19, 2025
5 min read

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

  1. Visit tailscale.com
  2. Click "Sign Up"
  3. Authenticate with Google, GitHub, or Microsoft
  4. 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:

  1. Download from tailscale.com/download
  2. Run installer
  3. 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

  1. Go to Machines
  2. Click on VPS machine
  3. 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
ComponentPurposeDefault Port
Tailscale ClientVPN endpoint on each device41641 UDP
Control ServerManages network configurationN/A
VPSBackend infrastructureVirtual IP
Local MachineDevelopment workstationVirtual IP
DatabaseAccessible via VPN only5432

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.