LW IT Solutions logo LW IT Solutions logo LW IT Solutions
« Blog-Übersicht /Raspberry Pi/Tutorials / Docker-Compose-Heimserver: Traefik, TLS und Update-Prüfung
Diesen Artikel in anderen Sprachen lesen:

Docker-Compose-Heimserver: Traefik, TLS und Update-Prüfung

Teil 4 von 7 der Reihe Homelab auf dem Raspberry Pi

Docker-Compose-Heimserver: Traefik, TLS und Update-Prüfung

Management Summary

Ein Heimserver kann mehrere lokale Dienste über einen gemeinsam verwalteten Zugang bereitstellen. Der beschriebene Aufbau leitet Browseranfragen zur passenden Anwendung, erneuert Zertifikate für verschlüsselte Verbindungen und meldet verfügbare Softwareupdates. Diese Automatisierung erleichtert die Pflege kleiner Installationen auf einem Raspberry Pi. Die Aufgaben bleiben verschieden: Eine Update-Meldung installiert noch keine Korrektur. Ein einzelnes Gerät bleibt außerdem ausfallgefährdet; gespeicherte Daten brauchen wiederherstellbare Sicherungen.

Inhalt
  1. Ein Heimserver mit klar verteilten Aufgaben
  2. 1. DNS, Images und Zertifikatsspeicher vorbereiten
  3. 2. Anfragen weiterleiten und Docker-Zugriff begrenzen
  4. 3. Erst Staging prüfen, dann vertrauenswürdige Zertifikate beziehen
  5. 4. Optional eine Update-Prüfung ergänzen
  6. Fragen und Antworten
  7. Quellen

Ein Heimserver mit klar verteilten Aufgaben

Traefik leitet eingehende Anfragen an Docker-Container weiter und kann TLS-Zertifikate über Let’s Encrypt beziehen und erneuern. TLS verschlüsselt die Verbindung zwischen Browser und Traefik. Docker Compose hält die Dienstkonfiguration in einer Datei fest. Watchtower kann Container-Images auf Änderungen prüfen. Das verringert Routinearbeit; Sicherungen, Überwachung und bewusst geplante Updates bleiben erforderlich.

Das folgende Beispiel dient als Ausgangspunkt für einen getrennten Testaufbau auf einem Raspberry Pi mit Docker Engine und Compose. Image-Architektur, Docker-API-Kompatibilität und die gewählten Versionen müssen zum Zielsystem passen. Ein einzelner Pi mit jeweils einem Anwendungscontainer bietet keine Hochverfügbarkeit.

Traefik leitet HTTPS-Anfragen weiter; ein eingeschränkter Socket-Proxy liefert Daten zur Diensterkennung. Der optionale Watchtower-Monitor installiert keine Updates.
Traefik leitet HTTPS-Anfragen weiter; ein eingeschränkter Socket-Proxy liefert Daten zur Diensterkennung. Der optionale Watchtower-Monitor installiert keine Updates.

1. DNS, Images und Zertifikatsspeicher vorbereiten

HTTP-01 benötigt eine administrativ kontrollierte Domain und einen aus dem Internet erreichbaren Port 80. Öffentliche A-/AAAA-Einträge, Portweiterleitung und IPv4-/IPv6-Firewallregeln müssen zusammenpassen. Die Host-Ports 80 und 443 müssen frei sein. DNS-01 ermöglicht Zertifikate ohne eingehende Verbindung, macht einen Server hinter CGNAT aber nicht erreichbar. Bei CGNAT teilen mehrere Anschlüsse eine öffentliche IPv4-Adresse des Internetanbieters; eine gewöhnliche Portweiterleitung am Heimrouter genügt dann nicht.

In einem beschreibbaren Projektordner legen die folgenden Befehle den Zertifikatsspeicher an, ohne vorhandene Dateien zu leeren. Neben Dateirechten 600 benötigt der Containerprozess passende Eigentumsrechte. Die Dateien enthalten private Schlüssel und gehören in geschützte Sicherungen.

Shell
mkdir -p data
touch data/acme-staging.json data/acme-production.json
chmod 600 data/acme-staging.json data/acme-production.json

Die Hauptkonfiguration erhält den Namen compose.yaml. Eine benachbarte .env definiert TRAEFIK_IMAGE, SOCKET_PROXY_IMAGE, WHOAMI_IMAGE, ACME_EMAIL und APP_HOST. Die Image-Werte sind vollständige Referenzen auf getestete Versionen von traefik, ghcr.io/tecnativa/docker-socket-proxy und traefik/whoami, möglichst mit dokumentierten Digests. Ein Digest ist ein aus dem Inhalt berechneter Prüfwert, der das genaue Image festlegt statt einer veränderbaren Versionsbezeichnung. Als Hostname dient eine eigene Test-Subdomain ohne Schema oder Pfad. Fehlende Werte brechen Compose ab, statt unbemerkt latest zu verwenden.

2. Anfragen weiterleiten und Docker-Zugriff begrenzen

YAML
services:
  socket-proxy:
    image: ${SOCKET_PROXY_IMAGE:?set tested image reference}
    restart: unless-stopped
    networks: [control]
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock:ro
    environment:
      CONTAINERS: "1"
      EVENTS: "1"
      NETWORKS: "1"
      PING: "1"
      VERSION: "1"
      POST: "0"
  traefik:
    image: ${TRAEFIK_IMAGE:?set tested Traefik v3 image reference}
    restart: unless-stopped
    depends_on: [socket-proxy]
    networks: [control, proxy]
    ports: ["80:80", "443:443"]
    volumes:
      - ./data:/data
    command:
      - --providers.docker=true
      - --providers.docker.endpoint=tcp://socket-proxy:2375
      - --providers.docker.exposedbydefault=false
      - --providers.docker.network=home_proxy
      - --entrypoints.web.address=:80
      - --entrypoints.web.http.redirections.entrypoint.to=websecure
      - --entrypoints.web.http.redirections.entrypoint.scheme=https
      - --entrypoints.websecure.address=:443
      - --certificatesresolvers.home.acme.email=${ACME_EMAIL:?set account email}
      - --certificatesresolvers.home.acme.storage=/data/${ACME_FILE:-acme-staging.json}
      - --certificatesresolvers.home.acme.caserver=${ACME_CA:-https://acme-staging-v02.api.letsencrypt.org/directory}
      - --certificatesresolvers.home.acme.httpchallenge.entrypoint=web
  whoami:
    image: ${WHOAMI_IMAGE:?set tested whoami image reference}
    restart: unless-stopped
    networks: [proxy]
    labels:
      traefik.enable: "true"
      traefik.http.routers.demo.rule: Host(`${APP_HOST:?set owned test hostname}`)
      traefik.http.routers.demo.entrypoints: websecure
      traefik.http.routers.demo.tls.certresolver: home
      traefik.http.services.demo.loadbalancer.server.port: "80"
      com.centurylinklabs.watchtower.enable: "true"
      com.centurylinklabs.watchtower.scope: home-demo
networks:
  control:
    internal: true
  proxy:
    name: home_proxy

Nur Traefik veröffentlicht Host-Ports. Die Anwendung teilt das Netzwerk home_proxy mit Traefik; im internen Netzwerk control befinden sich ausschließlich Traefik und der Socket-Proxy. Compose legt beide Netzwerke an. Der feste Netzwerkname muss auf dem Host eindeutig sein oder an beiden Stellen übereinstimmend geändert werden.

Traefik erhält keinen direkten Socket-Mount. Der Proxy erlaubt die aufgeführten Lese-Endpunkte und sperrt schreibende Methoden über POST=0. Auch Lesezugriffe offenbaren Container-Metadaten, möglicherweise einschließlich Umgebungsvariablen. Der Socket-Proxy selbst behält weitreichende Docker-Rechte; Netztrennung und vertrauenswürdige Images bleiben wichtig. Ein Socket-Mount mit :ro allein beschränkt die Docker-API nicht auf Lesezugriffe.

Ein Dashboard wird nicht freigegeben. HTTPS endet bei Traefik; zwischen Traefik und whoami verwendet das Beispiel HTTP. Eine durchgängige TLS-Verschlüsselung liegt damit nicht vor. Der Diagnosedienst whoami gibt Anfrageinformationen zurück und eignet sich nur für einen kurzen Routingtest ohne Zugangsdaten oder vertrauliche Header.

3. Erst Staging prüfen, dann vertrauenswürdige Zertifikate beziehen

docker compose config --quiet prüft die zusammengesetzte Konfiguration. Nach Kontrolle der aufgelösten Werte startet docker compose up -d den Testaufbau. docker compose logs traefik socket-proxy hilft bei der Diagnose von Diensterkennung, abgewiesenen API-Aufrufen und ACME-Fehlern. Abhängig von den gewählten Versionen kann eine Anpassung der erlaubten Lese-Endpunkte nötig sein; pauschaler Schreibzugriff ist keine Lösung.

Voreingestellt ist die Staging-Umgebung von Let’s Encrypt. Deren Zertifikaten vertrauen Browser absichtlich nicht. Nach erfolgreichen Routing- und Challenge-Prüfungen erhalten ACME_CA und ACME_FILE in .env die Werte https://acme-v02.api.letsencrypt.org/directory und acme-production.json. docker compose up -d traefik erstellt Traefik mit der geänderten Konfiguration neu. Staging und Produktion verwenden getrennte Dateien.

Zur Abnahme gehören HTTP-Weiterleitung, HTTPS-Hostname und Zertifikatskette, eine Ablaufüberwachung sowie ein tatsächlicher Anwendungsaufruf von außerhalb des Heimnetzes. Eine gefüllte JSON-Datei allein belegt kein gültiges öffentliches Zertifikat. DNS, Verbindungsprobleme, Dateirechte und Ratenbegrenzungen können die Erneuerung verhindern. Nach dem Test entfällt der Diagnosedienst.

4. Optional eine Update-Prüfung ergänzen

Das ursprüngliche Repository containrrr/watchtower wurde am 17. Dezember 2025 archiviert. Der Fork nicholas-fedor/watchtower veröffentlicht das Image nickfedor/watchtower. Die Auswahl benötigt eine eigene Bewertung von Pflegezustand und Kompatibilität; ein vertrauter Image-Name ist keine Sicherheitsgarantie.

Die optionale Datei monitor.yaml beobachtet nur Container mit Freigabe-Label und dem Geltungsbereich home-demo. Im Beispiel trägt ausschließlich whoami beide Labels. WATCHTOWER_IMAGE muss eine getestete Version referenzieren. docker compose -f compose.yaml -f monitor.yaml up -d ergänzt den Monitor. Bereits vorhandene Watchtower-Instanzen auf dem Host benötigen ebenfalls passende Auswahlregeln.

YAML
services:
  watchtower:
    image: ${WATCHTOWER_IMAGE:?set tested nickfedor/watchtower image reference}
    restart: unless-stopped
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock
    environment:
      WATCHTOWER_MONITOR_ONLY: "true"
      WATCHTOWER_LABEL_ENABLE: "true"
      WATCHTOWER_SCOPE: home-demo
      WATCHTOWER_POLL_INTERVAL: "86400"
      WATCHTOWER_CLEANUP: "false"
      WATCHTOWER_LABEL_TAKE_PRECEDENCE: "false"
      WATCHTOWER_LIFECYCLE_HOOKS: "false"
    labels:
      com.centurylinklabs.watchtower.enable: "false"
      com.centurylinklabs.watchtower.scope: home-demo

Dieser Modus ersetzt keine Container. Image-Downloads sind weiterhin möglich; Lifecycle-Hooks, also zusätzliche Befehle zu festgelegten Zeitpunkten des Ablaufs, sind ausdrücklich abgeschaltet. Ergebnisse stehen in den Logs; externe Benachrichtigungen benötigen eine eigene Einrichtung und Prüfung. Watchtower behält auch im Beobachtungsmodus den vollständigen Socket-Zugriff. Die Label-Auswahl ist eine Betriebsregel und keine Sicherheitsgrenze.

Für automatisiertes DNS-01 begrenzen eng zugeschnittene DNS-API-Zugangsdaten oder eine delegierte Challenge-Zone die Rechte; unbeschränkte DNS-Zugangsdaten gehören nicht in einen öffentlichen Anwendungscontainer.

Fragen und Antworten

Garantiert eine tägliche Prüfung Patches innerhalb von 24 Stunden?

Nein. Updates hängen von Image-Veröffentlichung, verfolgter Referenz, Registry-Erreichbarkeit und erfolgreicher Ausführung ab. Ein fester Digest folgt keinen neuen Versionen. Ein Versions-Tag kann verändert werden, aber auch ohne weitere Pflege bleiben. Der Monitor installiert nichts; gewählte Versionsreferenzen benötigen bewusste Aktualisierung.

Verhindern automatische Neustarts Ausfallzeiten?

Nein. Der Austausch eines einzelnen Anwendungscontainers unterbricht diese Instanz. Rolling Restarts allein schaffen weder Redundanz noch eine Datenmigration. Automatische Updates benötigen eine ausdrückliche Auswahl, geprüfte Zustandskontrollen, Sicherungen und ein Rückkehrverfahren für Image und Daten. Ein altes Image genügt nach einer inkompatiblen Datenbankmigration nicht.

Reicht eine IP-Freigabeliste für das Dashboard?

Das Beispiel veröffentlicht kein Dashboard. Ein späterer Verwaltungszugang benötigt Authentifizierung und beschränkten Zugriff, etwa über VPN. IP-Regeln hängen von der tatsächlichen Quelladresse und vertrauenswürdigen vorgeschalteten Proxys ab; breite private Adressbereiche belegen keine Identität.

Ist ein Beobachtungslauf vollständig lesend?

Nein. Monitor-only kann Images herunterladen; aktivierte Hooks können Befehle ausführen. Ein zweiter Prozess innerhalb eines laufenden Updaters hält den ursprünglichen Prozess nicht an. --no-pull unterbindet Downloads, ersetzt aber nicht den Beobachtungsmodus.

Homelab auf dem Raspberry Pi

  1. Raspberry Pi 4 und 5: Vom SSD-Laufwerk booten über den Bootloader
  2. USV für Raspberry Pi: fünf Lösungen und Auswahlkriterien
  3. Lokales CI/CD für den Raspberry Pi: Automatisierung von Docker-Compose-Deployments
  4. Docker-Compose-Heimserver: Traefik, TLS und Update-Prüfung
  5. Jellyfin auf Raspberry Pi 5: Direct Play und Grenzen der Transkodierung
  6. Raspberry Pi als gehärtetes WireGuard-VPN-Gateway mit Split-Tunneling
  7. Raspberry Pi mit Prometheus und Grafana überwachen
Lukas Wojcik

Lukas Wojcik

Systems architect and technology enthusiast specializing in scalable tracking solutions, GMP Stack (GA4 & GTM), and robust backend architectures. Advocate for clean code and privacy-first design.

Kontakt

Eine Frage oder eine Idee für ein Webprojekt? Schreib mir kurz, worum es geht. Das Formular nutzt reCAPTCHA zum Schutz vor Spam.

Kommentar schreiben

Erfahrungen mit anderen Modellen und Rückfragen zum Aufbau sind hier willkommen.

Die E-Mail-Adresse wird nicht veröffentlicht. Pflichtfelder sind mit einem Stern versehen.