Gabe Rocks!

Self-hosting with SSH tunnels

I wrote in a previous post that I’ve been using SSH tunnels to self-host services, but serve from a VPS. This was primarily motivated by the fact that a residential IP may inadvertently give out your exact location to others. Another advantage, is that your files and keys are still kept on your local machine instead of in the cloud. For services that require heavy use of files that aren’t private, I’d recommend using an S3 bucket if possible.

Essentially there are three steps

  1. Setup SSH tunnels
  2. Create an always-on SSH session
  3. Setup your reverse-proxy

1. Setup SSH tunnels.

The best way to setup your tunnels is to use your ~/.ssh/config file.

Host vps
    Hostname {your-vps-hostname}
    User {your-server-user}
    ServerAliveInterval 300
    RemoteForward localhost:80
    #You can forward multiple ports
    RemoteForward localhost:8008
    #IdentityFile ~/.ssh/ 

man page

What this means is that when your machine has an ssh session to the vps, you want to open the ports listed, from the ports on your machine which are listed second.

2. Keep an always-open SSH tunnel.

For this, I created a systemd service:

Using: systemctl edit --full --force systemd-tunnel to create the service

Description=Reverse SSH connection

User={your user}
Group={your group}
ExecStart=/usr/bin/ssh -vvv -g -N -T -o "ServerAliveInterval 10" -o "ExitOnForwardFailure yes" vps


Then you can simply start the service with systemctl enable --now secure-tunnel

3. Configure your reverse proxy

In the example .ssh/config we forwarded local port 8080 to the vps port 80. This means that for that port no additional modifications are required. Anything served on your port 8080 will be served from your vps as http. The second example we forwarded local (http) synapse port to 8008 on the vps. So you’ll want to reverse proxy that.To do this on nginx, on your VPS you’ll proxy_pass to https://localhost:8008.

Here’s an example nginx config sample that would be in /etc/nginx/sites/available/matrix

server {
    listen 8448;
    server_name matrix.your.domain;
    location / {
        proxy_pass http://localhost:8008;        
    #SSL and other options here...

I hope you’ve found this helpful. I plan to explain this in even more detail in a peertube video sometime soon.

Reply to this post

Self-Hosting SSH Linux
Prev B @ Next