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.
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 0.0.0.0:8080 localhost:80
#...
#You can forward multiple ports
RemoteForward 0.0.0.0:8008 localhost:8008
#IdentityFile ~/.ssh/your-ssh.pub
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
[Unit]
Description=Reverse SSH connection
After=network.target
[Service]
User={your user}
Group={your group}
Type=simple
ExecStart=/usr/bin/ssh -vvv -g -N -T -o "ServerAliveInterval 10" -o "ExitOnForwardFailure yes" vps
Restart=always
RestartSec=3s
[Install]
WantedBy=default.target
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.