Tailscale creates a private WireGuard mesh (a "tailnet") so you can reach your VPS without exposing SSH to the public internet.
1. Install Tailscale on the VPS
curl -fsSL https://tailscale.com/install.sh | sh
2. Bring it up
sudo tailscale up
3. Authenticate
Open the login link it prints and authenticate in your browser.
4. Confirm the VPS got a Tailscale IP
tailscale ip -4
You should see a 100.x.y.z address.
5. Install Tailscale on your laptop
- Log into the same tailnet.
- Confirm you can reach the VPS over its Tailscale IP:
ssh user@100.x.y.z
6. Lock down SSH
Do this only after you've successfully SSH'd to the VPS over its Tailscale IP.
Firewall SSH to Tailscale only
If using ufw:
# Remove any existing allow rules for port 22
sudo ufw delete allow 22
sudo ufw delete allow 22/tcp
# Allow SSH only on the Tailscale interface, deny everywhere else
sudo ufw allow in on tailscale0 to any port 22 proto tcp
sudo ufw deny 22/tcp
sudo ufw reload
Then verify:
sudo ufw status verbose
You should see:
To Action From
-- ------ ----
443 ALLOW IN Anywhere
22/tcp on tailscale0 ALLOW IN Anywhere
22/tcp DENY IN Anywhere
443 (v6) ALLOW IN Anywhere (v6)
22/tcp (v6) on tailscale0 ALLOW IN Anywhere (v6)
22/tcp (v6) DENY IN Anywhere (v6)
That keeps sshd running, but only reachable via tailscale0.
If ufw is not active
Use your host firewall tool directly, but the idea is the same:
- allow
22/tcpon interfacetailscale0 - deny
22/tcpon public interfaces
Very important
Keep your current public SSH session open while testing a new Tailscale SSH session.
ssh your-user@<vps-tailscale-ip>
If that works after the firewall change, you're done.
Desired state
22reachable via Tailscale only443reachable publicly- everything else closed unless intentional
7. Update your SSH config
Now that public SSH is closed, update ~/.ssh/config on your laptop to use the Tailscale IP:
Host my-vps
HostName 100.x.y.z # your VPS's Tailscale IP
User your-user
IdentityFile ~/.ssh/id_ed25519_hetzner
SetEnv TERM=xterm-256color
Then connect with:
ssh my-vps
Verify the new setup
What should happen:
ssh your-user@<public-ip-or-domain>→ fail (port 22 denied publicly)ssh your-user@<tailscale-ip>with Tailscale on → work
Troubleshooting
If SSH over the Tailscale IP isn't working, check these on the VPS:
tailscale ip -4 # confirm the Tailscale IP
ip addr show tailscale0 # confirm the interface is up
sudo ss -tulpn | grep ':22\b' # confirm sshd is listening
Likely causes:
tailscale0isn't up on the VPS- You're using the wrong Tailscale IP
- sshd is running but Tailscale ACLs or routing are blocking it
- You're still SSHing to the public IP or domain instead of the
100.x.y.zaddress