Proxy applications

Proxy a local application

Place Caddy in front of one loopback application and verify the client and upstream as separate connections.

10 minute lesson

~~~

Most Caddy deployments do one thing: sit in front of an application. Your Node or Go or Python app listens on a local port, Caddy owns ports 80 and 443, and the piece connecting them is a reverse proxy.

Why not expose the app directly? Because Caddy brings HTTPS, compression, access logs, and graceful configuration reloads — things your framework either lacks or does worse. The app gets to focus on being an app.

Start a stand-in application on loopback:

python3 -m http.server 3000 --bind 127.0.0.1

Then write the Caddyfile:

:8080 {
  reverse_proxy 127.0.0.1:3000
}

Understand what happens per request: the client connects to Caddy, then Caddy opens a second connection to 127.0.0.1:3000, forwards the request, and relays the response back. Two connections, two log entries, one request.

Compare direct access against the proxied path:

curl -i http://127.0.0.1:3000/
curl -i http://127.0.0.1:8080/

Same body both times. Watch the Python terminal: it logged both requests, one straight from curl and one from Caddy. From the app’s point of view, Caddy is just another client.

The most important detail in this setup is the app’s bind address. It listens on 127.0.0.1, not on all interfaces. If the app also listens publicly, anyone can skip Caddy — and with it your TLS, your logs, and any auth you add later. Verify it:

ss -lnt | grep 3000

You want 127.0.0.1:3000 in that output, not *:3000 or 0.0.0.0:3000.

Now break it on purpose. Stop the Python process and curl through Caddy again: you get 502 Bad Gateway. The runtime log — journalctl -u caddy, or your foreground terminal — shows the dial error with the upstream address. Remember this signature: a 502 from Caddy almost always means the upstream didn’t answer. Check the app first, not the proxy.

Lesson completed

Take this course offline

Get every free book and course as PDF and EPUB files.

Get the download library →