Happy New Year!
From time to time I need to expose a development web site or web service to the world. In the past, I’ve used ngrok for that, and of course long ago I built ReverseHTTP which is somewhere in the same ballpark, but I recently got fed up with the state of affairs and decided to see whether there was something simple I could run myself to do the job.
I found Anders Pitman’s SirTunnel:
Minimal, self-hosted, 0-config alternative to ngrok. Caddy+OpenSSH+50 lines of Python.
It really is desperately simple. A beautiful bit of engineering. At its heart, it scripts Caddy’s API to add and remove tunnels on the fly. When you SSH into your server, you invoke the script, and for the duration of the SSH connection, a subdomain of your server’s domain forwards traffic across the SSH link.
I’ve forked the code for myself. So far, I haven’t changed much: the script cleans up stale registrations at startup, as well as at exit, in case a previous connection was interrupted somehow; and I’ve added support for forwarding to local TLS services, with optional “insecure-mode” for avoiding certificate identity checks.
To get it running on a VM in the cloud, install Caddy (there’s a
caddy package for Debian bookworm and sid), then
disable the systemd
caddy service and enable the
Set up a wildcard DNS record for your server - something like
*.demo.example.com. Each tunnel
will be made available on a subdomain of
Then use the API to upload a simple “global” config. Here’s mine:
Upload it by putting it in a file
caddy_global.json and run
Then, make sure SirTunnel’s
sirtunnel.py script is available somewhere on the server to your
SSH user account.
At that point, to expose a local development service running on port 8443 to the world:
I wrapped that up in a tiny script so that I didn’t have to remember the details of that incantation, but it’s simple enough that you could easily just type it in the terminal each time.
Many thanks to Anders Pitman for a really nice piece of software!