Reverse Tunnel a Home Service to a Cloud Server

written October 2020

I host my own email server from my home. I cannot (and do not want to) expose any ports on my home router to the Internet directly, so I needed a way to tunnel that traffic from a cloud-based server (Digital Ocean in my case).

ssh provides the -R flag which sets up a reverse tunnel to the remote host and allows your local-running service to appear as though it is running at the remote host. The trick is to set up such a tunnel in a way that it keeps running and survives reboots, home Internet connection outages, network routing issues, etc.

After much experimentation, I came up with the following systemd service config which seems to do the trick:

Description=SSH Remote Tunnel for IMAP

ExecStart=expect -c "set timeout -1; spawn ssh -R *:143:localhost:143 -N -o ServerAliveInterval=180 -o ServerAliveCountMax=2; expect \"port forwarding failed\" { exit 1 }"



  1. expect runs the ssh program and monitors for the output "port forwarding failed"—if such output is seen, then the ssh program is terminated.
  2. ssh sets up the reverse tunnel with keep-alive enabled, meaning that the tunnel should remain open even without keyboard input.
  3. systemd takes care of restarting the program if it exits and also restarts the program proactively once a day just for good measure.

I won't get into further detail about how to install and enable the systemd service or how to enable tunneling in the SSH daemon in the remote host config—there are other Internet tutorials that explain those tasks better than I would.

I've been using this systemd service config for a few weeks now and it's working beautifully. I can access my home email from a public cloud-based server without exposing ports on my home firewall or making my home IP address known.

Hosting for this site is provided by

The SDF Public Access UNIX System