This episode covers wildcard certificates for all subdomains with the DNS-01 challenge: how TXT records work, DNS provider integration such as Cloudflare with an API token, environment variable configuration, multi-domain SANs, and troubleshooting propagation timeouts and resolvers.

A wildcard certificate *.example.com protects all subdomains at once — one certificate, no need to register every name. Episode 16 covers how to get one through the DNS-01 challenge, the only challenge that supports wildcards, plus integration with DNS providers such as Cloudflare and Route53.
The challenge: DNS-01 requires the ability to write TXT records in your domain's DNS programmatically. Traefik does this through the lego library, which supports dozens of providers. In this episode we practice with Cloudflare as an example, complete with environment variable configuration and troubleshooting.
The HTTP-01 and TLS-ALPN-01 challenges run per-domain: for *.example.com, there is no single host that represents the wildcard. DNS-01 works at the domain name level: Let's Encrypt asks you to place a token in the _acme-challenge.example.com TXT record. By controlling DNS, you prove ownership of the entire domain at once.
The complete flow:
*.example.com._acme-challenge.example.com TXT record at the DNS provider.Because no inbound connection is needed, DNS-01 can also be used for servers behind full NAT.
To use the Cloudflare provider, create an API Token with Zone.DNS:Edit permission on the target zone. Store the token as an environment variable — never write it in a version-controlled configuration file:
services:
traefik:
image: traefik:v3
environment:
- CLOUDFLARE_DNS_API_TOKEN=${CLOUDFLARE_DNS_API_TOKEN}
volumes:
- /var/run/docker.sock:/var/run/docker.sock:ro
- ./config/traefik.yml:/etc/traefik/traefik.yml:ro
- ./acme.json:/etc/traefik/acme.jsonThe token is taken from .env on the host during docker compose up. The resolver configuration uses DNS-01 with the Cloudflare provider:
certificatesResolvers:
letsencrypt:
acme:
email: admin@example.com
storage: /etc/traefik/acme.json
dnsChallenge:
provider: cloudflare
resolvers:
- "1.1.1.1:53"
- "8.8.8.8:53"provider: cloudflare: tells lego which provider to use.resolvers: the DNS servers Let's Encrypt uses when verifying the TXT record — list servers that are reachable and accurate.For other providers, the env var token differs but the pattern is the same: ROUTE53_ACCESS_KEY_ID, AZURE_CLIENT_SECRET, GANDI_API_KEY, and so on. The _acme-challenge record pattern is set automatically by lego.
A single router can request a certificate with a combination of specific domains and wildcards at once:
services:
portal:
image: nginx:alpine
labels:
- traefik.enable=true
- traefik.http.routers.portal.rule=HostRegexp(`{subdomain:[a-z]+}.example.com`)
- traefik.http.routers.portal.entrypoints=websecure
- traefik.http.routers.portal.tls.certresolver=letsencrypt
- traefik.http.routers.portal.tls.domains[0].main=example.com
- traefik.http.routers.portal.tls.domains[0].sans=*.example.com
- traefik.http.routers.portal.service=portal-svc
- traefik.http.services.portal-svc.loadbalancer.server.port=80The HostRegexp rule makes all *.example.com subdomains enter this router. The tls.domains[0].main label requests a certificate for example.com plus the wildcard SAN *.example.com. Traefik merges requests from all routers using the same resolver, so overlapping domains are not issued as duplicates.
The most common DNS-01 error is a propagation timeout: the TXT record has been created, but the verification server has not seen it yet because DNS has not spread. Handling it:
dnsPropagationTimeout on dnsChallenge (60 seconds default for most providers) to 2-3 minutes._acme-challenge record TTL is low — if the TTL is 1 hour, verification can fail until the old record disappears.dig whether the TXT record is visible from the internet perspective:dig TXT _acme-challenge.example.com
dig TXT _acme-challenge.example.com @1.1.1.1The first dig command uses the default resolver, the second forces resolver 1.1.1.1 — if the results differ, propagation is not complete yet.
If resolvers is not filled in, lego uses built-in resolvers that may not see recent changes. Register trusted resolvers as above. For domains managed across many zones, make sure the token has permission on the correct zone — an unauthorized error is almost always a token scope problem, not a Traefik configuration problem.
Tip
Use mixed subdomain and wildcard combinations wisely: a *.example.com wildcard certificate does not cover example.com itself nor a.b.example.com. Add main and sans explicitly as needed.
Key takeaways:
_acme-challenge TXT record at the DNS provider via lego.Zone.DNS:Edit through an env var.HostRegexp plus tls.domains with main and sans.dig.In episode 17 next we will cover custom certificates & mutual TLS — certificates from the file provider with hot reload, certificate stores and SNI routing, and mTLS for certificate-based client authentication. This is where Traefik turns from a public security guard into a trusted gateway for internal APIs.