My cheap alternative to Ngrok

Since GoBlog has an Auto-HTTPS feature that can automatically retrieve HTTPS certificates via ACME from e.g. Let’s Encrypt, I need a public IP address with which I can reach my test instance of GoBlog via port 80 and 443.

So far I’ve been using my ISP’s IP address for this, luckily I don’t have any problems with CGNAT or similar, so I just need to change my daily changing IP address via DynDNS and open the ports on my router.

But I’m not sure if I want to keep this setup forever, because I might switch to mobile internet instead of VDSL in my second home, where my code server is currently located. Then the public IP address would no longer be available.

There are easy alternatives: For example, you can use Ngrok to forward TCP traffic. However, this requires Ngrok Personal, which is not cheap.

But I was able to build my own alternative for free:

I already have experience with Chisel to reverse proxy some self-hosted tools from my VPS at Hetzner to my code/home server. Chisel is a nice tool for TCP and UDP proxing.

Oracle offers a free VPS with a public IP address with their “Always Free” cloud offering. It’s cheaper than renting another VPS from Hetzner! 😀

I took advantage of this, created a new ARM instance with Ubuntu 22.04, configured the network security rules to allow traffic to port 80, 443 and 2334, installed Tailscale to access the VPS using Tailscale SSH, installed Docker using the convenience script, and used this simple Compose configuration to start a Chisel proxy instance:

services:
chisel:
container_name: chisel
image: jpillora/chisel
restart: unless-stopped
ports:
- 80:80
- 443:443
- 2334:2334
command:
- 'server'
- '--port=2334'
- '--auth=user:randompassword' # Change this to your own password
- '--reverse'

I added the following service to the Compose setup on my home server:

services:
chiselproxy:
container_name: chiselproxy
image: jpillora/chisel:latest
restart: unless-stopped
command:
- "client"
- "--auth=user:randompassword" # Change this to your own password
- "1.2.3.4:2334" # Change this to your own public IP
- "R:80:localhost:80"
- "R:443:localhost:443"

And it works! 😄

Interactions & Comments