ADR-0002 — Traefik v3 as the edge reverse proxy with automatic TLS¶
- Status: accepted
- Date: 2026-06-30
- Domain: edge routing · TLS
Context¶
Every service in the lab is published at https://<project>.tarik-lab.dev. A wildcard A record
points the whole subdomain space at the VPS, so adding a service must not require DNS work. Each
new service needs (1) HTTP routing by hostname and (2) a valid TLS certificate, issued and renewed
without manual steps. New services are added often, and the friction of adding one should be near
zero — ideally no central config file to edit. The decision is which component sits at the edge
terminating TLS and routing requests.
Decision¶
Traefik v3. Its container-label service discovery is the decisive property: a new service declares its own host rule, TLS, and middleware as labels on its container, and Traefik picks it up with no central file to touch and no reload to orchestrate. Combined with built-in ACME, this makes "add a service" a one-file change inside that service's own compose definition. Caddy was the close runner-up and would also have automated TLS, but Traefik's label-driven dynamic configuration and middleware ecosystem fit the "many small services, each self-describing" shape of the lab better.
Consequences¶
- A new service is published by adding labels — no central router edits, no DNS, no manual certs. ACME issuance and renewal are fully automated, and the routing dashboard gives visibility into what is exposed and how.
- Traefik's label/router/middleware model has a real learning curve, and its dynamic nature can hide a misconfiguration (a service silently not matching a router) in a way a static nginx vhost would not. v3 introduced breaking changes from v2, and online config examples are often still v2 and need translation. A single proxy at the edge is also a shared dependency — a Traefik misconfig can affect every service at once.
- This decision is coupled to ADR-0004 (ACME challenge type), which Traefik performs on the lab's behalf. Caddy remains a viable fallback if Traefik's complexity ever outweighs its flexibility at this scale — revisit if the label-driven model becomes a net source of confusion, or a need arises that Traefik handles poorly and a simpler proxy would handle cleanly.
Alternatives considered¶
- Nginx — rejected: vhosts are static files and TLS needs a separate certbot loop; adding a service means editing central config and reloading.
- Caddy — close runner-up: automatic HTTPS out of the box with very simple config, but a smaller middleware ecosystem than Traefik's label-driven model offers.
- HAProxy — rejected: an excellent load balancer, but heavier to configure for this label-driven, per-service-TLS use case.