The recurring friction in my self-hosted gateway stack is not routing itself. It is everything around routing: certificate renewal, HTTP/3 support, container networking, and keeping a small proxy configuration understandable enough for the team to review.
I spent a late-night break wiring Caddy in front of a few internal services. The first useful result was operational rather than dramatic: the basic reverse proxy configuration stayed tiny, while HTTPS and certificate renewal required no separate cron job or sidecar.
Minimal setup
A private Docker network keeps the upstream service off the public interface:
services:
caddy:
image: caddy:2
ports:
- "80:80"
- "443:443"
- "443:443/udp"
volumes:
- ./Caddyfile:/etc/caddy/Caddyfile:ro
- caddy_data:/data
- caddy_config:/config
networks:
- edge
- internal
api:
image: example/api:latest
expose:
- "8080"
networks:
- internal
networks:
edge:
internal:
internal: true
volumes:
caddy_data:
caddy_config:
api.example.test {
reverse_proxy api:8080
}
For a real public hostname, I would replace the test domain, point DNS at the host, and verify that ports 80 and 443 are reachable. Caddy then manages certificates automatically.
Before versus after
With a conventional stack, I usually end up joining Nginx, Certbot, renewal hooks, and custom container scripts. Caddy compresses that workflow into one binary and one readable configuration. That reduces deployment surface area and makes review faster.
My latency check would be explicit rather than trusting impressions:
curl -sS -o /dev/null \
-w 'connect=%{time_connect} start=%{time_starttransfer} total=%{time_total}\n' \
https://api.example.test/health
docker stats caddy
The important measurements are cold-start behavior, steady-state memory, TLS handshake time, and error rates under concurrent requests. Caddy is not a quota engine, identity provider, or token governance system; those controls belong upstream or in a dedicated policy layer.
Practical verdict
I would keep Caddy for small and medium self-hosted gateways, especially when automatic HTTPS, private Docker routing, and HTTP/1.1–3 support matter more than an enormous plugin ecosystem.
I would stay vanilla when the team already has a standardized proxy platform, requires advanced traffic policy, or needs strict access-log elimination. Caddy can minimize logging, but privacy still requires deliberately reviewing logs, metrics, headers, and certificate metadata.
Top comments (0)