zurück / back

Expose local app to the public internet using a custom domain

Why?

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.

My solution

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.

Server

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.

Domain

You'll need a domain. Lets use `dev.my.domain for this example. Create a DNS record that points your domain to your server.

Caddy

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/.

Compose

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.

Port forward

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.

Costs

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.

Impressum