Traefik v3 als Reverse Proxy auf Debian 13 mit Docker einrichten: Automatisches SSL, dynamische Konfiguration und Dashboard. Die moderne Alternative zu Nginx für Container-Setups.
💡 Hinweis: Dieses Tutorial setzt voraus, dass du einen normalen Benutzer mit sudo-Rechten verwendest — wie im Tutorial Debian 13 Server absichern beschrieben. Außerdem solltest du Docker installiert haben.
Einleitung — Was ist Traefik?
Wenn ihr Docker-Container hostet, kennt ihr das Problem: Jeder Container will einen eigenen Port, SSL-Zertifikate müssen einzeln eingerichtet werden, und bei jedem neuen Service müsst ihr die Reverse-Proxy-Konfiguration von Hand anpassen. Klassische Lösungen wie Nginx funktionieren — aber sie sind statisch.
Traefik ist ein moderner Reverse Proxy, der speziell für Container-Umgebungen gebaut wurde. Er erkennt automatisch neue Docker-Container, holt sich Let’s-Encrypt-Zertifikate automatisch und konfiguriert das Routing automatisch — alles über Docker-Labels. Kein Reload, kein Restart, keine manuelle Config pro Service.
Was Traefik kann
- Auto-Discovery — Erkennt neue Docker-Container und routet automatisch
- Automatisches SSL — Let’s Encrypt out of the box, inklusive Wildcard-Zertifikaten via DNS-Challenge
- Dynamische Konfiguration — Änderungen ohne Restart
- Web-Dashboard — Übersicht aller Routen, Services und Middlewares
- Middlewares — Rate-Limiting, Auth, Header-Manipulation, Redirects, IP-Whitelist
- Multi-Provider — Docker, Kubernetes, Consul, File, HTTP — alles parallel
- HTTP/3 & TCP/UDP-Routing — Moderne Protokolle nativ unterstützt
- Metrics & Tracing — Prometheus, Jaeger, OpenTelemetry direkt integriert
Traefik vs. Nginx vs. Caddy
| Feature | Traefik v3 | Nginx | Caddy |
|---|---|---|---|
| Auto-Discovery | Ja (Docker, K8s) | Nein | Teilweise |
| Automatisches SSL | Ja | Nur via Certbot | Ja |
| Wildcard SSL (DNS) | Ja | Nur via Certbot | Ja |
| Web-Dashboard | Ja | Nein | Nein |
| Konfiguration | YAML/TOML/Labels | nginx.conf | Caddyfile |
| Performance | Sehr gut | Exzellent | Sehr gut |
| Lernkurve | Mittel | Niedrig | Niedrig |
| Beste Wahl für | Docker-Setups | Bare Metal, hohe Last | Einfache Setups |
In diesem Guide richten wir Traefik v3 von Grund auf ein — von der Installation über das Dashboard bis zum ersten abgesicherten Service inklusive HTTPS-Redirect, Middlewares und Monitoring.
Voraussetzungen
Bevor wir starten, braucht ihr:
- Einen Debian 13 (Trixie) Server — Eingerichtet nach unserem Debian 13 Server-Guide
- Docker & Docker Compose installiert — Wie in unserem Docker-Tutorial beschrieben
- Eine Domain (z.B.
example.com) — für SSL-Zertifikate zwingend nötig - Ports 80 und 443 müssen von außen erreichbar sein
- DNS-Zugriff — A-Records für eure Subdomains
- Eine E-Mail-Adresse für Let’s Encrypt
💡 Hinweis: Falls ihr bereits Nginx oder einen anderen Reverse Proxy auf Port 80/443 laufen habt, müsst ihr diesen vorher stoppen. Zwei Reverse Proxies auf den gleichen Ports gehen nicht.
Firewall-Ports öffnen
sudo ufw allow 80/tcp
sudo ufw allow 443/tcp
sudo ufw status
DNS vorbereiten
Erstellt für jeden Service, den ihr später hinter Traefik betreibt, einen A-Record. Für den Anfang reicht ein Wildcard:
Typ: A
Name: *
Wert: EURE-SERVER-IP
TTL: 3600
Typ: A
Name: @
Wert: EURE-SERVER-IP
TTL: 3600
Wartet ein paar Minuten und prüft die Auflösung:
dig +short traefik.example.com
dig +short whoami.example.com
Traefik installieren
Wir installieren Traefik mit Docker Compose und einer ausgelagerten Konfigurationsdatei. Das ist der sauberste Weg und macht Updates trivial.
Schritt 1: Verzeichnisstruktur anlegen
sudo mkdir -p /opt/traefik/{config,certs,logs}
cd /opt/traefik
sudo touch certs/acme.json
sudo chmod 600 certs/acme.json
Die acme.json speichert eure SSL-Zertifikate. Sie muss chmod 600 haben — sonst weigert sich Traefik zu starten.
Schritt 2: Docker-Netzwerk erstellen
Damit Traefik mit anderen Containern reden kann, brauchen wir ein gemeinsames Docker-Netzwerk:
sudo docker network create traefik-public
Alle Services, die Traefik routen soll, müssen später in diesem Netzwerk sein.
Schritt 3: Statische Konfiguration (traefik.yml)
sudo nano /opt/traefik/config/traefik.yml
Inhalt:
# Globale Einstellungen
global:
checkNewVersion: true
sendAnonymousUsage: false
# Logs
log:
level: INFO
filePath: /logs/traefik.log
accessLog:
filePath: /logs/access.log
bufferingSize: 100
# API & Dashboard
api:
dashboard: true
insecure: false
# Entry Points (eure öffentlichen Ports)
entryPoints:
web:
address: ":80"
http:
redirections:
entryPoint:
to: websecure
scheme: https
permanent: true
websecure:
address: ":443"
http:
tls:
certResolver: letsencrypt
# Provider — wo Traefik nach Konfiguration sucht
providers:
docker:
endpoint: "unix:///var/run/docker.sock"
exposedByDefault: false
network: traefik-public
file:
directory: /config
watch: true
# SSL-Zertifikate via Let's Encrypt
certificatesResolvers:
letsencrypt:
acme:
email: euer@example.com
storage: /certs/acme.json
httpChallenge:
entryPoint: web⚠️ Wichtig: Tauscht
euer@example.comgegen eure echte E-Mail-Adresse. Let’s Encrypt schickt euch dort Warnungen, falls Zertifikate nicht erneuert werden können.
Schritt 4: Dynamische Konfiguration (dynamic.yml)
Diese Datei enthält Middlewares, die wir gleich für die Absicherung nutzen.
sudo nano /opt/traefik/config/dynamic.yml
Inhalt:
http:
middlewares:
# Sicherheits-Header für alle Services
secure-headers:
headers:
frameDeny: true
sslRedirect: true
browserXssFilter: true
contentTypeNosniff: true
forceSTSHeader: true
stsIncludeSubdomains: true
stsPreload: true
stsSeconds: 31536000
customFrameOptionsValue: "SAMEORIGIN"
referrerPolicy: "strict-origin-when-cross-origin"
# Rate-Limiting (100 req/sec, burst 50)
rate-limit:
rateLimit:
average: 100
burst: 50
# Basic Auth fürs Dashboard (Hash gleich generieren)
dashboard-auth:
basicAuth:
users:
- "HIER_KOMMT_GLEICH_DER_HASH_REIN"
# TLS-Optionen — moderne Cipher Suites only
tls:
options:
default:
minVersion: VersionTLS12
sniStrict: true
cipherSuites:
- TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256
- TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256
- TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384
- TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384
- TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305
- TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305
Schritt 5: Basic-Auth-Hash für das Dashboard generieren
Das Dashboard sollte nicht öffentlich erreichbar sein. Wir schützen es mit Basic Auth:
sudo apt install -y apache2-utils
htpasswd -nb admin EUER_PASSWORT
Die Ausgabe sieht so aus: admin:$apr1$xyz...$abc...
Wichtig: In Docker-Compose und YAML-Files muss jedes $ zu $$ verdoppelt werden. In der dynamic.yml (die Traefik direkt liest) reicht ein $. Tauscht HIER_KOMMT_GLEICH_DER_HASH_REIN durch euren Hash:
sudo nano /opt/traefik/config/dynamic.yml
Schritt 6: docker-compose.yml erstellen
sudo nano /opt/traefik/docker-compose.yml
Inhalt:
services:
traefik:
image: traefik:v3.2
container_name: traefik
restart: unless-stopped
security_opt:
- no-new-privileges:true
ports:
- "80:80"
- "443:443"
volumes:
- /var/run/docker.sock:/var/run/docker.sock:ro
- ./config/traefik.yml:/etc/traefik/traefik.yml:ro
- ./config:/config:ro
- ./certs:/certs
- ./logs:/logs
networks:
- traefik-public
labels:
# Aktiviere Traefik für sich selbst
- "traefik.enable=true"
# Dashboard-Router
- "traefik.http.routers.dashboard.rule=Host(`traefik.example.com`)"
- "traefik.http.routers.dashboard.entrypoints=websecure"
- "traefik.http.routers.dashboard.tls=true"
- "traefik.http.routers.dashboard.tls.certresolver=letsencrypt"
- "traefik.http.routers.dashboard.service=api@internal"
# Middlewares: Auth + Sicherheits-Header
- "traefik.http.routers.dashboard.middlewares=dashboard-auth@file,secure-headers@file"
networks:
traefik-public:
external: true
💡 Hinweis: Tauscht
traefik.example.comdurch eure echte Subdomain. Der DNS-A-Record dafür muss bereits existieren, sonst kann Let’s Encrypt das Zertifikat nicht ausstellen.
Schritt 7: Traefik starten
cd /opt/traefik
sudo docker compose up -d
Der erste Start dauert 10-30 Sekunden. Den Fortschritt mitlesen:
sudo docker compose logs -f
Bei Configuration loaded from file und Server now listening ist Traefik bereit.
Schritt 8: Dashboard aufrufen
Öffnet im Browser:
https://traefik.example.com
Ihr werdet nach Basic-Auth-Credentials gefragt — gebt die Daten ein, die ihr beim htpasswd-Schritt vergeben habt. Wenn das Dashboard erscheint, ist Traefik komplett einsatzbereit.
✅ Geschafft! Traefik läuft, das Dashboard ist erreichbar, das SSL-Zertifikat wurde automatisch geholt. Jetzt kommen die ersten Services dahinter.
Ersten Service hinter Traefik betreiben
Als Beispiel deployen wir whoami — einen winzigen Container, der HTTP-Request-Details zurückgibt. Perfekt zum Testen.
Schritt 1: Compose-Datei erstellen
sudo mkdir -p /opt/whoami
sudo nano /opt/whoami/docker-compose.yml
Inhalt:
services:
whoami:
image: traefik/whoami
container_name: whoami
restart: unless-stopped
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"
- "traefik.http.routers.whoami.tls.certresolver=letsencrypt"
- "traefik.http.routers.whoami.middlewares=secure-headers@file"
- "traefik.http.services.whoami.loadbalancer.server.port=80"
networks:
traefik-public:
external: true
Schritt 2: Starten und testen
cd /opt/whoami
sudo docker compose up -d
Im Browser:
https://whoami.example.com
Ihr seht die HTTP-Header der Anfrage — und das Schloss-Symbol bestätigt das gültige SSL-Zertifikat.
💡 Tipp: Das ist das Grundmuster für jeden Service hinter Traefik: Container ins
traefik-public-Netzwerk hängen, Labels setzen, fertig. Keine Reverse-Proxy-Config zu schreiben, kein Reload nötig.
Wichtige Traefik-Labels verstehen
Die Labels sind das Herzstück von Traefik. Hier die wichtigsten erklärt:
| Label | Funktion |
|---|---|
traefik.enable=true | Container überhaupt durch Traefik routen |
traefik.http.routers.NAME.rule=Host(...) | Welche Domain auf diesen Service zeigt |
traefik.http.routers.NAME.entrypoints=websecure | HTTPS-Entry-Point |
traefik.http.routers.NAME.tls=true | SSL aktivieren |
traefik.http.routers.NAME.tls.certresolver=letsencrypt | SSL-Zertifikat von Let’s Encrypt |
traefik.http.services.NAME.loadbalancer.server.port=8080 | Auf welchem Port der Container lauscht |
traefik.http.routers.NAME.middlewares=... | Welche Middlewares angewendet werden |
Komplexere Routing-Regeln sind möglich:
# Mehrere Domains
- "traefik.http.routers.app.rule=Host(`app.example.com`) || Host(`www.app.example.com`)"
# Nur ein bestimmter Pfad
- "traefik.http.routers.api.rule=Host(`example.com`) && PathPrefix(`/api`)"
# Bestimmter Header
- "traefik.http.routers.beta.rule=Host(`example.com`) && Headers(`X-Beta`, `true`)"
Wildcard-SSL via DNS-Challenge
Die HTTP-Challenge (Standard) braucht für jede Subdomain ein eigenes Zertifikat. Bei vielen Services ist das umständlich. Mit der DNS-Challenge holt ihr ein Wildcard-Zertifikat (*.example.com) — gilt für alle Subdomains gleichzeitig.
Voraussetzung: Ihr nutzt einen unterstützten DNS-Provider mit API. Wir zeigen das Beispiel für Cloudflare — eine vollständige Liste findet ihr in der Traefik-Dokumentation.
Schritt 1: Cloudflare-API-Token erstellen
Im Cloudflare-Dashboard:
- My Profile → API Tokens → Create Token
- Template: Edit zone DNS
- Permissions:
Zone — DNS — Edit,Zone — Zone — Read - Zone Resources: Eure Domain
- Token erstellen und sicher kopieren
Schritt 2: Token in Traefik eintragen
Erweitert die docker-compose.yml:
services:
traefik:
# ... vorhandene Config ...
environment:
- CF_DNS_API_TOKEN=EUER_CLOUDFLARE_TOKEN
Schritt 3: traefik.yml anpassen
Ergänzt einen zweiten Resolver für die DNS-Challenge:
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"
Schritt 4: Wildcard-Zertifikat anfordern
In den Labels eines Services:
labels:
- "traefik.http.routers.app.tls.certresolver=cloudflare"
- "traefik.http.routers.app.tls.domains[0].main=example.com"
- "traefik.http.routers.app.tls.domains[0].sans=*.example.com"
Traefik holt jetzt ein einzelnes Zertifikat, das für alle Subdomains gilt — und erneuert es automatisch.
💡 Tipp: Wildcard-Zertifikate sind perfekt für Homelabs mit vielen Services, sparen Rate-Limit-Anfragen bei Let’s Encrypt und ermöglichen Subdomains für Services, die von außen gar nicht erreichbar sein sollen.
Middlewares — Services absichern
Middlewares sind Filter, die Anfragen vor dem Service verarbeiten. Hier die wichtigsten Patterns:
IP-Whitelist
Nur bestimmte IPs dürfen zugreifen — perfekt für Admin-Panels.
In dynamic.yml:
http:
middlewares:
admin-only:
ipAllowList:
sourceRange:
- "192.168.1.0/24"
- "10.0.0.0/8"
- "EURE_HEIM_IP/32"
In den Labels:
- "traefik.http.routers.admin.middlewares=admin-only@file,secure-headers@file"
Basic Auth
Wie schon beim Dashboard genutzt — funktioniert für jeden Service:
http:
middlewares:
portainer-auth:
basicAuth:
users:
- "admin:$apr1$xyz...$abc..."
Rate-Limiting pro Client-IP
http:
middlewares:
api-rate-limit:
rateLimit:
average: 50
period: 1s
burst: 20
sourceCriterion:
ipStrategy:
depth: 1
Authentik Forward-Auth
Wenn ihr unser Authentik-Tutorial befolgt habt, könnt ihr Authentik als Forward-Auth-Middleware nutzen:
http:
middlewares:
authentik:
forwardAuth:
address: http://authentik-server:9000/outpost.goauthentik.io/auth/traefik
trustForwardHeader: true
authResponseHeaders:
- X-authentik-username
- X-authentik-groups
- X-authentik-email
- X-authentik-name
- X-authentik-uid
In den Labels:
- "traefik.http.routers.app.middlewares=authentik@file,secure-headers@file"
Jetzt fragt Traefik bei jedem Request Authentik, ob der User eingeloggt ist.
Logs & Monitoring
Traefik schreibt zwei Log-Dateien:
- traefik.log — Server-Logs (Errors, Config-Changes, ACME-Events)
- access.log — Jeder eingehende Request
Logs ansehen
# Live mitlesen
sudo tail -f /opt/traefik/logs/traefik.log
sudo tail -f /opt/traefik/logs/access.log
# Im Container
sudo docker compose logs -f traefik
Access-Log als JSON
Für Auswertung mit Tools wie Grafana Loki ist JSON praktischer als das Standard-Format:
accessLog:
filePath: /logs/access.log
format: json
fields:
headers:
defaultMode: keep
names:
Authorization: drop
Prometheus-Metrics
Traefik kann Metriken im Prometheus-Format exportieren:
metrics:
prometheus:
addEntryPointsLabels: true
addRoutersLabels: true
addServicesLabels: true
Die Metrics liegen dann unter http://traefik:8080/metrics — perfekt für ein späteres Grafana-Setup.
Backups
Traefik selbst hat keinen Datenbank-State, aber zwei Dinge müssen gesichert werden:
Was muss gesichert werden?
/opt/traefik/config/— Statische und dynamische Konfiguration/opt/traefik/certs/acme.json— Eure SSL-Zertifikate/opt/traefik/docker-compose.yml
Automatisches Backup-Script
sudo nano /usr/local/bin/traefik-backup.sh
Inhalt:
#!/bin/bash
set -e
BACKUP_DIR="/var/backups/traefik"
TIMESTAMP=$(date +%Y%m%d-%H%M%S)
RETENTION_DAYS=14
mkdir -p "$BACKUP_DIR"
tar -czf "$BACKUP_DIR/traefik-$TIMESTAMP.tar.gz" \
-C /opt/traefik config certs docker-compose.yml
find "$BACKUP_DIR" -type f -mtime +$RETENTION_DAYS -delete
echo "Backup completed: $TIMESTAMP"
Ausführbar machen und mit systemd Timer automatisieren — wie in unserem restic Backup-Tutorial beschrieben:
sudo chmod +x /usr/local/bin/traefik-backup.sh
sudo /usr/local/bin/traefik-backup.sh
⚠️ Best Practice: Die
acme.jsonenthält eure privaten SSL-Schlüssel. Speichert Backups nur an sicheren Orten und verschlüsselt sie für Off-Site-Storage.
Updates
Traefik veröffentlicht regelmäßig Updates. Major-Versionen können Breaking Changes haben — also Release-Notes lesen.
Update durchführen
cd /opt/traefik
# Image-Tag in docker-compose.yml anpassen (z.B. von v3.2 auf v3.3)
sudo nano docker-compose.yml
# Backup vor dem Update!
sudo /usr/local/bin/traefik-backup.sh
# Update
sudo docker compose pull
sudo docker compose up -d
Während des Restarts sind eure Services kurz nicht erreichbar (5-10 Sekunden).
💡 Empfehlung: Pinnt Traefik immer auf eine Major.Minor-Version (z.B.
traefik:v3.2), nicht auflatest. Major-Updates wie v2 → v3 brachten Breaking Changes in der Konfiguration.
Zusammenfassung & Checkliste
Hier eine Checkliste, damit ihr nichts vergesst:
| Schritt | Status |
|---|---|
| Debian 13 Server eingerichtet | ☐ |
| Docker installiert | ☐ |
| Domain & DNS-Records (A & Wildcard) konfiguriert | ☐ |
Verzeichnisstruktur unter /opt/traefik | ☐ |
acme.json mit chmod 600 erstellt | ☐ |
Docker-Netzwerk traefik-public erstellt | ☐ |
traefik.yml mit Let’s Encrypt konfiguriert | ☐ |
dynamic.yml mit Middlewares erstellt | ☐ |
| Basic-Auth-Hash für Dashboard generiert | ☐ |
| Traefik-Container gestartet | ☐ |
| Dashboard unter eurer Domain erreichbar | ☐ |
| SSL-Zertifikat erfolgreich ausgestellt | ☐ |
| whoami-Test-Service deployed und erreichbar | ☐ |
| Backup-Script eingerichtet | ☐ |
Troubleshooting
Traefik startet nicht
cd /opt/traefik
sudo docker compose logs -f
Häufigste Ursachen:
acme.jsonhat nichtchmod 600traefik.ymlenthält Syntax-Fehler (YAML ist whitespace-sensitiv!)- Port 80/443 schon belegt →
sudo ss -tlnp | grep -E '(:80|:443)'
SSL-Zertifikat wird nicht ausgestellt
- DNS prüfen:
dig +short euredomain.com— Zeigt es auf eure Server-IP? - Port 80 muss von außen erreichbar sein (HTTP-Challenge braucht das)
- Let’s Encrypt Rate-Limit erreicht? → 50 Zertifikate / Domain / Woche
- In Traefik-Logs nach
acmesuchen:sudo docker compose logs traefik | grep -i acme
Service erreichbar, aber kein SSL
- Hat der Container
traefik.enable=true? - Ist der Container im
traefik-public-Netzwerk? - Im Dashboard prüfen: Wird der Router angezeigt? Hat er einen TLS-Eintrag?
„Gateway Timeout“ oder „Bad Gateway“
- Stimmt der Port in
loadbalancer.server.port? - Lauscht die App auf
0.0.0.0(nicht nurlocalhost)? - Gleiches Docker-Netzwerk wie Traefik?
Dashboard nicht erreichbar
- Subdomain in
Host(...)korrekt? - DNS-A-Record für
traefik.example.comexistiert? - Basic-Auth-Hash korrekt eingetragen? (Vorsicht mit
$vs.$$)
„too many redirects“
- Cloudflare SSL-Modus auf Full (strict) stellen, nicht auf Flexible
- Im HTTPS-Redirect schauen: ist
permanent: trueaktiv?
Nächste Schritte
Traefik läuft — und jetzt? Hier sind sinnvolle nächste Schritte:
- Wildcard-SSL via DNS-Challenge — Vertiefendes Tutorial
- Authentik als Forward-Auth integrieren — SSO für alle Services hinter Traefik
- Crowdsec-Bouncer — Brute-Force und Bot-Schutz auf Layer 7
- Prometheus + Grafana — Visualisierung aller Traefik-Metrics
- Multi-Server-Setup — Mehrere Traefik-Instanzen mit gemeinsamem Cluster-Storage
- TCP/UDP-Routing — Auch Datenbanken und Game-Server hinter Traefik betreiben
Traefik ist das Herzstück eines modernen Container-Setups. Die offizielle Dokumentation ist sehr umfangreich und immer aktuell.
Habt ihr Fragen oder Probleme? Schreibt es in die Kommentare — ich helfe gerne!