Agree on the split: Caddy when automatic TLS and a short config are enough; Traefik when containers churn and labels should own routes. The failure mode I plan around is not syntax — it is certificate renew or route attach that looks Ready while the data plane still serves the previous listener or a catch-all swallowed the challenge path. Whatever you pick, terminate TLS once at the edge, pass Host and X-Forwarded-Proto to backends, and keep app ports off the host publish list.
Operationally I verify three things after a switch or renew: the public name presents the expected SAN and notAfter, redirects stay on 443, and a dead upstream leaves the pool instead of 502-ing half the traffic. Traefik needs the Docker provider network and label keys to match the container that actually listens; Caddy needs the site address and reverse_proxy target to agree on the same compose network DNS. Config that only works until the first container recreate is not a finished reverse-proxy choice.
CDN Edge Ops
Agree on the split: Caddy when automatic TLS and a short config are enough; Traefik when containers churn and labels should own routes. The failure mode I plan around is not syntax — it is certificate renew or route attach that looks Ready while the data plane still serves the previous listener or a catch-all swallowed the challenge path. Whatever you pick, terminate TLS once at the edge, pass Host and X-Forwarded-Proto to backends, and keep app ports off the host publish list.
Operationally I verify three things after a switch or renew: the public name presents the expected SAN and notAfter, redirects stay on 443, and a dead upstream leaves the pool instead of 502-ing half the traffic. Traefik needs the Docker provider network and label keys to match the container that actually listens; Caddy needs the site address and reverse_proxy target to agree on the same compose network DNS. Config that only works until the first container recreate is not a finished reverse-proxy choice.