Traefik Reverse Proxy – HTTPS Webservices selber hosten

26. April 2021

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 vermeinden 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 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 unbestimmt 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

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-dockerdocker-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öntigt 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 Dockernetzwerk 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, so lange 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 ist, 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
Das sieht dann in etwa so aus:

[...]
   "Certificates": [
      {
        "domain": {
          "main": "nextcloud.example.com"
        },
        "certificate":
[...]

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


3 Antworten zu “Traefik Reverse Proxy – HTTPS Webservices selber hosten”

  1. Andreas Meier sagt:

    Vielen Dank für die Anleitung – jetzt heißt es probieren….. der Abend ist gesichert 😉

  2. Hans sagt:

    Danke für die Anleitung und vor allem das tolle Skript =) leider bekomme ich meine Nextcloud nicht mit meiner Domain über den Traefik Reverse Proxy zum laufen 🙁 Gibt es eventuell ein neues Tutorial? Bei YouTube finde ich nur das alte für NextcloudPi. Sehr cooles Projekt!!! weiter so und viele Grüße

    • Felix sagt:

      Gerne!
      Ist richtig, ein Tutorial gibt es nur für NextcloudPi, das für das offizielle Nextcloud steht noch aus.
      Es fehlt aber nicht viel:
      In den docker compose templates ist die config für traefik ja schon drin und dann fehlen nur noch ein paar Zeilen in der /home/pi/ei23-docker/volumes/nextcloud/html/config/config.php

        array (
          0 => 'example.com',
        ),
        'trusted_proxies' => 
        array (
          0 => '172.18.0.0/16',
        ),
        'overwrite.cli.url' => 'https://example.com',
        'overwritehost' => 'example.com',
        'overwriteprotocol' => 'https',
      

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert.