A short course on Caddy

Caddy: route order and reverse_proxy

Caddy answers the same two questions nginx does — which block handles this request, and what path does the backend see — through completely different machinery. This course measures both on Caddy v2.11.4 inside a caddy:2-alpine container, and puts the matching nginx 1.27.5 measurement beside it wherever the comparison is meaningful.

The biggest difference from nginx nginx runs five fixed steps over the location blocks in the order you wrote them. Caddy reorders the route list while it reads the Caddyfile, then evaluates linearly and takes the first route that matches. Measured consequence: swapping two lines in a Caddyfile can change the answer, while swapping two location blocks in nginx does not.

The two lessons

Ten to fifteen minutes of reading each, with a lab that runs in the browser.

How the measurements were taken

Each lesson runs a caddy:2-alpine container. For lesson 1, every handle block returns its own name and curl is called for each path; on top of that, caddy adapt prints the route order in the JSON configuration Caddy actually runs. For lesson 2, a second server in the same container plays the backend and echoes the {http.request.uri} it receives.

docker run -d --name cdlab -p 8097:80 \
  -v "$PWD/Caddyfile:/etc/caddy/Caddyfile:ro" \
  caddy:2-alpine

curl -s http://localhost:8097/img/a.gif
# 3 regex-gif-jpg

docker run --rm -v "$PWD/Caddyfile:/c:ro" caddy:2-alpine \
  caddy adapt --config /c --adapter caddyfile

caddy adapt is what makes this course measurable: it prints the sorted route list, so the order never has to be guessed. The JavaScript in both labs was checked against 24 caddy adapt results, the 14 curl results of lesson 1, and the 13 combinations of lesson 2.