Photo by Kaffeebart / Unsplash

Traefik als Reverse Proxy

docker 30. Mai 2023

Traefik ist ein Reverse Proxy, der sich einfach im Docker-Umfeld nutzen lässt, da Traefik selbst auch nur ein weiterer Docker Container ist. Die Konfiguration der einzelnen Dienste kann leicht über die Angabe von Labels beim jeweiligen Container erfolgen.

Was ist überhaupt ein Reverse Proxy?

Über einen Reverse Proxy erhält man einfach die Möglichkeit, die Verbindungen zu einem Dienst mit https zu verschlüsseln. Der Reverse Proxy übernimmt dabei häufig die Beantragung/Verwaltung/Erneuerung der Zertifikate, sodass dies nur an einer zentralen Stelle erfolgen muss. Verschlüsselt wird dabei die Verbindung vom Nutzer bis zum Reverse Proxy, die interne Weiterleitung zum eigentlichen Dienst erfolgt dann meistens unverschlüsselt. Da diese Verbindung häufig auf dem gleichen System oder sogar im gleichen Docker Netzwerk ist, ist dies unproblematisch.

Skizze Reverse Proxy

Anhand der eingegebenen URL kann der Reverse-Proxy entscheiden, mit welchem Dienst er den Benutzer verbinden muss. Eine Anfrage an https://dienst1.einedomain.de zum Beispiel würde dementsprechend intern an "Dienst 1" weitergeleitet werden.

Voraussetzungen

ℹ️
Es wird vorausgesetzt, dass Port 80 und 443 von außen erreichbar sind. Solltet ihr Traefik zu Hause installieren, müsst ihr diese Ports entsprechend im Router freigeben.

In dieser Beschreibung wird davon ausgegangen, dass Docker bereits installiert ist. Falls nicht, kann dies mit Hilfe des Beitrags Docker - Installation auf Server nachgeholt werden.

Desweiteren wird von folgender Ordnerstruktur auf einem Linux-System ausgegangen:

├── /home/USERNAME/docker/
│   ├── traefik
│   │   ├── docker-compose.yml
│   │   ├── config/
│   │   │   ├── traefik.yml
│   │   │   ├── dynamic/
│   │   │   │   ├── simpleAuth_middleware.yml

Um die Ordnerstruktur schnell anzulegen, am besten in das Benutzerverzeichnis wechseln:

cd ~

und dann die Ordner anlegen:

mkdir -p docker/traefik/config/dynamic

Durch das -p wird nicht nur der zuletzt genannte Ordner dynamic angelegt, sondern auch alle davor genannten Ordner, sofern sie noch nicht existieren.

Ihr benötigt auch eine Domain oder mindestens eine Subdomain, die auf die IP des Systems/Servers zeigt auf der/dem Traefik installiert wird.

Konfigurationen für Traefik anlegen

Zunächst legen wir die Konfigurationsdateien für Traefik an. Dazu wechseln wir in das traefik-Verzeichnis.

cd ~/docker/traefik

Für die Hauptkonfiguration von Traefik legen wir eine yaml-Datei im Unterverzeichnis config an, dazu öffnen wir eine neue leere Datei mit dem Editor nano:

nano config/traefik.yml

Diese Datei füllen wir mit nachfolgendem Inhalt. Der Eintrag "DEINE_EMAIL" muss durch deine Emailadresse ersetzt werden. Diese wird bei der Beantragung der Zertifikate an Let's Encrypt übermittelt und wird für wichtige Informationen bezüglich der Zertifikate genutzt:

# Traefik static config

global:
  checkNewVersion: true
  sendAnonymousUsage: false

entrypoints:
  web:
    address: ":80"
    http:
      redirections:
        entryPoint:
          to: websecure
          scheme: https
          permanent: true
  websecure:
    address: ":443"

api:
  dashboard: true

log:
  level: INFO

certificatesResolvers:
  letsencrypttls:
    acme:
      email: DEINE_EMAIL
      storage: "/acme/acme.json"
      tlsChallenge: {}

providers:
  docker:
    watch: true
    network: traefik
    exposedByDefault: false
  file:
    directory: "./dynamic"
    watch: true

Speichern und schließen mit
Win: STRG+O, ENTER, STRG+X
Mac: CONTROL+O, ENTER, CONTROL+X

Zusatzinfos zur traefik.yml

Grobe Beschreibung, angegeben ist jeweils das Hauptelement.

  • global: Prüfung auf neue Versionen aktivieren, Übermittlung von Statistiken deaktivieren.
  • entrypoints: Ports 80 (http) und 443 (https) öffnen. Da wir nur sichere Verbindungen wollen, wird jede Anfrage auf Port 80 immer auf 443 weitergeleitet.
  • api: Aktivierung des Traefik Dashboards. Bietet eine Übersicht aller Services auf einer Webseite.
  • log: Level des Loggers. Bei Problemen kann kurzzeitig "DEBUG" genutzt werden, damit erhält man sehr viele Ausgaben im Log. Sollte nicht dauerhaft genutzt werden, damit die Logs nicht zu groß werden.
  • certificatesResolvers: Einstellungen für den Zertifikatsspeicher und der Beantragungsmethode bei Let's Encrypt.
  • providers: Definiert, dass Einstellungen von Docker Containern gelesen werden sollen, wenn sie sich im Docker Netzwerk "traefik" befinden. Außerdem werden Konfigurationen aus Dateien gelesen, die im Unterordner "dynamic" liegen.

Absicherung des Dashboards

Da wir nicht wollen, dass jeder das Dashboard von Traefik einsehen kann, schützen wir dieses mit einem Benutzernamen und ein Passwort. Dieses wird dann vom Browser abgefragt, sobald man das Dashboard aufrufen möchte.

Dazu generieren wir uns erstmal einen sicheren String, der den gewünschten Benutzernamen und das Passwort verschlüsselt beinhaltet ("benutzername" muss ersetzt werden):

echo $(htpasswd -nB benutzername)
ℹ️
Falls folgender Fehler erscheint:-bash: htpasswd: Kommando nicht gefunden.--> Dann führe vorher noch diesen Befehl aus:sudo apt install apache2-utilsund wiederhole danach den fehlgeschlagenen Befehl.

Du wirst aufgefordert, ein Passwort einzugeben und dieses dann nochmal zu wiederholen, als Ergebnis erhält man dann eine kryptische Zeichenkette:

benutzername:$2y$05$Wz.GxsiC37w/CBVKTOpBjO8mdHND1G0duWj6l8f5G5S5u1oh94OKi

Diese speichern wir uns irgendwo zwischen, denn wir benötigen sie in der neuen Datei, die wir jetzt unter config/dynamic anlegen:

nano config/dynamic/simpleAuth_middleware.yml

Dort wird folgender Inhalt eingefügt, SECRET_STRING muss mit der gerade erzeugten Zeichenkette ersetzt werden (Anführungsstriche beibehalten):

http:
  middlewares:
    simpleAuth:
      basicAuth:
        users:
          - "SECRET_STRING"

Speichern und schließen mit
Win: STRG+O, ENTER, STRG+X
Mac: CONTROL+O, ENTER, CONTROL+X

Diese Konfiguration definiert eine so genannte "Middleware". Sie hat den Namen "simpleAuth" und kann bei jedem gewünschten Dienst zwischengeschaltet werden und sorgt dafür, dass man das Ziel nur durch Eingabe von den definierten Logindaten erreichen kann.

Traefik Container erstellen und starten

Die Vorbereitungen sind abgeschlossen, sodass wir jetzt den Container selbst erstellen können. Dies machen wir mit docker-compose, also legen wir eine entsprechende yaml-Datei an. Wir befinden uns weiterhin im Verzeichnis /home/USERNAME/docker/traefik, dies kann mit dem Befehl pwd geprüft werden.

nano docker-compose.yml

Hier fügen folgendes ein:

⚠️
Die Domain "traefik.domain.tld" muss mit der gewünschten Domain für das Traefik Dashboard ersetzt werden. Die Domain muss auf den Server verweisen, auf dem Traefik läuft.
version: "3"

services:
  traefik:
    container_name: traefik
    hostname: traefik
    image: traefik:latest
    restart: unless-stopped
    security_opt:
      - no-new-privileges:true
    ports:
      - 80:80/tcp
      - 443:443/tcp
    environment:
      TZ: Europe/Berlin
    volumes:
      - traefik-acme:/acme
      - ./config/traefik.yml:/traefik.yml
      - ./config/dynamic:/dynamic
      - /etc/localtime:/etc/localtime:ro
      - /var/run/docker.sock:/var/run/docker.sock:ro
      - /var/log/docker/traefik:/var/log/traefik
    networks:
      - traefik
    labels:
      # Traefik
      traefik.enable: true
      traefik.http.routers.traefik.entrypoints: websecure
      traefik.http.routers.traefik.rule: Host(`traefik.domain.tld`)
      traefik.http.routers.traefik.service: api@internal
      traefik.http.routers.traefik.middlewares: simpleAuth@file
      traefik.http.routers.traefik.tls: true
      traefik.http.routers.traefik.tls.certresolver: letsencrypttls

networks:
  traefik:
    name: traefik

volumes:
  traefik-acme:
    name: traefik-acme
ℹ️
Eine detailliertere Erklärung von docker-compose und deren yaml-Konfiguration ist nicht Bestandteil dieses Artikels, grobe Zusatzinfos gibt es nachfolgend.

Zusatzinfos zur docker-compose.yml

In dieser Datei ist folgendes definiert:

  • Erstelle einen Container mit dem Namen "traefik" aus dem Image "traefik:latest".
  • Neu starten, wenn er abstürtzt, sofern er nicht manuell gestoppt wurde.
  • Öffne die Ports 80 und 443 nach außen.
  • Lege das Docker Netzwerk "traefik" an und tritt diesem bei.
  • Lege ein Docker Volume "traefik-acme" an und sichere darin die Zertifikate.
  • Mappe die Datei "traefik.yml" und den Ordner "dynamic" in den Container.
  • Mappe "docker.sock" nur lesend (ro = readonly) in den Container, damit Traefik Informationen aus anderen Containern lesen kann.
  • Die Labels definieren die Einstellungen für das Traefik Dashboard. Sie definieren die URL, die Beantragung des Zertifikats über das in der Traefik-Konfiguration definierte "letsencrypttls" und weisen dem Dashboard "simpleAuth" zu, damit die Seite durch einen Login geschützt ist.

Speichern und schließen mit
Win: STRG+O, ENTER, STRG+X
Mac: CONTROL+O, ENTER, CONTROL+X

Jetzt kann der Container erstellt und gestartet werden:

docker compose up -d && docker compose logs -f

Damit wird das notwendige Image geladen, der Container gemäß der Einstellungen in der yaml-Datei erstellt und anschließend im Hintergrund gestartet. Durch docker compose logs -f springen wir direkt nach der Erstellung ins Log des Containers und können verfolgen, ob alles ok aussieht. Die Ausgaben solten ungefähr so aussehen:

traefik  | time="2023-05-31T09:43:15+02:00" level=info msg="Configuration loaded from file: /traefik.yml"
traefik  | time="2023-05-31T09:43:15+02:00" level=info msg="Traefik version 2.10.1 built on 2023-04-27T14:52:35Z"
traefik  | time="2023-05-31T09:43:15+02:00" level=info msg="\nStats collection is disabled.\nHelp us improve Traefik by turning this feature on :)\nMore details on: https://doc.traefik.io/traefik/contributing/data-collection/\n"
traefik  | time="2023-05-31T09:43:15+02:00" level=info msg="Starting provider aggregator aggregator.ProviderAggregator"
traefik  | time="2023-05-31T09:43:15+02:00" level=info msg="Starting provider *file.Provider"
traefik  | time="2023-05-31T09:43:15+02:00" level=info msg="Starting provider *traefik.Provider"
traefik  | time="2023-05-31T09:43:15+02:00" level=info msg="Starting provider *docker.Provider"
traefik  | time="2023-05-31T09:43:15+02:00" level=info msg="Starting provider *acme.ChallengeTLSALPN"
traefik  | time="2023-05-31T09:43:15+02:00" level=info msg="Starting provider *acme.Provider"
traefik  | time="2023-05-31T09:43:15+02:00" level=info msg="Testing certificate renew..." providerName=letsencrypttls.acme ACME CA="https://acme-v02.api.letsencrypt.org/directory"
traefik  | time="2023-05-31T09:43:17+02:00" level=info msg=Register... providerName=letsencrypttls.acme

Log verlassen mit
Win: STRG+C
Mac: CONTROL+C

Dashboard aufrufen

Da Traefik jetzt läuft, müssen wir auch das Dashboard aufrufen können. Dazu geben wir die URL in den Browser ein, die wir in der docker-compose.yml bei den Traefik-Labels definiert haben. Du solltest dann direkt ein Popup vom Browser sehen, in dem du die von dir definierten Logindaten eingeben musst.

Login Traefik Dashboard - Browser Popup - Hier: macOS Safari

Nach der korrekten Eingabe dieser Daten wird dann das Dashboard von Traefik angezeigt.

Traefik Dashboard - Übersichtsseite - Dark Mode

Traefik ist einsatzbereit

Damit ist die Installation und Einrichtung von Traefik abgeschlossen. Um Traefik nun für weitere Dienste zu nutzen, muss der jeweilige Dienst nur dem Docker Netzwerk "traefik" beitreten und die Konfiguration in der docker-compose.yml des Dienstes über die Labels vorgenommen werden.

Beispiel-Labels für einen einfachen Container, der einen Webserver auf Port 80 bereitstellt. Der Port darf nicht nach außen freigegeben werden, denn nur Traefik soll eine Verbindung intern aufbauen:

[...]
    networks:
      - traefik
[...]
    labels:
      traefik.enable: true
      traefik.http.routers.beispielweb.entrypoints: websecure
      traefik.http.routers.beispielweb.rule: Host(`beispiel.eineadresse.de`)
      traefik.http.services.beispielweb.loadbalancer.server.port: 80
      traefik.http.routers.bitwarden.tls: true
      traefik.http.routers.bitwarden.tls.certresolver: letsencrypttls
[...]
networks:
  traefik:
    external: true
[...]

Bei Anmerkungen oder Fragen kommt gerne auf unseren Discord.

Join the IceFlom & maarsellow & Viertelwissen Discord Server!
Gemeinschaftsdiscord von IceFlom, Maarsellow und Viertelwissen

Tags