Wildcard-SSL-Zertifikate mit Traefik und Let’s Encrypt automatisieren: DNS-Challenge mit Cloudflare, Hetzner DNS und anderen Providern. Ein Zertifikat für alle Subdomains.
💡 Hinweis: Dieses Tutorial setzt voraus, dass Traefik v3 bereits auf eurem Server läuft und ihr die HTTP-Challenge funktionsfähig habt. Ihr ergänzt jetzt die DNS-Challenge.
Einleitung — Warum Wildcard-SSL?
Mit der Standard-HTTP-Challenge holt Traefik für jede Subdomain ein eigenes Zertifikat. Bei zehn Self-Hosted-Diensten habt ihr zehn Zertifikate, die einzeln erneuert werden müssen. Funktioniert — aber:
- Let’s Encrypt Rate-Limit kann bei vielen neuen Domains zuschlagen (50 Zertifikate / Domain / Woche)
- Interne Subdomains (nicht öffentlich erreichbar) bekommen kein Zertifikat per HTTP-Challenge
- HTTP-Port 80 muss erreichbar sein — was bei manchen Setups nicht erwünscht ist
Mit der DNS-Challenge holt ihr ein einziges Wildcard-Zertifikat (*.example.com), das automatisch für alle Subdomains gilt. Vorteile:
- Ein Zertifikat für alle Subdomains
- Funktioniert auch für interne Services, die von außen nicht erreichbar sind
- Port 80 nicht zwingend nötig
- Keine Rate-Limit-Probleme bei vielen neuen Subdomains
Die DNS-Challenge funktioniert über die API eures DNS-Providers — Traefik trägt einen TXT-Record bei euch ein, Let’s Encrypt verifiziert ihn, und das Zertifikat wird ausgestellt.
In diesem Guide zeigen wir das Setup mit Cloudflare und Hetzner DNS — beides häufig genutzte Provider im deutschen Raum. Andere Provider funktionieren analog.
Voraussetzungen
- Traefik v3 läuft mit funktionierender HTTP-Challenge — siehe Traefik-Tutorial
- Eine Domain bei einem unterstützten DNS-Provider — Liste: Traefik DNS Providers
- API-Zugang zum DNS-Provider
- Eine Subdomain wie
*.example.com— wird gleich konfiguriert
Variante A: Cloudflare
Cloudflare ist gratis und der häufigste Provider für Self-Hoster. Wir richten zuerst hier ein.
Schritt 1: Cloudflare-API-Token erstellen
Im Cloudflare-Dashboard:
- My Profile → API Tokens → Create Token
- Custom token → Get started
- Konfiguration:
- Token name:
traefik-dns-challenge - Permissions:
Zone — DNS — EditZone — Zone — Read
- Zone Resources:
Include — Specific zone — example.com - TTL: unbegrenzt oder z.B. 1 Jahr
- Token name:
- Continue to summary → Create Token
Token sofort kopieren — er wird nur einmal angezeigt.
⚠️ Wichtig: Verwendet niemals euren globalen API-Key. Erstellt immer einen scoped Token mit minimalen Berechtigungen für genau diese Zone. Falls der Token kompromittiert wird, ist nur eure DNS-Zone betroffen, nicht euer ganzer Account.
Schritt 2: Token in Traefik bereitstellen
sudo nano /opt/traefik/.envInhalt:
CF_DNS_API_TOKEN=EUER_CLOUDFLARE_TOKENBerechtigungen restriktiv setzen:
sudo chmod 600 /opt/traefik/.envSchritt 3: docker-compose.yml erweitern
sudo nano /opt/traefik/docker-compose.ymlIm services.traefik-Block ergänzen:
services:
traefik:
image: traefik:v3.2
# ... bestehende Config ...
env_file:
- ./.env
environment:
- CF_DNS_API_TOKEN=${CF_DNS_API_TOKEN}Schritt 4: traefik.yml mit Cloudflare-Resolver erweitern
sudo nano /opt/traefik/config/traefik.ymlIm certificatesResolvers-Block:
certificatesResolvers:
letsencrypt:
acme:
email: euer@example.com
storage: /certs/acme.json
httpChallenge:
entryPoint: web
cloudflare:
acme:
email: euer@example.com
storage: /certs/acme.json
dnsChallenge:
provider: cloudflare
resolvers:
- "1.1.1.1:53"
- "8.8.8.8:53"
# Wartezeit für DNS-Propagation (in Sekunden)
delayBeforeCheck: 30💡 Hinweis:
delayBeforeCheck: 30ist ein Sicherheitspuffer. Cloudflare propagiert TXT-Records meist in 1-2 Sekunden. Bei langsameren Providern (manche Registrare) kann ein höherer Wert wie60oder120nötig sein.
Schritt 5: Traefik neu starten
cd /opt/traefik
sudo docker compose up -d
sudo docker compose logs -f traefik | grep -i acmeBis hier holt Traefik noch keine Wildcard-Zertifikate — es weiß nur, dass es zwei Resolver gibt (letsencrypt und cloudflare).
Schritt 6: Wildcard-Zertifikat anfordern
Wir holen das Wildcard-Zertifikat direkt im Traefik-Container über Labels — nicht erst beim ersten Service.
sudo nano /opt/traefik/docker-compose.ymlIm Traefik-Service Labels ergänzen:
labels:
# ... bestehende Labels ...
# Wildcard-Zertifikat erzwingen
- "traefik.http.routers.dashboard.tls.certresolver=cloudflare"
- "traefik.http.routers.dashboard.tls.domains[0].main=example.com"
- "traefik.http.routers.dashboard.tls.domains[0].sans=*.example.com"Container neu starten:
sudo docker compose up -d
sudo docker compose logs -f traefik | grep -iE 'acme|cloudflare|certificate'Beim ersten Mal dauert das 30-60 Sekunden. Erfolgreich, wenn ihr Certificates obtained for [example.com *.example.com] seht.
✅ Geschafft! Ihr habt ein Wildcard-Zertifikat. Es gilt für
example.complus alle Subdomains (anything.example.com).
Variante B: Hetzner DNS
Wenn ihr eure Domain über Hetzner DNS verwaltet, geht es ähnlich.
Schritt 1: Hetzner-API-Token erstellen
Im Hetzner DNS Console:
- Oben rechts auf euer Profil → API Tokens
- Create access token
- Token-Beschreibung eingeben (z.B.
traefik-dns-challenge) → Create access token
Token sofort kopieren.
Schritt 2: Token in .env
sudo nano /opt/traefik/.envHinzufügen:
HETZNER_API_KEY=EUER_HETZNER_TOKENSchritt 3: traefik.yml-Resolver
certificatesResolvers:
hetzner:
acme:
email: euer@example.com
storage: /certs/acme.json
dnsChallenge:
provider: hetzner
resolvers:
- "1.1.1.1:53"
- "8.8.8.8:53"
delayBeforeCheck: 30Schritt 4: docker-compose.yml ergänzen
services:
traefik:
environment:
- HETZNER_API_KEY=${HETZNER_API_KEY}Schritt 5: Anwendung wie bei Cloudflare
In den Labels statt cloudflare jetzt hetzner als Resolver verwenden:
- "traefik.http.routers.dashboard.tls.certresolver=hetzner"Variante C: Andere DNS-Provider
Traefik unterstützt 80+ DNS-Provider. Das Setup-Muster ist immer gleich:
- API-Token / Credentials beim Provider erstellen
- In
.envablegen environmentim Compose setzen- Resolver in
traefik.ymldefinieren - Labels auf den neuen Resolver verweisen
Eine vollständige Liste mit den jeweils nötigen Environment-Variablen findet ihr in der Traefik-Dokumentation. Beispiele für gängige Provider im deutschen Raum:
| Provider | Resolver-Name | Env-Variablen |
|---|---|---|
| Cloudflare | cloudflare | CF_DNS_API_TOKEN |
| Hetzner DNS | hetzner | HETZNER_API_KEY |
| INWX | inwx | INWX_USERNAME, INWX_PASSWORD |
| Netcup | netcup | NETCUP_CUSTOMER_NUMBER, NETCUP_API_KEY, NETCUP_API_PASSWORD |
| IONOS | ionos | IONOS_API_KEY |
| Strato | (kein offizieller Support) | — |
| OVH | ovh | OVH_* (Application Key, Secret, Consumer Key) |
| DigitalOcean | digitalocean | DO_AUTH_TOKEN |
⚠️ Wichtig: Manche Provider (Strato, einige deutsche Registrare) bieten keine API. In dem Fall könnt ihr keine DNS-Challenge nutzen — entweder zu Cloudflare wechseln (Domain bleibt, nur DNS umstellen) oder bei der HTTP-Challenge bleiben.
Schritt 7: Wildcard für eure Services nutzen
Sobald ihr das Wildcard-Zertifikat einmal habt, müssen einzelne Services es nur noch referenzieren — nicht erneut anfordern.
Beispiel-Service mit Wildcard
services:
whoami:
image: traefik/whoami
networks:
- traefik-public
labels:
- "traefik.enable=true"
- "traefik.http.routers.whoami.rule=Host(`whoami.example.com`)"
- "traefik.http.routers.whoami.entrypoints=websecure"
- "traefik.http.routers.whoami.tls=true"
# Hier den Wildcard-Resolver nutzen
- "traefik.http.routers.whoami.tls.certresolver=cloudflare"
- "traefik.http.services.whoami.loadbalancer.server.port=80"
networks:
traefik-public:
external: <strong>true</strong>Container starten:
sudo docker compose up -dTraefik erkennt: Diese Subdomain ist von *.example.com abgedeckt → kein neuer Zertifikat-Request, das vorhandene Wildcard wird genutzt.
💡 Tipp: Im Traefik-Dashboard → Routers seht ihr für jeden Router, welches Zertifikat verwendet wird. Bei korrektem Setup sollte überall
*.example.comals Cert-Common-Name stehen.
Schritt 8: Default-Resolver setzen — optional
Damit ihr nicht bei jedem Service den Resolver einzeln eintragen müsst, könnt ihr cloudflare als Default für alle Services setzen.
In traefik.yml:
entryPoints:
websecure:
address: ":443"
http:
tls:
certResolver: cloudflare
domains:
- main: example.com
sans:
- "*.example.com"Damit gilt: Jeder Service auf websecure-Entry-Point nutzt automatisch das Wildcard-Zertifikat. Ihr braucht in den Service-Labels keinen Resolver mehr anzugeben.
Schritt 9: Verifizieren
Nach dem Restart prüfen, ob das Wildcard wirklich greift:
echo | openssl s_client -connect whoami.example.com:443 -servername whoami.example.com <strong>2</strong>>/dev/null \
| openssl x509 -noout -issuer -subjectErwartete Ausgabe (gekürzt):
issuer=C = US, O = Let's Encrypt, CN = R10
subject=CN = *.example.comsubject=CN = *.example.com heißt: Wildcard-Zertifikat aktiv.
Zusammenfassung & Checkliste
| Schritt | Status |
|---|---|
| Traefik v3 läuft mit HTTP-Challenge | ☐ |
| API-Token bei DNS-Provider erstellt | ☐ |
Token in /opt/traefik/.env mit chmod 600 | ☐ |
environment im Compose gesetzt | ☐ |
DNS-Resolver in traefik.yml definiert | ☐ |
| Wildcard-Zertifikat erfolgreich angefordert | ☐ |
| Test-Service nutzt Wildcard-Zertifikat | ☐ |
| Default-Resolver auf Wildcard umgestellt (optional) | ☐ |
Verifiziert per openssl s_client | ☐ |
Troubleshooting
„Could not obtain certificates: timeout“
- DNS-Propagation langsam?
delayBeforeCheckauf60oder120erhöhen - Token hat keine
Edit DNS-Berechtigung? Permissions im Cloudflare-Dashboard prüfen
„Authentication failed“
CF_DNS_API_TOKENkorrekt gesetzt?sudo docker compose exec traefik env | grep CF- Token ist scoped auf die richtige Zone?
„DNS problem: NXDOMAIN looking up TXT for _acme-challenge.example.com“
- Bei Cloudflare: Steht eure Zone wirklich unter Cloudflare-DNS?
dig NS example.comzeigt es. - Bei anderen Providern: TTL der TXT-Records prüfen — manche Provider ignorieren die DNS-Challenge bei zu hoher TTL
„rateLimited“ Error von Let’s Encrypt
- Pro Domain pro Woche max. 50 Zertifikate. Bei vielen Versuchen erreicht?
- Mit Wildcard ist das praktisch unmöglich — meist liegt es an HTTP-Challenge-Spam
Wildcard wird ausgestellt, aber Service nutzt es nicht
- In Service-Labels:
tls.certresolverkorrekt? - Default-Resolver in
traefik.ymlkorrekt gesetzt? acme.jsonBerechtigungen:chmod 600
Cloudflare Proxy (orange Wolke) verhindert HTTPS
- DNS-Challenge funktioniert auch mit aktivem Cloudflare-Proxy
- Aber: Cloudflare-SSL-Modus muss auf Full (strict) stehen, sonst Endlosschleife
Nächste Schritte
- Authentik als Forward-Auth in Traefik — SSO für alle Services hinter Traefik
- Crowdsec-Bouncer für Traefik — Brute-Force-Schutz auf Layer 7
- TCP/UDP-Routing mit Traefik — Auch Datenbanken & Game-Server
- Multi-Domain-Setups — Mehrere Wildcard-Zertifikate parallel
Habt ihr Fragen oder Probleme? Schreibt es in die Kommentare — ich helfe gerne!