Traefik Wildcard-SSL mit Let’s Encrypt DNS-Challenge — Cloudflare, Hetzner & Co.

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.

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:

  1. My Profile → API Tokens → Create Token
  2. Custom tokenGet started
  3. Konfiguration:
    • Token name: traefik-dns-challenge
    • Permissions:
      • Zone — DNS — Edit
      • Zone — Zone — Read
    • Zone Resources: Include — Specific zone — example.com
    • TTL: unbegrenzt oder z.B. 1 Jahr
  4. 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/.env

Inhalt:

CF_DNS_API_TOKEN=EUER_CLOUDFLARE_TOKEN

Berechtigungen restriktiv setzen:

sudo chmod 600 /opt/traefik/.env

Schritt 3: docker-compose.yml erweitern

sudo nano /opt/traefik/docker-compose.yml

Im 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.yml

Im 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: 30 ist ein Sicherheitspuffer. Cloudflare propagiert TXT-Records meist in 1-2 Sekunden. Bei langsameren Providern (manche Registrare) kann ein höherer Wert wie 60 oder 120 nötig sein.

Schritt 5: Traefik neu starten

cd /opt/traefik
sudo docker compose up -d
sudo docker compose logs -f traefik | grep -i acme

Bis 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.yml

Im 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.com plus 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:

  1. Oben rechts auf euer Profil → API Tokens
  2. Create access token
  3. Token-Beschreibung eingeben (z.B. traefik-dns-challenge) → Create access token

Token sofort kopieren.

Schritt 2: Token in .env

sudo nano /opt/traefik/.env

Hinzufügen:

HETZNER_API_KEY=EUER_HETZNER_TOKEN

Schritt 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: 30

Schritt 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:

  1. API-Token / Credentials beim Provider erstellen
  2. In .env ablegen
  3. environment im Compose setzen
  4. Resolver in traefik.yml definieren
  5. 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:

ProviderResolver-NameEnv-Variablen
CloudflarecloudflareCF_DNS_API_TOKEN
Hetzner DNShetznerHETZNER_API_KEY
INWXinwxINWX_USERNAME, INWX_PASSWORD
NetcupnetcupNETCUP_CUSTOMER_NUMBER, NETCUP_API_KEY, NETCUP_API_PASSWORD
IONOSionosIONOS_API_KEY
Strato(kein offizieller Support)
OVHovhOVH_* (Application Key, Secret, Consumer Key)
DigitalOceandigitaloceanDO_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 -d

Traefik 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.com als 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 -subject

Erwartete Ausgabe (gekürzt):

issuer=C = US, O = Let's Encrypt, CN = R10
subject=CN = *.example.com

subject=CN = *.example.com heißt: Wildcard-Zertifikat aktiv.


Zusammenfassung & Checkliste

SchrittStatus
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? delayBeforeCheck auf 60 oder 120 erhöhen
  • Token hat keine Edit DNS-Berechtigung? Permissions im Cloudflare-Dashboard prüfen

„Authentication failed“

  • CF_DNS_API_TOKEN korrekt 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.com zeigt 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.certresolver korrekt?
  • Default-Resolver in traefik.yml korrekt gesetzt?
  • acme.json Berechtigungen: 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!

Kommentar hinterlassen