How to Set Up a Reverse SSH Tunnel to Access Your Home Server via VPS

How to Set Up a Reverse SSH Tunnel to Access Your Home Server via VPS

Your home server sits behind a NAT router with a dynamic IP — no way to SSH into it from outside without complicated port forwarding or dynamic DNS. A VPS solves this elegantly with a reverse SSH tunnel: your home server connects outward to the VPS (which it can always reach), and the VPS then forwards incoming connections back to your home server. The result: a stable, permanent way to access your home server from anywhere using just the VPS’s fixed IP.

This guide covers setting up a reverse SSH tunnel, keeping it alive with autossh and systemd, and hardening the connection for production use.

How Reverse SSH Tunneling Works

Normal SSH:
  You → Internet → Home Server (BLOCKED by NAT)

Reverse SSH Tunnel:
  Home Server → outbound SSH → VPS (always works)
  You → SSH to VPS → tunnel → Home Server ✅

The home server initiates the connection (outbound, which NAT allows). The VPS listens on a port and forwards connections back through that tunnel to the home server.

Requirements

  • A VPS with a static public IP (e.g., VPS.DO USA VPS)
  • A home server running Linux (Ubuntu, Raspberry Pi, etc.)
  • SSH access to both machines

💡 VPS.DO Tip: Any VPS.DO plan works for this. Even the smallest plan handles multiple reverse tunnels comfortably. View Plans →


Step 1: Set Up SSH Keys (No Password Authentication)

The tunnel must connect automatically without a password prompt:

# On your home server — generate a dedicated tunnel key
ssh-keygen -t ed25519 -C "home-server-tunnel" \
  -f ~/.ssh/tunnel_key -N ""

# Copy the public key to your VPS
ssh-copy-id -i ~/.ssh/tunnel_key.pub user@YOUR_VPS_IP
# Test the passwordless connection
ssh -i ~/.ssh/tunnel_key user@YOUR_VPS_IP

Step 2: Configure the VPS for Tunneling

# On the VPS — allow gateway ports (needed for tunnel to accept external connections)
sudo nano /etc/ssh/sshd_config
# Add or uncomment:
GatewayPorts yes
AllowTcpForwarding yes
sudo systemctl restart sshd

Step 3: Create the Reverse Tunnel

# Run this on your HOME SERVER
# This forwards VPS port 2222 → home server port 22

ssh -i ~/.ssh/tunnel_key \
    -N \          # No remote command (tunnel only)
    -R 2222:localhost:22 \   # Remote port 2222 → local SSH
    -o ServerAliveInterval=30 \
    -o ServerAliveCountMax=3 \
    user@YOUR_VPS_IP

Now, from your VPS (or from any machine that can reach your VPS), connect to your home server:

# From your VPS — access the home server
ssh -p 2222 home_user@localhost

# From anywhere else — SSH to VPS, then hop to home server
ssh user@YOUR_VPS_IP
ssh -p 2222 home_user@localhost

Or directly in one command:

ssh -J user@YOUR_VPS_IP -p 2222 home_user@localhost

Step 4: Keep the Tunnel Alive with autossh

A plain SSH tunnel dies if the connection drops. autossh monitors and restarts it automatically:

# On the home server
sudo apt install autossh -y

# Test autossh tunnel
autossh -M 0 \
  -i ~/.ssh/tunnel_key \
  -N \
  -R 2222:localhost:22 \
  -o ServerAliveInterval=30 \
  -o ServerAliveCountMax=3 \
  -o ExitOnForwardFailure=yes \
  user@YOUR_VPS_IP

The -M 0 flag disables autossh’s own monitoring port and relies on SSH’s built-in keepalive instead (simpler and more reliable).


Step 5: Run the Tunnel as a systemd Service

Make the tunnel start automatically on boot and restart if it fails:

sudo nano /etc/systemd/system/ssh-tunnel.service
[Unit]
Description=Reverse SSH Tunnel to VPS
After=network-online.target
Wants=network-online.target
StartLimitIntervalSec=0

[Service]
Type=simple
User=YOUR_HOME_USER
ExecStart=/usr/bin/autossh -M 0 \
  -i /home/YOUR_HOME_USER/.ssh/tunnel_key \
  -N \
  -R 2222:localhost:22 \
  -o "ServerAliveInterval=30" \
  -o "ServerAliveCountMax=3" \
  -o "ExitOnForwardFailure=yes" \
  -o "StrictHostKeyChecking=no" \
  user@YOUR_VPS_IP

Restart=always
RestartSec=10
Environment="AUTOSSH_GATETIME=0"

[Install]
WantedBy=multi-user.target
sudo systemctl daemon-reload
sudo systemctl enable ssh-tunnel
sudo systemctl start ssh-tunnel
sudo systemctl status ssh-tunnel

The tunnel now starts on boot and automatically reconnects if the connection drops. ✅


Step 6: Forwarding Multiple Services

You can tunnel multiple ports in a single SSH connection:

# Forward multiple ports in one tunnel:
# - Port 2222 → home SSH (22)
# - Port 8080  → home web server (80)
# - Port 5900  → home VNC (5900)
# - Port 8443  → home HTTPS (443)

autossh -M 0 \
  -i ~/.ssh/tunnel_key \
  -N \
  -R 2222:localhost:22 \
  -R 8080:localhost:80 \
  -R 5900:localhost:5900 \
  -o ServerAliveInterval=30 \
  user@YOUR_VPS_IP
# Access each service from anywhere:
# SSH:  ssh -p 2222 user@YOUR_VPS_IP
# Web:  http://YOUR_VPS_IP:8080
# VNC:  vnc://YOUR_VPS_IP:5900

Step 7: Expose the Tunnel Publicly

By default, the reverse tunnel binds to localhost on the VPS — only accessible from within the VPS. To allow external connections:

# The GatewayPorts yes setting (Step 2) allows:
-R 0.0.0.0:2222:localhost:22
# Update the firewall on the VPS
sudo ufw allow 2222/tcp

Now anyone who knows your VPS IP can SSH to port 2222 and reach your home server.


Step 8: Security Hardening

Restrict tunnel access by IP

# On VPS UFW — only allow tunnel port from your trusted IPs
sudo ufw allow from YOUR_LAPTOP_IP to any port 2222
sudo ufw deny 2222/tcp

Create a dedicated restricted tunnel user on VPS

# On VPS — create a user that can only forward ports, not run commands
sudo useradd -m -s /bin/false tunneluser
sudo passwd tunneluser
# Restrict the tunnel user in /etc/ssh/sshd_config
Match User tunneluser
    AllowTcpForwarding yes
    X11Forwarding no
    AllowAgentForwarding no
    PermitTTY no
    ForceCommand echo 'This account is for tunneling only'

Use the restricted user for the tunnel

# Home server tunnels through the restricted user
ssh-copy-id -i ~/.ssh/tunnel_key.pub tunneluser@YOUR_VPS_IP

autossh -M 0 \
  -i ~/.ssh/tunnel_key \
  -N \
  -R 2222:localhost:22 \
  tunneluser@YOUR_VPS_IP

Practical Use Cases

Use Case Port to forward
SSH to home server -R 2222:localhost:22
Access home Plex/media server -R 32400:localhost:32400
Raspberry Pi VNC remote desktop -R 5900:localhost:5900
Home NAS web interface -R 5000:localhost:5000
Home automation (Home Assistant) -R 8123:localhost:8123
Development server testing -R 3000:localhost:3000
Printer/scanner sharing -R 631:localhost:631

Monitoring Tunnel Status

# On the VPS — check active tunnels
ss -tlnp | grep LISTEN
# Look for ports 2222, 8080, etc.

# Check autossh process on home server
systemctl status ssh-tunnel
journalctl -u ssh-tunnel -f

# Test tunnel connectivity from VPS
ssh -p 2222 home_user@localhost "hostname && uptime"

Final Thoughts

A reverse SSH tunnel transforms a VPS into a permanent gateway to any machine on any network — home servers, office machines, remote Raspberry Pi devices, IoT hardware. The setup takes under 30 minutes and costs nothing beyond your VPS subscription. With autossh and systemd, the tunnel is self-healing and starts automatically on every reboot.

Fast • Reliable • Affordable VPS - DO It Now!

Get top VPS hosting with VPS.DO’s fast, low-cost plans. Try risk-free with our 7-day no-questions-asked refund and start today!