Software Berater Logo Software Berater #neuland seit 1993

Træfik und OAuth

Mein Setup mehrerer Docker-Container für verschiedene Anwendungen hatte eine Schwäche: Um die Anwendungen verwenden zu können, habe ich sie per Nginx Proxy zugänglich gemacht. Einzeln, und von Hand. Das Verfahren war hinderlich. Jetzt verwende ich Traefik dafür, und OAuth zur Anmeldung. Wie das geht, zeige ich hier.

Traefik Proxy ist ein dynamischer Reverse-Proxy für containerisierte Anwendungen. Traefik arbeitet nahtlos mit Containerwerkzeugen wie Docker Compose, Swarm oder Kubernetes zusammen, und kann selbständig hinzukommende Anwendungen nach Regeln verfügbar machen, oder gestoppte Anwendungen entfernen. Traefik enthält unter anderem Load Balancing und ist damit geeignet, viele Instanzen einer Anwendung hochverfügbar zu machen.

traefik Dashboard

Ich hatte in der Vergangenheit einen ähnlichen Zweck mit manueller Arbeit verfolgt: Sorgfältig gewählte TCP-Ports auf Localhost habe ich mit einer manuellen nginx-Konfiguration an Server verbunden, Hostnamen gesetzt, Lets-Encrypt-Zertifikate eingerichtet und mehr. Viel Arbeit. Mit Traefik ist das einfacher: Anstatt Container und Proxy separat voneinander zu pflegen, setzt man Attribute (sog. Labels) am Container, welche Traefik auswertet. Schauen wir uns das mal an:

traefik/docker-compose.yml auf git.software-berater.net

Das ist die Datei docker-compose.yml für Traefik selbst. Durch sie wird der Service traefik definiert, und sein api@internal genanntes Dashboard auch gleich bekannt gemacht. Dazu dienen die labels-Zeilen, die man übrigens in Version 3 des docker-compose-Files auch als Dictionary formulieren darf.1

Der Eintrag traefik-forward-auth dient der OAuth Integration, dazu weiter unten mehr.

Neben der Datei docker-compose.yml lege ich ein Verzeichnis data an, dieses enthält zwei weitere Dateien:

traefik/data/traefik.yml auf git.software-berater.net

Diese Datei enthält die sog. statische Konfiguration von Traefik. Die hier gesetzten Werte könnten auch per Kommandozeile oder Umgebungsvariable gesetzt werden. Diese Datei legt grundlegende entryPoints fest, aktiviert den Lets-Encrypt-Support und das Dashboard.

traefik/data/dynamic_conf.yml auf git.software-berater.net

Im Gegensatz dazu bildet die zweite Datei die dynamische Konfiguration. Diese nennt man dynamisch, weil sie hauptsächlich zur Laufzeit von den Container-Attributen definiert wird - nur zusätzlich kann man auch zB eine Datei verwenden.

Anwendungsbeispiel

software-berater/docker-compose.yml auf git.software-berater.net

Das ist dann die docker-compose Definition einer Anwendung mit Traefik-Labels. Tatsächlich werden hier schon zwei Traefik-“Services” definiert:

  1. traefik.http.routers.swb hat nur die Aufgabe, eingehende http-Requests entgegenzunehmen und auf https umzuleiten.
  2. traefik.http.routers.swb-secure bildet die SSL-Konfiguration und regelt die LetsEncrypt Integration über den in der Datei data/traefik.yml (oben) konfigurierten Resolver namens http.

Wichtig ist, dass alle nach außen sichtbaren Anwendungen auf das passende Netzwerk konfiguriert wurden, hier: web.

Debugging Tipps

Um die Logausgaben eines systemd-Services zu beobachten, kann man diesen Befehl verwenden:

journalctl -u dc@traefik.service -f

Mit -u gibt man den Namen der zu beobachtenden Unit an, mit -f folgt die Ausgabe neuen Zeilen. Das funktioniert gut, ist aber unhandlich, wenn man ständig Änderungen macht und diese bewerten möchte. Wenn ich Änderungen am Service mache und deren Auswirkung beobachten will, dann

  1. stoppe ich den Service mit service <name> stop
  2. starte ich den Dienst von Hand mit docker-compose up --remove-orphans und lasse das im Terminal laufen
  3. beende ich den Dienst bei Bedarf mit strg-c und starte ihn ggfs neu
  4. setze ich am Ende den Dienst wieder automatisch fort: service <name> start

OAuth zur Anmeldung

Das gefällt mir besonders gut: Dienste wie zB das Dashboard benötigen eine Anmeldung. Ich will aber nicht viele separate Datenbanken mit Usernamen und Passworten pflegen. Da kommt es gelegen, dass das von mir bereits verwendete Gitea auch als OAuth-Provider fungieren kann: Die Anmeldung erfolgt dann in Gitea mit den dort konfigurierten Benutzern und Passworten, angeschlossene Anwendungen wie das Dashboard sehen das Passwort nie.

Dazu gibt es eine praktische Software namens traefik-forward-auth, die man als Middleware in Traefik einbinden kann. Eine solche Middleware wird aktiviert, bevor auf die eigentliche Zielanwendung zugegriffen wird. In der Datei docker-compose.yml oben definiere ich dazu in Zeile 13 die Middleware namens traefik-forward-auth und verwende sie in Zeile 46:

traefik.http.routers.traefik-secure.middlewares=traefik-forward-auth

Damit weise ich Traefik an, beim Zugriff auf den Service traefik-secure die Middleware traefik-forward-auth einzubinden, welche die Anmeldung an den konfigurierten OAuth Service delegiert. Die angegebene Datei server.env befindet sich absichtlich nicht im Git und schaut schematisch so aus:

PROVIDERS_GENERIC_OAUTH_AUTH_URL=<url>/login/oauth/authorize
PROVIDERS_GENERIC_OAUTH_TOKEN_URL=<url>/login/oauth/access_token
PROVIDERS_GENERIC_OAUTH_USER_URL=<url>/api/v1/user
PROVIDERS_GENERIC_OAUTH_CLIENT_ID=12345678901234567890
PROVIDERS_GENERIC_OAUTH_CLIENT_SECRET=123456abcdef123456abcdef123456a
PROVIDERS_GENERIC_OAUTH_TOKEN_STYLE=query
SECRET=<secret>

Siehe dazu auch die Dokumentation für die Gitea Einbindung.

Quellen