When developing web apps I sometimes need to expose the local app to the public internet using one of my own domains. One such use case is an OAuth2 flow that requires a callback url. Currently I'm eager to experiment with ActivityPub again. If a Mastodon instance should talk to my app it obvisouly needs to be exposed to the internet.
I used ngrok in the past, but I need it only from time to time in my spare time. A subscription does not make sense to me, so I looked for alternatives.
I found a few open source alternatives, but none really convinced me. Today I managed to get a very simple solution up and running that fits my requirements. It boils down to a reverse proxy in Caddy and a ssh port forward. That's all! It might be obvious to some, but others might be as uninformed as I was, so I'll share my solution with you.
You'll need a server that will redirect the traffic. I use the smallest
possible instance offered by Hetzner. I prefer to
run my stuff using Docker, so first install
Docker. Create a folder for your
project on the server. Lets use /opt/dev-forwarding/
for this example.
You'll need a domain. Lets use `dev.my.domain for this example. Create a DNS record that points your domain to your server.
To let Caddy proxy incoming traffic to port 3333 you need a Caddyfile
like
this:
my.dev.domain {
reverse_proxy * 0.0.0.0:3333
}
Put it into /opt/dev-forwarding/config/caddy/
.
To run Caddy create the following compose.yaml
in /opt/dev-forwarding/
:
services:
caddy:
image: caddy:2
restart: unless-stopped
volumes:
- ./config/caddy:/etc/caddy
- ./caddy/data/:/data
- ./caddy/config/:/config
network_mode: host
Create ./caddy/data
and ./caddy/config
in your project folder. They just
need to exist, so that Caddy can write to them. Start Caddy via docker compose
up -d
. Incomming traffic to https://dev.my.domain
will now be forwarded to
port 3333 on your server. It will not yet work, because there is nothing
listening on that port.
On your local machine run:
ssh -R 0.0.0.0:3333:localhost:8000 you@dev.my.domain
This assumes that my local web app is listening on port 8000. That port will be
forwarded to port 3333 on the server. So Caddy will now proxy traffic to port
3333 which in turn will be forwarded to your local port 8000. Open
https://dev.my.domain/
in your browser and you should see your local
application.
The cost for the Hetzner server is less than 5 Euro per month if you use it for a full month. Stopping the server will still cause costs. But you can create a snapshot and afterwards delete the server. You can rebuild from your snapshot at any time. In my case the snapshot was around 1GB which costs around 1-2 Cent (yes, really) per month for the storage.