sichere https Verbindung: Traefik Reverse Proxy + Let´s Encrypt
Für nahezu alle bekannten Websysteme gibt es fertige Docker-Container, bzw. können diese relativ einfach selbst erstellt oder bestehende Container angepasst werden. Als Docker-Container können die Webservices sehr einfacher installiert und betrieben werden. Wer einen Webservice über das Internet veröffentlicht, sollte dafür heute unbedingt eine verschlüsselte Verbindung (SSL) anbieten. Um den Zugriff auf einen oder mehrere Container zu regeln, kann ein Reverse-Proxy mit kostenlosen Let’s Encrypt-Zertifikaten für das SSL-Offloading verwendet werden, siehe auch: eigener Webserver – wie funktioniert eigentlich das Internet? Um Webservices vom Heimnetzwerk über das Internet zu Verfügung zu stellen bietet ev. Cloudflare eine einfachere Alternative zu diesem Setup.
Ziel dieses Beitrags
Der Betrieb von einem oder mehrerer Docker-Webservices (Websites) inklusive HTTPS-Verschlüsselung auf einem Server.Die Webservices können über deren Eigenschaften (Docker-Container-Labels) veröffentlicht und über eine eigene Weboberfläche kontrolliert werden.
Aufwand
Lesedauer: ca. 15 MinutenVoraussetzung
Ein im Internet veröffentlichter Server mit Docker und eine registrierte WebdomainVom NGINX Proxy zu Traefik
Ursprünglich habe ich für den Betrieb mehrerer Docker-basierter Webseiten "NGINX Proxy Automation" von Evert Ramos verwendet, siehe: nginx-LetsEncrypt Reverse Proxy in der Praxis. Das Projekt funktioniert wunderbar, hat aber im Vergleich zum alternativen Reverse-Proxy: Traefik einige Limitationen. Mit Traefik ist es gefühlt noch einfacher und dank des Web-Dashboards übersichtlicher mehrere Webseiten auf einem Server zu betreiben. Zahlreiche Middleware bieten zudem zusätzliche Funktionen.
Schematische Darstellung
Der Traefik-Docker-Container kümmert sich um das Ausstellen, Verwalten und Verwenden von SSL-Zertifikaten und leitet Webanfragen auf die jeweiligen Webservices, die wiederum auch als Docker-Container bereitgestellt werden.
Traefik kümmert sich um
-
-
- den Zugriff auf einen oder mehrere Docker-Webanwendungen
- die Zertifikatsverwaltung für eine HTTPS-Verschlüsselung
-
Software | Traefik |
---|---|
GitHub | https://github.com/traefik/traefik |
aktuelle Version | 2.10.4 |
gefunden | 26.07.2023 |
Installation: Server, Domain (DNS) und Docker
Docker Basics
Docker ermöglicht es, Services oder Applikationen per Befehl in einem sogenannten Container zu starten.Ein Container ist eine vom Betriebssystem (OS) unabhängige isolierte Umgebung:
Beim ersten Start eines Containers, lädt Docker selbstständig alle notwendigen Quellen
aus dem Internet.
Docker kann unter Windows, macOS oder einer Linux-Distribution installiert werden,
siehe auch: Docker
Für das hier vorgestellte Setup wird Docker benötigt, siehe: Docker Installation Linux oder Docker Installation Windows. Bei einem Server eines Hosting-Providers kann Docker und das hier vorgestellte Setup über eine SSH-Verbindung zum Server und über die beschriebenen Bash-Befehle erfolgen. Sollte sich der Server im eigenen Heimnetzwerk befinden, muss am Router ein entsprechendes Port-Forwarding eingerichtet werden, siehe: aus dem Internet verfügbar machen: Port-Forwarding - OpenWRT. Sollte der Internetprovider die öfftenliche IP-Adresse regelmässig ändern, siehe: free DynDNS Service - Zugriff bei wechselnder öffentlicher IP.
Wer Docker bereits installiert hat und die entsprechenden A-Records in der Domainverwaltung eingetragen hat, benötigt eine Textdatei mit Namen docker-compose.yml und als Vorlage folgenden Inhalt:
docker-compose.yml
services:
traefik:
image: "traefik:v2.8"
container_name: "traefik"
command:
#- "--log.level=DEBUG"
- "--api.dashboard=true"
- "--providers.docker=true"
- "--providers.docker.exposedbydefault=false"
- "--entrypoints.web.address=:80"
- "--entrypoints.websecure.address=:443"
- "--certificatesresolvers.myresolver.acme.tlschallenge=true"
- "--certificatesresolvers.myresolver.acme.email=admin@domain.tld"
- "--certificatesresolvers.myresolver.acme.storage=/letsencrypt/acme.json"
- "--entrypoints.web.http.redirections.entryPoint.to=websecure"
- "--entrypoints.web.http.redirections.entryPoint.scheme=https"
expose:
# traefik dashboard port
- 8080
labels:
- "traefik.enable=true"
- "traefik.http.routers.traefik.rule=Host(`traefik.domain.tld`)"
- "traefik.http.routers.traefik.entrypoints=websecure"
- "traefik.http.routers.traefik.tls.certresolver=myresolver"
- "traefik.http.routers.traefik.service=api@internal"
- "traefik.http.routers.traefik.middlewares=traefik-auth"
- "traefik.http.middlewares.traefik-auth.basicauth.users=admin:??????"
ports:
- "80:80"
- "443:443"
- "8080:8080"
volumes:
- "./letsencrypt:/letsencrypt"
- "/var/run/docker.sock:/var/run/docker.sock:ro"
restart: "always"
networks:
default:
name: webproxy
external: true
Das Beispiel verwendet Bind-Mounts und keine Volumes, siehe: Docker Daten speichern: Docker Volumes vs. Host-Ordner.
Anpassen der docker-compose.yml-Datei
Die docker-compose-yml-Vorlage verwendet nicht nur für die veröffentlichten Web-Service-Container ein Zertifikat, sondern auch für das Traefik-Dashboard, wodurch auch der Zugriff auf das Dashboard verschlüsselt stattfindet. Damit das Dashboard nicht von jedermann aufgerufen werden kann, wurde eine Basic-Authentication mit einem Admin-User hinterlegt.
Vor dem eigentlichen Start muss die Datei natürlich ein klein wenig angepasst werden:
- traefik.domain.tld sollte mit einer eigenen Domäne für das Traefik-Dashboard,
- acme.email mit einer Mailadresse und
- basicauth.users mit einem eigenen Benutzernamen und einem entsprechenden md5-Kennwort ersetzt werden.
Anstelle von traefik.domain.tld kann für den Zugriff auf das Dashboard eine Subdomain einer vorhandenen Domain verwendet werden. Als Beispiel könnte in der DNS-Zonenverwaltung für die Domäne libe.net ein A-Record für eine Subdomain traefik.libe.net auf die IP-Adresse des Webservers erstellt werden.
Natürlich muss in der docker-compose.yml-Datei für dieses Beispiel auch traefik.libe.net anstelle von traefik.domain.tld verwendet werden.
Die Mailadresse wird von Let’s Encrypt verwendet, um bestimmte Informationen oder Warnungen zu versenden: Zum Beispiel, falls ein Zertifikat bald abläuft. Keine Sorge, Traefik kümmert sich um die Verlängerung der Zertifikate, entsprechend sollten E-Mails mit der Information über den Ablauf eines Zertifikats ernst genommen werden.
Das Kennwort für die Basic-Authentifizierung kann nicht im Klartext eingetragen werden und muss daher vorab über einen Befehl als MD5-Hash erzeugt werden und für die Verwendung in docker-compose müssen einfache $ mit $$ ersetzt werden, siehe: doc.traefik.io/traefik/middlewares/http/basicauth/
In Linux kann dazu folgender Befehl verwendet werden: echo $(htpasswd -nB admin) | sed -e s/\\$/\\$\\$/g
root@Webserver:~# echo $(htpasswd -nB admin) | sed -e s/\\$/\\$\\$/g
New password:
Re-type new password:
admin:$$2y$$05$$7liwlteyGcPyCr2oXc4Do.G/wWxjwWLYpTWg6vvQ4pU7PLAS4ysMm
Anstelle von admin kann hier auch ein anderer Benutzername verwendet werden.
Nach dem Anpassen der Datei können wir den Traefik-Container starten. Nachträglich gestartete Docker-Container mit den hinterlegten Labels für dessen Webservice werden im laufenden Betrieb von Traefik verarbeitet und veröffentlicht.
Start des Traefik-Containers
Als Netzwerk für Traefik und für die später erstellen Webservices verwende ich ein eigenes Netzwerk mit Namen „webproxy“, welches ich vor dem Start von Traefik (docker-compose up) erstelle:
cd /OrdnerDockerComposeFileTraefik
docker network create webproxy
docker-compose up -d
Sollte alles richtig funktionieren, kann das Traefik-Dashboard über die angegebene Domain und nach Eingabe des angegebenen Benutzers aufgerufen werden:
Websites oder Services erstellen und hosten
Wird ein anderer Docker-Container mit dem Netzwerk webproxy und entsprechenden Labels für Traefik gestartet, kann dieser über Traefik aufgerufen werden.
Wer mehrere Webservices starten will, muss darauf achten, dass unterschiedliche Labels in den jeweiligen Konfigurationen verwendet werden:
z. B. Webservice 1:
labels:
- "traefik.enable=true"
- "traefik.http.routers.webservice1.rule=Host(`service1.domain.tld`)"
- "traefik.http.routers.webservice1.entrypoints=web"
- "traefik.http.routers.webservice1.entrypoints=websecure"
...
und für einen weiteren Docker-Container mit einem anderen Service:
labels:
- "traefik.enable=true"
- "traefik.http.routers.webservice2.rule=Host(`service2.domain.tld`)"
- "traefik.http.routers.webservice2.entrypoints=web"
- "traefik.http.routers.webservice2.entrypoints=websecure"
...
„web“ als Entrypoint erlaubt den unverschlüsselten Zugriff auf den Service und „websecure“ den verschlüsselten Zugriff über HTTPS.
Siehe auch: eigener Webserver - wie funktioniert eigentlich das Internet?
Authentifizierung
Wer für einen Container eine simple Basic-Authentifizierung hinzufügen möchte, kann dies durch das Hinzufügen der Basic-Authentication-Middleware. (gleich dem Traefik-Dashboard)
(Basic-Authentication: Bevor das Dashboard aufgerufen werden kann, muss der hinterlegte Benutzername und das Passwort eingegeben werden)
Die folgende Zeile legt eine Middleware mit Namen: webserver-basic-auth an und definiert damit den Benutzernamen und das Passwort:
- "traefik.http.middlewares.webserver-basic-auth.basicauth.users=admin:md5Passwort"
Das Kennwort kann, wie bereits beschrieben mit einem Linux-Befehl in einen md5-Hash umgewandelt werden:echo $(htpasswd -nB admin) | sed -e s/\\$/\\$\\$/g
Damit der Router, hier mit Namen "webserver" die angelegte Middleware verwendet, habe ich folgende Zeile hinzugefügt:
- "traefik.http.routers.webserver.middlewares=webserver-basic-auth"
labels:
- "traefik.enable=true"
- "traefik.http.routers.webserver.rule=Host(`domain.tld`)"
- "traefik.http.routers.webserver.entrypoints=web"
- "traefik.http.routers.webserver.entrypoints=websecure"
- "traefik.http.routers.webserver.tls.certresolver=myresolver"
- "traefik.http.middlewares.webserver-basic-auth.basicauth.users=admin:md5Passwort"
- "traefik.http.routers.webserver.middlewares=webserver-basic-auth"
Alternativ zur Basic-Authentifizierung kann auch ein externer Anmeldeanbieter verwendet werden. Als Beispiel die Verwendung von Google als Anmeldeanbieter, also die Verwendung eines Google-Kontos für die Anmeldung auf den eigenen Webservices, siehe: Traefik Google-Authentifizierung.
Zusätzliche SAN (Subject Alternative Names)
Damit ein Webzertifikat für mehrere Subdomains ausgestellt werden kann, können sogenannte SAN verwendet werden:
labels:
- "traefik.enable=true"
- "traefik.http.routers.webservice.rule=Host(`domain.tld`,`www.domain.tld`,`dev.domain.tld`,`dev2.domain.tld)"
- "traefik.http.routers.webservice.entrypoints=web"
- "traefik.http.routers.webservice.entrypoints=websecure"
- "traefik.http.routers.webservice.tls.certresolver=myresolver"
Umleitungen
Für das Umleiten von Subdomains auf eine andere Subdomain, können Regex-Ausdrücke verwendet werden.
Diverse Subdomains und/oder Non-WWW auf WWW umleiten
Das folgende Beispiel leitet alle Subdomains und die Root-Domain (Non-WWW) auf eine URL mit WWW um:
domain.tld, dev.domain.tld und dev2.domain.tld werden auf www.domain.tld umgeleitet. Damit das Zertifikat auch alle Domänen-Namen enthält, müssen diese in der Host-Rule angegeben werden:
labels:
- "traefik.enable=true"
- "traefik.http.routers.webservice.rule=Host(`domain.tld`,`dev.domain.tld`,`dev2.domain.tld`,`www.domain.tld`)"
- "traefik.http.routers.webservice.entrypoints=web"
- "traefik.http.routers.webservice.entrypoints=websecure"
- "traefik.http.routers.webservice.tls.certresolver=myresolver"
- "traefik.http.routers.webservice.middlewares=redirect_???2www"
- "traefik.http.middlewares.redirect_???2www.redirectregex.regex=^https://(dev.|dev2.)?domain.tld(.*)"
- "traefik.http.middlewares.redirect_???2www.redirectregex.replacement=https://www.domain.tld$${2}"
- "traefik.http.middlewares.redirect_???2www.redirectregex.permanent=true"
Diverse Subdomains und/oder WWW auf Non-WWW
labels:
- "traefik.enable=true"
- "traefik.http.routers.webservice.rule=Host(`domain.tld`,`dev.domain.tld`,`dev2.domain.tld`,`www.domain.tld`)"
- "traefik.http.routers.webservice.entrypoints=web"
- "traefik.http.routers.webservice.entrypoints=websecure"
- "traefik.http.routers.webservice.tls.certresolver=myresolver"
- "traefik.http.routers.webservice.middlewares=redirect_www2none"
- "traefik.http.middlewares.redirect_www2none.redirectregex.regex=^https://(www.|dev.|dev2.)domain.tld(.*)"
- "traefik.http.middlewares.redirect_www2none.redirectregex.replacement=https://domain.tld$${2}"
- "traefik.http.middlewares.redirect_www2none.redirectregex.permanent=true"
HTTP auf HTTPS umleiten (nicht global, nur für den jeweiligen Container)
labels:
- "traefik.enable=true"
- "traefik.http.routers.webservice.rule=Host(`domain.tld`,`dev.domain.tld`,`dev2.domain.tld`,`www.domain.tld`)"
- "traefik.http.routers.webservice.entrypoints=web"
- "traefik.http.routers.webservice.entrypoints=websecure"
- "traefik.http.routers.webservice.tls.certresolver=myresolver"
- "traefik.http.routers.webservice_http.rule=Host(`domain.tld`,`www.domain.tld`,`dev.domain.tld`)"
- "traefik.http.routers.webservice_http.entrypoints=web"
- "traefik.http.routers.webservice_http.middlewares=redirect-to-https"
- "traefik.http.middlewares.redirect-to-https.redirectscheme.scheme=https"
FAQ
Was ist ein Reverse-Proxy?
Ein Reverse Proxy nimmt Webanfragen entgegen und leitet diese an dahinterliegende Webservices weiter. Damit die Anfragen an den richtigen Webservice weitergeleitet werden, verwenden die meisten Reverse-Proxys den Host-Header (=Domainnamen). Ein Reverse-Proxy kann zusätzliche Funktionen für einen besseren Schutz, einen optimierten Datenverkehr oder eine zusätzliche Authentifizierung bieten.
Wozu wird ein Reverse-Proxy verwendet?
Ein Reverse Proxy wird überwiegend für den Webzugriff auf einen oder mehrere Webserver vorgeschaltet. Neben dem Verteilen der Anfragen auf mehrere Webservices, wird ein Reverse Proxy häufig für ein sogenanntes SSL-Offloading verwendet. Der Reverse-Proxy kümmert sich dabei um das Bereitstellen der Webservices über HTTPS und übernimmt neben dem Verschlüsseln und Entschlüsseln des Datenverkehrs auch häufig das Zertifikatsmanagement.
Was ist der Unterschied zwischen einem Reverse-Proxy und einem Load Balancer?
Die Aufgabe eines Load Balancer ist primär die Last zwischen verschiedenen Servern oder Geräten zu verteilen. Ein Reverse-Proxy kann neben einem Lastausgleich auch noch andere Funktionen wie SSL-Offloading oder Caching und wird überwiegend für Webserver (HTTP) eingesetzt. Ein Load Balancer hingegen kann auch für andere Protokolle verwendet werden.
Webservices, Beispiele
Hier eine Liste von Webservices, die ich bisher getestet habe:
- Nextcloud , siehe : Nextcloud Server Docker | Einrichtung +https: Let’s Encrypt [ssl]
- Home-Assistant, siehe : Alles zu Home Assistant: Inbetriebnahme + Integration + Betrieb
- Docker Mailserver, siehe : Docker Mailserver selbst betreiben | ein Erfahrungsbericht
- GitLab, siehe : GIT-Repositories selbst hosten: GitLab als Docker-Container starten
- Gitea , siehe : Schlanker und schneller GIT-Server, ähnlich GitHub (Docker)
- webhookd, siehe : Docker WebHook Daemon: einfacher Hook-Server für Bash-Skripts
- WordPress, siehe : WordPress in Docker inkl. HTTPS Let's Encrypt-Setup
- Laravel, siehe : mein Docker-Webserver Setup für Laravel - Konfig im Detail
- Bitwarden, siehe : Bitwarden in Docker betreiben - Setup Schritt für Schritt
- Uptime Kuma, siehe : Webseiten überwachen mit Uptime Kuma
- Portainer, siehe : Docker Container GUI grafische Weboberfläche mit Portainer
- Matomo, siehe : Besucherstatistik: Matomo, Google Analytic Ersatz selbst hosten

{{percentage}} % positiv

DANKE für deine Bewertung!
Top-Artikel in diesem Bereich
Wer nach einem NAS (Network Attached Storage oder Netzwerkspeicher) für den Heimgebrauch sucht, kommt an den Herstellern Synology und QNAP nicht vorbei. Beide Hersteller liefern kleine NAS-Komplettlösungen mit der Möglichkeit, Daten lokal oder über das Internet zu synchronisieren und beide verlangen für die verwendete Hardware nicht gerade wenig Geld.
Mit ioBroker können verschiedene Automatisierungslösungen oder Geräte in einem System zusammengefasst werden. Um bestimmte Gateways oder Geräte ansprechen zu können, werden in ioBroker verschiedene Adapter verwendet.
Bitwarden ist ein webbasierter Passwort-Manager, ähnlich LastPass, aber Open Source und der Möglichkeit diesen selbst zu betreiben (hosten). Wie sich Bitwarden im Vergleich zu anderen Passwort-Managern einordnet, habe ich auf folgender Seite überlegt: Passwort-Manager sicher? KeePass vs. LastPass vs. Bitwarden. Bitwarden besteht aus mehreren Services, welche über verschiedene Container bereitgestellt werden können. Das relativ aufwändige Setup wurde mit "Bitwarden Unified" speziell für ein Selbs...
Fragen / Kommentare
(sortiert nach Bewertung / Datum) [alle Kommentare(neueste zuerst)]
Hallo, schöne Anleitung! Ich habe den Docker Stack auf einer Portainer Instanz auf einem QNAP ausprobiert. Dabei habe ich immer wieder den Fehler "port is missing" bekommen: level=error msg="service \"traefik-traefik\" error: port is missing" providerName=docker container=traefik-traefik.... Mit dem zusätzlichen Label - "traefik.http.services.traefik.loadbalancer.server.port=80" startet Traefik ohne Fehlermeldung. Allerdings hab ich es bis jetzt nicht geschafft das Traefik Dashboard aufzurufen. Irgendwas an der Portweiterleitung klemmt. Firewalls hab ich schon ausgeschlossen. Es könnte noch an belegten Ports auf dem QNAP liegen (QNAP: 8080, 443, Portainer: 8443) oder daran, dass ich ein VLAN betreibe. Letzteres schliesse ich eigentlich aus, da ich aus der Shell im Traefik Container z.B. google.de anpingen kann. Für Hinweise bin ich dankbar. Vielleicht ist auch das zusätzliche Label noch nicht korrekt. Beste Grüße Christian
Hallo, nach längerer Suche funktioniert das Traefik Dashboard mit basicAuth jetzt and auch der Traefik/whoami ist erreichbar. BasicAuth / Dashboard: Damit ist eigentlich alles in Ordnung. Das Problem liegt bei der Einstellung "expose: 8080" bzw. dem fehlenden loadbalancer. Zunächst zu expose. Da ich noch ziemlich neu in der Docker-Welt bin, ging ich irrtümlich davon aus, dass dies eine Traefik spezifische Einstellung ist und dass das Dashboard über den angegebenen Port 8080 erreichbar sein sollte. Tatsächlich sagt die docker compose reference dazu: "Expose ports without publishing them to the host machine - they’ll only be accessible to linked services. Only the internal port can be specified." Das Dashboard ist natürlich ganz normal über den Namen in der Host rule (im Beispiel traefik.domain.tld) erreichbar. Die Frage ist also, für was ist die Einstellung "expose: 8080" gut? Erschwerend kam hinzu, dass ohne den loadbalancer ein Fehler auftritt, der die Erzeugung der Middleware für die basicAuth verhindert. Theoretisch sollte Traefik unter Docker automatisch den Port des Servers verwenden, wenn es nur einen gibt: "Port detection works as follows: If a container exposes a single port, then Traefik uses this port for private communication. If a container exposes multiple ports, or does not expose any port, then you must manually specify which port Traefik should use for communication by using the label traefik.http.services.<service_name>.loadbalancer.server.port (Read more on this label in the dedicated section in routing)." Das scheint nicht ganz zu funktionieren, da jedenfalls bei mir der Fehler auftritt. Traefik/whoami: Standardmässig startet Traefik/whoami auf Port 80. Ich habe aber versucht, den Server auf Port 443 anzusprechen. Das kann natürlich nicht funktionieren. Hoffe, das hilft dem ein oder anderen. Beste Grüße Christian
Beitrag erstellt von anonym