FUTURE OF WORK
Developer Builds Self-Hosted Alternative to ngrok Using Only OpenSSH and Nginx
A blog post by developer Vincent Bernat shows how to share a local web server over the internet without installing any new software, using OpenSSH's remote port forwarding paired with nginx and a secure-link token.
Image: IntraGoals Media · Uploaded by IntraGoals — usage rights confirmed
Need to let someone preview a website you're building on your own laptop, without signing up for a third-party tunneling service? Developer Vincent Bernat has published a detailed walkthrough showing how to do it using nothing but software that's probably already running on a server you control: OpenSSH and nginx.
The problem is a familiar one. A work-in-progress blog post or web app often runs locally on an address like localhost:8080, invisible to anyone outside the machine it's on. Tools such as ngrok and Cloudflare Quick Tunnels solve this as paid or hosted services. Others, like frp and localtunnel, are self-hostable but require installing a special client. A tool called sish works with any plain SSH client but needs a specific SSH server running on the far end. Bernat's approach avoids all of that extra tooling.
The technique starts with a standard OpenSSH feature: remote port forwarding. Running a command such as 'ssh -N -R 0:localhost:8080 web02.luffy.cx' tells the remote server to open a port and forward any traffic it receives there back down the SSH connection to the local service on port 8080. Specifying '0' as the remote port lets the server pick a free one automatically, such as 41535.
From there, nginx takes over. A server block on the remote machine recognizes incoming requests to addresses like https://p41535.ssh.luffy.cx and proxies them straight through to http://127.0.0.1:41535, the port OpenSSH just opened. Supporting DNS records, including a wildcard CNAME and a Let's Encrypt wildcard certificate obtained via a DNS-01 challenge, complete the basic setup.
Because the port number is the only thing standing between the outside world and the content being shared, and because the kernel's pool of ephemeral ports offers under 15 bits of randomness, Bernat adds a second layer of protection. Using nginx's secure_link module, the server computes an MD5 hash over the port number, an expiration timestamp and a private secret, then requires that hash to be presented in the URL before it will proxy a request. The hash and expiry are smuggled into the URL as an HTTP Basic Authentication username, a trick that works with most HTTP clients, including curl. Nginx checks the hash, returns a 401 error if it's missing or wrong, and a 410 error if the link has expired, before stripping the Authorization header and forwarding the request onward with WebSocket support enabled.
To smooth over the rough edges, Bernat wrote a helper script that automatically discovers which port OpenSSH allocated for a given SSH session, by walking the process tree to find the associated sshd-session process and querying its listening sockets, then prints a ready-to-share, signed URL and keeps the session alive. Installed on the server and wired into an SSH config entry, it turns the whole process into a single command that produces a shareable link.
The result, Bernat notes, is a tunnel that depends on no software beyond what's already running on his server: OpenSSH and nginx. He has published the full helper script, along with a NixOS module for anyone who wants to deploy the setup declaratively.