Traefik Reverse Proxy - HTTPS Webservices selber hosten
Um Web-Services, die bei uns zu Hause laufen, aus dem Internet zu erreichen, gibt es viele Möglichkeiten. Die schlechteste Möglichkeit wäre die Portfreigabe und Weiterleitung auf ein Gerät mit unverschlüsseltem Protokoll wie beispielsweise das HTTP oder FTP. Versuche es unbedingt zu vermeiden, eine einfache Portfreigabe auf HTTP oder FTP zu nutzen!
Besser wäre da schon das SFTP und bzw. oder ein VPN. Beide verlangen Zertifikate um Clients zu autorisieren und die Daten werden anschließend verschlüsselt übertragen.
Bei vielen Routern und Endgeräten ist die Einrichtung jedoch aufwendig und beispielsweise ist das Hauseigene VPN einer FritzBox, welches auf IPSec setzt, ist nicht besonders modern oder schnell.
Abhilfe schafft da WG-Easy (siehe Compose Templates) oder PiVPN, womit sich einfach WireGuard oder OpenVPN installieren lässt. Dazu habe ich bereits ein Video Tutorial erstellt, wie dies mit dem ei23 Smart Home Server funktioniert.
Ein VPN löst nicht alle Probleme
Was ist aber wenn unbestimmte viele Clients auf unser System zugreifen sollen, oder wir nicht jedem Nutzer ein Zertifikat zur Verfügung stellen möchten? Oder was ist wenn wir einen Service betreiben, der zeitweise mehr Ressourcen benötigt, als beispielsweise ein kleiner Raspberry Pi zur Verfügung stellen kann?
Hier kommen Reverse Proxies und SSL Zertifikate ins Spiel. Mit einem Reverse Proxy kann beispielsweise eine Domain oder Subdomain aufgerufen werden, und der Reverse-Proxy entscheidet dann, welcher Inhalt dem Nutzer zugänglich gemacht wird. Zusätzlich kann der Inhalt über SSL verschlüsselt werden. So ist es beispielsweise möglich, eine IP hinter mehreren Domains zu verstecken und trotzdem mehrere Services aufzurufen.
Traefik Architecture (Quelle: traefik.io)
Es gibt natürlich auch andere Lösungen, wie z.B. Nginx. Da der ei23 Smart Home Server jedoch viele Programme als Docker-Container betreibt, nutzen wir Traefik, welches für Programme im Docker nochmal einige Vorteile bringt und zu dem eine gutes visuelles Interface hat.
Proxy Konfiguration von Docker-Containern
Um einen Docker Container für Traefik zu konfigurieren, ist es lediglich notwendig die /home/pi/ei23-docker/docker-compose.yaml
anzupassen. Wie das geht, zeige ich im Video zu Version 1 vom Smart Home Skript.
Beispiel docker-compose Bitwarden
bitwarden:
image: bitwardenrs/server:latest
container_name: bitwarden
restart: unless-stopped
# ports:*
# - 2223:80
labels:
- traefik.enable=true
- traefik.http.routers.bitwarden.rule=Host(`example.com`)
- traefik.http.routers.bitwarden.entrypoints=web-secured
- traefik.http.routers.bitwarden.tls=true
- traefik.http.routers.bitwarden.tls.certresolver=letsEncrypt
volumes:
- ./volumes/bitwarden:/data
Mit Traefik ist es nicht zwingend notwendig die *Ports über Docker freizugeben, so lange Traefik sich im gleichen Dockernetzwerk wie die Container befindet. Daher sind diese im Beispiel oben mit # auskommentiert.
Beispiel: Webseite im LAN (in diesem Fall das ei23 Dashboard)
labels:
- traefik.enable=true
- traefik.http.routers.ei23-lan.rule=(Host(`192.168.178.10`) || Host(`smarthome`))
- traefik.http.routers.ei23-lan.priority=1
- traefik.http.routers.ei23-lan.entrypoints=lan
Beispiel docker-compose Grafana
labels:
- traefik.enable=true
- traefik.http.routers.grafana.rule=Host(`grafana.example.com`)
- traefik.http.services.grafana.loadbalancer.server.port=3000
- traefik.http.routers.grafana.entrypoints=web-secured
- traefik.http.routers.grafana.tls=true
- traefik.http.routers.grafana.tls.certresolver=letsEncrypt
Beispiel docker-compose Nextcloud
labels:
- traefik.enable=true
- traefik.http.routers.nextcloud.middlewares=nextcloud,nextcloud_redirect
- traefik.http.routers.nextcloud.tls.certresolver=letsEncrypt
- traefik.http.routers.nextcloud.rule=Host(`nextcloud.example.com`)
- traefik.http.routers.nextcloud.entrypoints=web, web-secured
- traefik.http.routers.nextcloud.tls=true
- traefik.http.middlewares.nextcloud.headers.stsSeconds=15552000
- traefik.http.middlewares.nextcloud.headers.stsPreload=true
- traefik.http.middlewares.nextcloud_redirect.redirectregex.permanent=true
- traefik.http.middlewares.nextcloud_redirect.redirectregex.regex=^https://(.*)/.well-known/(card|cal)dav
- traefik.http.middlewares.nextcloud_redirect.redirectregex.replacement=https://$${1}/remote.php/dav/
Wie man erkennen kann, gibt es für Traefik "Router, Services und Middlewares". Jeder Dienst benötigt mindestens einen eigenen Traefik-Router.
Proxy Konfiguration von LoadBalancern / externen (IP) Adressen und weiteren Geräten im Netzwerk
In /home/pi/ei23-docker/volumes/traefik/traefik/dynamic/config.yml
ist beispielsweise ein externer "Loadbalancer" für Home Assistant erstellt, da Home Assistant nicht innerhalb des Dockernetzwerks, sondern im Hostnetzwerk läuft. (Achtung! Die Zeileneinrückung muss stimmen - der Yaml Parser will das so)
http:
routers:
home-assistant:
rule: Host(`homeassistant.example.com`)
service: home-assistant
tls:
certresolver: letsEncrypt
services:
home-assistant:
loadBalancer:
servers:
- url: http://172.17.0.1:8123 # 172.17.0.1 ist das Standard Docker Gateway
Dieser verweist statt auf einen Docker Container auf eine http-URL. Diese wird über den "certresolver" anschließend auch über SSL verschlüsselt.
Inbetriebnahme von Traefik / SSL Zertifikate erstellen
Traefik selbst wird als Docker Container betrieben und in der aktuellen Version des ei23 Smart Home Servers ist Traefik bereits vorkonfiguriert, es müssen nur noch kleine Änderungen vorgenommen werden.
Docker-Compose für Traefik
traefik:
image: traefik:v2.4
container_name: traefik
ports:
- "80:80" # as internal http
- "591:591" # as external http
- "2280:8080" # config port
- "443:443"
volumes:
- /var/run/docker.sock:/var/run/docker.sock:ro
- ./volumes/traefik/traefik/:/etc/traefik/
- ./volumes/traefik/letsencrypt:/letsencrypt
restart: unless-stopped
Unter /home/pi/ei23-docker/volumes/traefik/traefik/
befindet sich die traefik.yaml
.
[...]
entryPoints:
lan:
address: :80
web:
address: :591
http:
redirections:
entrypoint:
to: web-secured
scheme: https
web-secured:
address: :443
certificatesResolvers:
letsEncrypt:
acme:
email: mail@example.com
storage: /letsencrypt/acme.json
caserver: https://acme-staging-v02.api.letsencrypt.org/directory # Dies ist der caserver zum Testen
# caserver: https://acme-v02.api.letsencrypt.org/directory
httpChallenge:
entryPoint: web
[...]
Hier sind drei Eingangspunkte, die so genannten Entrypoints, definiert: - Port 80 (lan) ist für HTTP im Heimnetz (LAN) reserviert. - Port 591 (web) ist für HTTP nach außen (WAN) reserviert - Der externe Port 80 muss auf den internen Port 591 des Raspberry Pi weitergeleitet werden. Da wir ausschließlich verschlüsselte Verbindungen nutzen wollen, erzwingen wir mit Traefik eine Weiterleitung auf den web-secured Entrypoint (443). - Port 443 (web-secured) ist schließlich der Port für HTTPS. Dieser muss nach außen am Router freigegeben und eine Weiterleitung zum Raspberry Pi auf der Port 443 eingerichtet werden.
Die Verschlüsselung wird realisiert mit SSL.
Nach Ausführen von Docker Compose (ei23 dc
) und einem Neustart von Traefik werden die Labels von Traefik eingelesen und die Zertifikate erstellt.
Bevor aber ein Zertifikat erstellt werden kann, sollte eine Email Adresse hinterlegt werden. Darüber wird man ggf. über den Ablauf eines Zertifikates oder andere Warnungen bezüglich der Sicherheit informiert.
Der Dienst Let’s Encrypt ist so freundlich uns die sonst sehr teuren Zertifikate kostenlos zur Verfügung zu stellen. Allerdings gibt es ein Tages- und Wochenlimit, solange wir nur testen, ob alles klappt, sollten wir den “staging” caserver nutzen; hier wird kein offizielles Zertifikat ausgestellt.
Ein guter Webbrowser gibt beim Aufruf einer Adresse eine Warnung aus, wenn das Zertifikat nicht sicher bzw. echt ist. Wenn man diese Warnung akzeptiert und alle gewünschten Dienste dennoch erreichbar sind, dann kann man vom staging caserver zum offiziellen wechseln. Anschließend werden offizielle Zertifikate erstellt und die Webdienste sind nach kurzer Zeit offiziell verschlüsselt erreichbar.
Wenn Traefik und die Portweiterleitungen gemäß dieser Anleitung richtig konfiguriert worden sind, dann tauchen in der Datei /home/pi/ei23-docker/volumes/traefik/letsencrypt/acme.json
nach und nach die Zeilen mit den Schlüsseln zu deinen verschiedenen Domains / Subdomains auf.
Diese Basis Konfiguration sollte für den Heimserver bereits mehr als genug Funktionalität bieten. Wer dennoch weiter in die Materie einsteigen will: Traefik hat eine sehr gute Dokumentation: doc.traefik.io/traefik.