Certificates
Traefik obtains all certificates from Let’s Encrypt, using two different challenge methods for two different kinds of hostname.Why two
HTTP-01 requires Let’s Encrypt’s validation servers to reach the host on port 80. The admin surfaces have no public A record — that is the point of them — so HTTP-01 can never validate them. DNS-01 validates by publishing a TXT record instead, which works for any hostname regardless of whether it is publicly reachable. It needs an API-driven way to write that record, which is whatdns-manager provides.
The DNS-01 path
services/dns-manager/app.py exposes three endpoints:
Two implementation details matter enough that they are called out in the source doc as
the mistakes that were actually made:
- The TXT value is not the token. ACME DNS-01 requires
base64url(SHA256(keyAuth)). Publishing thetokenfield verbatim fails validation. dns-managermust return immediately. Traefik handles the propagation wait itself viadelayBeforeCheck: 30s. If the webhook sleeps, Traefik times out instead.
${VAR} in its YAML config, so the ACME email is
hardcoded in traefik.yml while the CA server is passed through Docker Compose, which
does interpolate.
Rate limits
Let’s Encrypt production allows 50 certificates per registered domain per week and 5 validation failures per hostname per hour. Because of that,make deploy-infra uses
staging certificates by default; production certificates require
make deploy-infra-production or the deploy-infra.yml workflow, which sets them
explicitly.
The edge stack is deliberately excluded from push-triggered deploys for the same reason —
recreating Traefik re-requests certificates, and that should be a decision rather than a
side effect of a merge.
Source documents
docs/architecture/certificates.md— full challenge flow, thedns-managerimplementation, troubleshooting for failed issuance and DNS record verificationdocs/reference/dns.md— DNS record inventory and the Hostinger API scripts