Using SSH tunnels to deploy your site
Note: Updated on 2019-09-09
Running a local service on the open Internet is still a thing, even in the age of the Cloud.
For instance, I have a local set of dashboards using Corsica that I’d like to have access to from the road. You may want to show a client work in progress without having to bother with deploying to an external host. You may want to connect to a security camera you run attached to a Raspberry Pi. Or run a web application on a non-privileged port.
For a long time, the way to do that would had been to set up port-forwarding on your router and use a personal DNS service. Port-forwarding requires router configuration, and limits you to exposing one service to the web, and your ISP most likely blocks ports 80 and 443.
With an SSH tunnel, you can expose your service to the internet without the hassle of router configuration:
ssh -R 80:localhost:8080 external.example.com
Your service at
localhost:8080 would be on the web at http://external.example.com.
external.example.com needs to be reachable from the public internet. You could host your endpoint yourself in the Cloud, but endpoints for SSH tunnels are available as a service from several providers.
Here’s my notes on two services I’ve tried.
Pagekite is a paid service. The company calls the tunnels ‘kites’ and meters bandwidth used by them.
pagekite.py 8080 yourname.pagekite.me
And your service will be available at https://yourname.pagekite.me.
If you don’t have an account, the script will prompt you to set up an account. Pagekite takes care of monitoring the tunnel for you. They provide documentation for starting up the service at boot using rc scripts. Again, you have to start your service before you start the tunnel.
If you only want to host a set of static files:
pagekite.py /path/to/folder yourname.pagekite.me
They provide built-in defenses for so-called ‘drive-by’ attacks, by blocking requests to
/wp-admin/ and similar paths by default. You can also add passwords, or restrict access by IP address (useful for the IoT camera example.)
For six hosts and 150,000 Mb of transfer, I pay 40 USD a year. They also provide a white label service for IoT device makers.
ssh -R 80:localhost:3000 serveo.net
which will return:
Hi there Forwarding HTTP traffic from https://randomname.serveo.net Press g to start a GUI session and ctrl-c to quit.
Notice that resulting url is
https so you don’t have to set up your own certificates.
You can specify a sub-domain, in your ssh command.
ssh -R emma:80:localhost:8888 serveo.net
If the subdomain
emma was available, you’d be reachable at
Using a tool like
autossh and startup scripts, you can make sure your service lives between restarts. Remember that you’ll also need to start the service you’re tunnelling. There’s a whole post on setting up
autossh with systemd you which is useful here.
Serveo’s ease-of-use is also its flaw. Anyone can set up a forward with it, and the serveo.net certificate is a wild card, so if a browser trusts your service using Serveo, it trusts every other service using it to forward.
Chen Hui Jing has a post, written after the first publication of this article, on other free tunneling services.
A tunnel is only as good as the endpoint. You have to trust the endpoint with your service. If it’s compromised, then you have to consider your service compromised. Google has blocklisted these services before when people acting from bad intent have used these to distribute malware. A service which requires an account might not be libre, but will have some accountability.