IAnswerable

Caddy, Traefik, or Nginx: Picking a Reverse Proxy

17 Sep 2026

Nginx if you want control and don’t mind writing config by hand. Caddy if you want HTTPS to just work. Traefik if you run Docker or Kubernetes and want the proxy to find services on its own.

What each one actually does

Nginx is a general-purpose web server that also reverse-proxies well. It’s mature, fast, and most ops people already half-know it. Certificates are your job — you wire up certbot, a renewal cron, and a reload hook, and you maintain that pipeline forever.

Caddy is a reverse proxy that treats HTTPS as the default, not an add-on. Point it at a domain and it gets a certificate from Let’s Encrypt automatically, renews it before expiry, and redirects HTTP to HTTPS without you writing a line for any of it.

Traefik is built for environments where services come and go. It watches Docker, Kubernetes, or Consul and updates routing rules as containers start and stop. Label a container and it shows up behind the proxy — no config reload, no restart.

Pick with this

flowchart TD
    A{"Need certs managed automatically?"} -->|no| N["Nginx"]
    A -->|yes| B{"Services start/stop often (Docker or K8s)?"}
    B -->|yes| T["Traefik"]
    B -->|no| C["Caddy"]
  

What the config looks like

A working HTTPS reverse proxy in Caddy is one block:

example.com {
    reverse_proxy localhost:3000
}

The same result in Nginx needs a server block, a listen directive for 443, cert paths, and a separate HTTP-to-HTTPS redirect block — plus certbot running outside the config entirely. It’s not hard, it’s just more surface area to get wrong.

Traefik’s config lives partly in labels on the container:

labels:
  - "traefik.http.routers.app.rule=Host(`example.com`)"
  - "traefik.http.routers.app.tls.certresolver=letsencrypt"

No central route file to edit when you add a service — the label is the route.

Where each one breaks

Nginx: forget to renew, or break the certbot cron silently, and you find out when a visitor hits a red padlock. Nothing in nginx itself watches for that.

Caddy: the module ecosystem is smaller. If you need something like ModSecurity-style WAF rules or a very specific rewrite pattern nginx has a battle-tested module for, you may not find a Caddy equivalent.

Traefik: when routing doesn’t work, the failure is usually a label typo or a missing network attachment, and the error shows up in Traefik’s logs, not the app’s. Debugging means learning its dashboard and its own vocabulary (routers, entrypoints, middlewares) before you can read the failure.

Comparison

Nginx Caddy Traefik
Cert automation Manual (certbot) Built in Built in
Config style Static file Static file Labels / dynamic
Best fit High-traffic, custom rules Solo dev, few sites Docker/K8s, many services
Learning curve Well documented, verbose Low Moderate

Verdict

Running a couple of sites on one VPS: use Caddy, you’ll never think about certs again. Running a docker-compose stack with services that change: use Traefik. Need nginx-specific modules, rate limiting tuned to your traffic, or you already have working nginx config: keep nginx, don’t migrate for its own sake.