Zum Inhalt

Traefik v3 als Reverse Proxy mit automatischen Let's-Encrypt-Zertifikaten per Docker einrichten

Veröffentlicht am 24. September 2026 · Geschätzte Lesezeit: 8 Minuten

Traefik ist ein Reverse Proxy, der Container im Docker-Netzwerk automatisch erkennt und per Label gesteuert Routen und HTTPS-Zertifikate bereitstellt. Anders als bei Nginx oder Caddy pflegst du keine manuellen Konfigurationsdateien pro Dienst – neue Container werden mit wenigen Labels freigeschaltet. Traefik bezieht selbstständig Let's-Encrypt-Zertifikate und erneuert sie. Die Einrichtung von Traefik mit einem ersten geschützten Dienst dauert etwa 30 bis 45 Minuten; eine eigene Domain und korrekte DNS-Einträge werden vorausgesetzt.[1][9]

Voraussetzungen

  • Ein Linux-Server mit Docker und Docker Compose
  • Die Ports 80 und 443 sind auf dem Server frei
  • Eine eigene öffentliche Domain mit Zugriff auf die DNS-Einstellungen
  • Ports 80 und 443 sind im Router auf den Docker-Server weitergeleitet
  • htpasswd installiert (Package apache2-utils unter Debian/Ubuntu)

1. Belegte Ports prüfen

Prüfe, ob Port 80 und 443 auf dem Docker-Server noch frei sind:

sudo ss -ltnp | grep -E ':(80|443)\b'

Bleibt die Ausgabe leer, sind die Ports frei. Läuft dort bereits ein anderer Reverse Proxy, musst du ihn zuerst stoppen, da nur ein Dienst gleichzeitig auf denselben Ports lauschen kann.

2. Docker-Netzwerk und Arbeitsordner anlegen

Erstelle ein gemeinsames Docker-Netzwerk für Traefik und alle Dienste, die später über Traefik erreichbar sein sollen:

docker network create traefik-public

Lege den Projektordner an und wechsle hinein:

mkdir -p ~/traefik && cd ~/traefik

Lege die leere ACME-Datei für Let's-Encrypt-Zertifikate an. Traefik startet nur, wenn acme.json die Berechtigung 600 besitzt:[1]

touch acme.json && chmod 600 acme.json

3. Compose-Datei erstellen

Lege im Ordner ~/traefik eine Datei compose.yaml mit diesem Inhalt an:

services:
  traefik:
    image: traefik:v3.7
    container_name: traefik
    restart: unless-stopped
    security_opt:
      - no-new-privileges:true
    ports:
      - "80:80"
      - "443:443"
    volumes:
      # Docker-Socket für die automatische Service-Erkennung (nur lesen!)
      - /var/run/docker.sock:/var/run/docker.sock:ro
      # Let's-Encrypt-Zertifikatsspeicher
      - ./acme.json:/acme.json
    environment:
      - TZ=Europe/Berlin
    command:
      # Dashboard (NICHT --api.insecure=true verwenden!)
      - "--api.dashboard=true"

      # Entrypoints
      - "--entrypoints.web.address=:80"
      - "--entrypoints.websecure.address=:443"

      # HTTP → HTTPS-Weiterleitung (global)
      - "--entrypoints.web.http.redirections.entryPoint.to=websecure"
      - "--entrypoints.web.http.redirections.entryPoint.scheme=https"

      # Docker-Provider: nur explizit freigegebene Container routen
      - "--providers.docker=true"
      - "--providers.docker.exposedbydefault=false"

      # ACME / Let's Encrypt – Platzhalter durch eigene Daten ersetzen
      - "--certificatesresolvers.letsencrypt.acme.email=<deine-email@example.de>"
      - "--certificatesresolvers.letsencrypt.acme.storage=/acme.json"
      - "--certificatesresolvers.letsencrypt.acme.httpchallenge.entrypoint=web"

networks:
  default:
    external:
      name: traefik-public

Erklärung der Platzhalter und Optionen:[2][3]

Wert Bedeutung
traefik:v3.7 Aktuelle stabile Version (Stand September 2026; ggf. auf neuere Patch-Version wie v3.7.13 aktualisieren)
<deine-email@example.de> E-Mail-Adresse für den Let's-Encrypt-Account (wichtig für Ablaufbenachrichtigungen)
exposedbydefault=false Nur Container mit dem Label traefik.enable=true werden geroutet – Sicherheit
httpchallenge.entrypoint=web HTTP-01-Challenge benötigt einen erreichbaren Port 80
/var/run/docker.sock:ro Nur-Lese-Zugriff auf die Docker-API (Sicherheit!)

4. Compose-Datei prüfen und starten

Prüfe die Syntax im Projektordner:

cd ~/traefik && docker compose config --quiet

Starte Traefik im Hintergrund:

docker compose up -d

Prüfe den Zustand:

docker compose ps

Sieh dir die ersten Protokollzeilen an, um sicherzustellen, dass Traefik ohne Fehler startet:

docker compose logs --tail=50 traefik

Bei einem Fehler wegen acme.json prüfe die Berechtigung erneut mit ls -l acme.json.

5. Dashboard mit Basic Auth absichern

Das Dashboard von Traefik ist auf Port 443 erreichbar, aber noch ohne Authentifizierung. Erstelle einen Basic-Auth-Benutzer. Ersetze <dein-passwort> durch ein sicheres Passwort:[4]

echo $(htpasswd -nB admin) | sed -e 's/\$/\$\$/g'

Der Befehl gibt eine Zeile wie admin:$$2y$$05$$... aus. Kopiere diesen Wert – die doppelten Dollarzeichen ($$) sind notwendig, damit Docker Compose sie nicht als Variable interpretiert.

Öffne ~/traefik/compose.yaml und ergänze im command:-Block vor dem ACME-Teil die Dashboard-Weiterleitung:[4][5]

    command:
      # …vorhandene Einträge…
      - "--api.dashboard=true"

      # Dashboard-Route und Basic-Auth-Middleware
      - "--entrypoints.websecure.http.middlewares=dashboard-auth@docker"

Ergänze außerdem direkt unter command: als neuen Abschnitt. Erstelle dafür eine spezielle Middleware-Konfiguration, indem du zusätzlich diese Labels an den Traefik-Container anhängst – am einfachsten ergänzt du im services.traefik:-Block einen labels:-Abschnitt:[4]

services:
  traefik:
    # …vorhandene Konfiguration…
    labels:
      # Dashboard-Router: leitet dashboard.DEINEDOMAIN.DE auf die interne API
      - "traefik.enable=true"
      - "traefik.http.routers.dashboard.rule=Host(`traefik.<deine-domain.de>`)"
      - "traefik.http.routers.dashboard.entrypoints=websecure"
      - "traefik.http.routers.dashboard.tls.certresolver=letsencrypt"
      - "traefik.http.routers.dashboard.service=api@internal"
      - "traefik.http.routers.dashboard.middlewares=dashboard-auth"

      # Basic-Auth-Middleware – HIER den generierten Hash eintragen
      - "traefik.http.middlewares.dashboard-auth.basicauth.users=<generierter-hash>"

Ersetze <deine-domain.de> durch deine echte Domain und <generierter-hash> durch die Ausgabe von htpasswd (die Zeile mit admin:$$2y$$…).

Setze das Compose-File neu um:

cd ~/traefik && docker compose up -d

Dashboard nie ohne Auth betreiben

Schalte das Dashboard nur mit Basic Auth oder einer anderen Authentifizierung frei. --api.insecure=true (Port 8080 ohne Passwort) ist ausschließlich für Entwicklungsumgebungen gedacht und niemals produktiv einzusetzen.[1]

6. DNS-Eintrag und Staging-Test (optional)

Lege beim DNS-Anbieter einen A-Eintrag für traefik.<deine-domain.de> an, der auf die öffentliche IPv4-Adresse deines Internetanschlusses zeigt. Prüfe die Auflösung:[5]

getent ahostsv4 traefik.<deine-domain.de>

Bevor du ein echtes Let's-Encrypt-Zertifikat anforderst, kannst du mit dem Staging-Server testen. Dadurch vermeidest du Rate Limits bei Fehlversuchen (maximal 5 Zertifikate pro identischem Domain-Satz pro Woche[8]). Ergänze temporär:[2]

      - "--certificatesresolvers.letsencrypt.acme.caserver=https://acme-staging-v02.api.letsencrypt.org/directory"

Starte Traefik neu und prüfe die Logs auf eine erfolgreiche Staging-Ausstellung. Entferne die Zeile danach wieder für das echte Zertifikat und lösche die acme.json (wird automatisch neu angelegt), starte Traefik erneut.

7. Wer ist da? Testdienst starten

Starte einen einfachen Testcontainer, um die automatische Erkennung zu prüfen. Erstelle eine separate Compose-Datei whoami.yml:

services:
  whoami:
    image: traefik/whoami
    container_name: whoami
    labels:
      - "traefik.enable=true"
      - "traefik.http.routers.whoami.rule=Host(`whoami.<deine-domain.de>`)"
      - "traefik.http.routers.whoami.entrypoints=websecure"
      - "traefik.http.routers.whoami.tls.certresolver=letsencrypt"

networks:
  default:
    external:
      name: traefik-public

Starte den Testcontainer:

docker compose -f whoami.yml up -d

Es ist kein Neustart von Traefik nötig – die Erkennung erfolgt automatisch über den Docker-Socket.[1]

8. HTTPS von außen testen

Lege den DNS-Eintrag whoami.<deine-domain.de> an, der auf deine öffentliche IP zeigt. Prüfe dann von einem externen Gerät (Mobilfunk):

curl -s -o /dev/null -w "%{http_code} %{ssl_verify_result}" https://whoami.<deine-domain.de>

Erwartete Ausgabe: 200 0 (HTTP 200 + SSL-Verifikation erfolgreich).

Prüfe auch die HTTP-zu-HTTPS-Weiterleitung:

curl -s -o /dev/null -w "%{redirect_url}" http://whoami.<deine-domain.de>

Erwarte eine HTTPS-URL als Antwort.

Öffne https://traefik.<deine-domain.de> im Browser. Nach Basic-Auth-Login siehst du das Dashboard mit den Einträgen für whoami und dashboard.

9. Einen weiteren Dienst anbinden

Jeder Docker-Container, der über Traefik erreichbar sein soll, benötigt: - Das Netzwerk traefik-public - Das Label traefik.enable=true - Eine Router-Regel mit Host und TLS-Zertifikatsresolver

Beispiel für einen beliebigen Dienst. Ersetze dienstname durch den Compose-Dienstnamen, <deine-domain.de> durch deine Domain und <container-port> durch den internen Port des Containers (z. B. 3000 für ein Webfrontend oder 1880 für Node-RED):

services:
  dienstname:
    # …vorhandene Konfiguration…
    networks:
      - traefik-public
    labels:
      - "traefik.enable=true"
      - "traefik.http.routers.dienstname.rule=Host(`dienst.<deine-domain.de>`)"
      - "traefik.http.routers.dienstname.entrypoints=websecure"
      - "traefik.http.routers.dienstname.tls.certresolver=letsencrypt"
      - "traefik.http.routers.dienstname.middlewares=dashboard-auth"

networks:
  traefik-public:
    external: true

Der interne Port des Dienstes muss nicht extra angegeben werden, wenn der Container nur einen Port exponiert – Traefik erkennt ihn automatisch. Bei mehreren Ports ergänzt du traefik.http.services.dienstname.loadbalancer.server.port=<container-port>. Ersetze <container-port> durch den tatsächlichen internen Port (z. B. 8080).

10. Backup und Rückweg

Sichere die wichtigsten Dateien und das ACME-Verzeichnis:[4]

cd ~/traefik
docker compose down
tar -czf "traefik-backup-$(date +%F).tar.gz" compose.yaml acme.json
docker compose up -d

Das Archiv enthält: - compose.yaml – deine gesamte Traefik-Konfiguration - acme.json – alle Let's-Encrypt-Zertifikate plus Account-Key (ohne dieses File musst du alle Zertifikate neu ausstellen lassen)

Rückweg: Stoppe Traefik, stelle die alte compose.yaml und acme.json aus dem Backup wieder her und starte Traefik neu:

cd ~/traefik && docker compose down
tar -xzf traefik-backup-2026-09-24.tar.gz
docker compose up -d

11. Risiken

  1. Docker-Socket-Zugriff: Traefik liest den Docker-Socket, um Container zu erkennen. Ein Angreifer, der Traefik kompromittiert, hat über den Socket potenziell Root-Zugriff auf den Host. Milderung: Der Socket ist nur lesend eingebunden (:ro), no-new-privileges:true ist gesetzt. Für höhere Sicherheit kannst du einen Docker-Socket-Proxy vorschalten.

  2. acme.json sichern: Ohne die ACME-Datei müssen alle Zertifikate neu ausgestellt werden. Rate Limits erlauben maximal 5 Duplikat-Zertifikate pro Woche für denselben Domain-Satz.[8] Sichere die Datei regelmäßig.

  3. exposedByDefault=false nicht vergessen: Ohne diese Option werden alle Container im Netzwerk traefik-public automatisch exponiert – auch Datenbanken und nicht-öffentliche Dienste.[3]

  4. Dashboard ohne Auth: --api.insecure=true gibt das Dashboard ohne Passwort frei. Das ist nur für lokale Entwicklungstests akzeptabel. In der Produktion immer mit Basic Auth oder einem externen Identity Provider schützen.[1]

12. Typische Fehler

Fehler Ursache Lösung
Traefik startet nicht acme.json hat falsche Rechte chmod 600 acme.json
Zertifikat kommt nicht Port 80 nicht von außen erreichbar Firewall prüfen: sudo ufw allow 80/tcp; Portweiterleitung im Router kontrollieren
Dashboard zeigt 404 Fehlendes Label traefik.http.routers.dashboard.service=api@internal Label ergänzen
Dashboard 401 Basic-Auth-Hash falsch escaped (einfaches $ statt $$) Hash mit sed neu generieren: echo $(htpasswd -nB admin) \| sed -e 's/\$/\$\$/g'
Keine Route trotz Label exposedbydefault=false und traefik.enable=true fehlt Beide Labels am Container setzen
Container nicht erreichbar Container ist nicht im Netzwerk traefik-public docker network connect traefik-public <container> (ersetze <container> durch den Containernamen) oder in Compose ergänzen

Fertig

Traefik läuft und erkennt neue Docker-Container automatisch. Deine Einrichtung ist erfolgreich, wenn:

  1. Traefik läuft: docker ps --filter name=traefik zeigt den Container als Up
  2. Ein Let's-Encrypt-Zertifikat ausgestellt wurde: docker compose logs traefik | grep -i "certificate obtained"
  3. Der Testdienst antwortet per HTTPS: curl -I https://whoami.<deine-domain.de> liefert Status 200
  4. Die HTTP-zu-HTTPS-Weiterleitung funktioniert: curl -s -o /dev/null -w "%{redirect_url}" http://whoami.<deine-domain.de> liefert eine HTTPS-URL
  5. Das Dashboard unter https://traefik.<deine-domain.de> erreichbar ist und sich anmelden lässt

Einen neuen Dienst schaltest du künftig mit nur drei Labels frei – kein Neustart von Traefik, kein Editieren einer Konfigurationsdatei, keine manuelle Zertifikatsverwaltung.

Sources

[1] https://doc.traefik.io/traefik/getting-started/docker — Traefik offizieller Docker-Quickstart [2] https://doc.traefik.io/traefik/reference/install-configuration/tls/certificate-resolvers/acme — Traefik ACME-Zertifikatsresolver-Referenz [3] https://doc.traefik.io/traefik/reference/install-configuration/providers/docker — Traefik Docker-Provider-Referenz [4] https://selfhosting.sh/apps/traefik — selfhosting.sh: Traefik-Komplettanleitung [5] https://linuxjunkies.org/guides/install-traefik-reverse-proxy — linuxjunkies: Traefik Reverse Proxy Guide [8] https://letsencrypt.org/docs/rate-limits — Let's Encrypt: Rate Limits [9] https://doc.traefik.io/traefik/deprecation/releases — Traefik: Versions- und Supportübersicht