Homepage Dashboard mit Docker Compose installieren und absichern
Diese Anleitung installiert Homepage mit Docker Compose unter /opt/homepage, bindet Dienste über YAML ein und erklärt Docker-Integration, Host-Prüfung, TLS, Authentifizierung sowie den sicheren Umgang mit dem Docker-Socket.

Mit jedem zusätzlichen Self-Hosting-Dienst wächst dasselbe praktische Problem: Weboberflächen liegen auf verschiedenen Hosts und Ports, der Zustand einzelner Container ist nur über weitere Werkzeuge sichtbar, und wichtige Zugänge verteilen sich auf Lesezeichen und Notizen. Ein internes Dashboard löst diesen Katalog nicht allein, schafft aber einen festen Einstiegspunkt für Dienste, Statuskontrolle und Zugang.
Homepage ist dafür eine schlanke, statisch generierte Startseite. Laut Projekt unterstützt sie über 100 Dienste und Integrationen sowie mehr als 40 Sprachen und läuft auf amd64 und arm64. Einträge werden in YAML oder über Docker Labels gepflegt. API-Anfragen an konfigurierte Backends werden vom Homepage-Server weitergeleitet, sodass Zugangsdaten nicht im Browser landen, aber weiterhin auf dem Server geschützt werden müssen.
1. Architektur und Sicherheitsziel festlegen
Diese Installation legt Konfiguration und Daten unter /opt/homepage ab. Der Container veröffentlicht Port 3000 zunächst nur auf der Loopback-Adresse des Docker-Hosts, ist also nicht direkt aus LAN oder Internet erreichbar. Der Zugriff erfolgt später über VPN oder einen Reverse Proxy mit TLS und zusätzlicher Anmeldung.
| Baustein | Aufgabe | Sicherheitsentscheidung |
|---|---|---|
| Homepage | Dashboard und Proxy für Integrationsanfragen | Läuft ohne Root-Rechte, nur auf 127.0.0.1 |
| Konfigurationsverzeichnis | YAML-Dateien, ggf. Zugangsdaten | Nur festgelegte UID/GID erhalten Schreibrechte |
| Reverse Proxy oder VPN | Kontrollierter Zugriff | TLS, Authentifizierung, korrekter Host-Header |
| Docker-Socket | Containerstatus, Auto-Erkennung | Optional, bevorzugt über Socket-Proxy |
Homepage ersetzt weder VPN noch Identity Provider. Wer Port 3000 direkt ins Internet veröffentlicht, macht aus einer internen Übersicht eine zusätzliche Angriffsfläche.
2. Verzeichnisse und nicht privilegierten Benutzer vorbereiten
Ermitteln Sie zuerst UID und GID des Kontos, das die Dateien besitzen soll.
id -u
id -g
sudo install -d -m 0750 -o "$(id -u)" -g "$(id -g)" /opt/homepage
sudo install -d -m 0750 -o "$(id -u)" -g "$(id -g)" /opt/homepage/config
cd /opt/homepage
printf 'PUID=%s\nPGID=%s\n' "$(id -u)" "$(id -g)" | sudo tee .env > /dev/null
sudo chown "$(id -u):$(id -g)" .env
sudo chmod 0600 .env
PUID und PGID sorgen dafür, dass der Prozess und neu geschriebene Dateien nicht Root gehören. Das reduziert Schäden bei einer kompromittierten Anwendung, ist aber keine vollständige Isolation vom Docker-Daemon und Kernel.
3. Vollständige Docker-Compose-Konfiguration erstellen
Speichern Sie diese Datei als /opt/homepage/compose.yaml. Ersetzen Sie dashboard.example.lan durch den tatsächlichen DNS-Namen. HOMEPAGE_ALLOWED_HOSTS akzeptiert eine kommagetrennte Liste, tragen Sie jeden genutzten Namen ein.
services:
homepage:
image: ghcr.io/gethomepage/homepage:latest
container_name: homepage
restart: unless-stopped
ports:
- "127.0.0.1:3000:3000"
environment:
HOMEPAGE_ALLOWED_HOSTS: "dashboard.example.lan,localhost:3000,127.0.0.1:3000"
PUID: "${PUID}"
PGID: "${PGID}"
volumes:
- /opt/homepage/config:/app/config
security_opt:
- no-new-privileges:true
cap_drop:
- ALL
read_only: true
tmpfs:
- /tmp:size=64m,mode=1777
healthcheck:
test: ["CMD-SHELL", "wget -qO- http://127.0.0.1:3000/ >/dev/null || exit 1"]
interval: 30s
timeout: 5s
retries: 3
start_period: 20s
Die feste Bindung 127.0.0.1:3000:3000 ist strenger als eine Veröffentlichung auf allen Interfaces. Liegt der Reverse Proxy auf einem anderen Host, nutzen Sie ein VPN zwischen den Hosts. Veröffentlichen Sie nicht gedankenlos 3000:3000. read_only, cap_drop und no-new-privileges begrenzen Schreibrechte und Linux-Capabilities auf das Nötige.
4. Grundkonfiguration und Dienste in YAML anlegen
Homepage liest die Konfiguration aus /app/config. Legen Sie mindestens settings.yaml, services.yaml, bookmarks.yaml und widgets.yaml an.
cd /opt/homepage/config
printf '%s\n' 'title: Infrastruktur' 'language: de' 'target: _self' > settings.yaml
printf '%s\n' '[]' > bookmarks.yaml
printf '%s\n' '[]' > widgets.yaml
chmod 0640 settings.yaml bookmarks.yaml widgets.yaml
Die Datei services.yaml gruppiert Links und optionale Widgets:
- Infrastruktur:
- Traefik:
icon: traefik.svg
href: https://proxy.example.lan
description: Reverse Proxy und Zertifikate
- Beszel:
icon: beszel.svg
href: https://monitoring.example.lan
description: Serverstatus und Ressourcen
- Speicher:
- Dateidienst:
icon: mdi-folder-network
href: https://files.example.lan
description: Zentraler interner Dateizugriff
Schreiben Sie API-Schlüssel nicht in href oder Beschreibungen. Widgets benötigen je nach Integration Benutzername, Passwort oder Token, diese Werte liegen als YAML auf dem Host und benötigen restriktive Rechte:
sudo chown -R "$(id -u):$(id -g)" /opt/homepage/config
find /opt/homepage/config -type d -exec chmod 0750 {} \;
find /opt/homepage/config -type f -exec chmod 0640 {} \;
5. Konfiguration prüfen und Container starten
cd /opt/homepage
docker compose config --quiet
docker compose pull
docker compose up -d
docker compose ps
docker compose logs --no-log-prefix --tail=100 homepage
Testen Sie danach mit erlaubtem und mit fremdem Host-Header. Der erste Aufruf prüft die Anwendung, der zweite die Schutzwirkung der Host-Liste:
curl -I -H 'Host: localhost:3000' http://127.0.0.1:3000/
curl -I -H 'Host: unerlaubt.example' http://127.0.0.1:3000/
Bleibt der Container unhealthy, prüfen Sie zuerst das Log. Entfernen Sie den Healthcheck nicht nur wegen eines roten Status, sondern klären Sie Ursache und Startzeit.
6. Docker-Integration bewusst aktivieren
Homepage kann Container erkennen und deren Zustand anzeigen. Dafür benötigt es Zugriff auf eine Docker-Instanz über docker.yaml sowie server und container in services.yaml. Eine direkte Einbindung von /var/run/docker.sock ist funktional einfach, sicherheitstechnisch aber kritisch: Der Docker-Socket ist keine harmlose Statusdatei. Wer darüber Docker-Befehle ausführen kann, kann üblicherweise privilegierte Container starten, Host-Verzeichnisse einbinden und damit faktisch Root-Rechte auf dem Host erlangen. Ein nur lesbar eingebundener Socket verhindert nicht automatisch schreibende API-Aufrufe.
volumes:
- /opt/homepage/config:/app/config
- /var/run/docker.sock:/var/run/docker.sock:ro
local-docker:
socket: /var/run/docker.sock
- Infrastruktur:
- Traefik:
icon: traefik.svg
href: https://proxy.example.lan
description: Reverse Proxy und Zertifikate
server: local-docker
container: traefik
Für produktive Systeme ist ein Docker-Socket-Proxy die bessere Grenze. Er stellt nur benötigte, möglichst lesende API-Bereiche bereit, behält aber selbst den mächtigen Socket-Zugriff und muss isoliert und ausschließlich über ein internes Docker-Netz erreichbar sein. Aktivieren Sie keine Endpunkte für Container-Erstellung, Exec, Images, Volumes oder Schreiboperationen. Noch sicherer ist Verzicht auf Auto-Erkennung und rein manuelle Pflege in services.yaml.
7. Zugriff mit TLS, VPN und Anmeldung absichern
Für Zugriff aus mehreren Netzen empfiehlt sich ein VPN, dann bleibt Port 3000 intern. Wird Homepage über einen Reverse Proxy bereitgestellt, muss dieser HTTPS erzwingen, einen gültigen Host-Header weitergeben und eine zusätzliche Zugriffskontrolle umsetzen. Eine passende Schrittfolge zeigt Traefik als Docker Reverse Proxy mit HTTPS einrichten. Der externe Name muss exakt in HOMEPAGE_ALLOWED_HOSTS stehen, und der Proxy darf den ursprünglichen Host nicht durch einen internen Namen ersetzen.
- Port 3000 nur an Loopback oder ein ausdrücklich freigegebenes internes Interface binden.
- HTTPS am Reverse Proxy erzwingen und HTTP auf HTTPS umleiten.
- Ein internes Dashboard nicht öffentlich indexieren lassen.
- OIDC bevorzugen, wenn bereits ein Identity Provider mit Mehrfaktor-Authentifizierung vorhanden ist.
- Die einfache Anmeldung nur als Zusatzschutz mit starken, einzigartigen Zugangsdaten einsetzen.
- Admin-Oberflächen der verlinkten Dienste weiterhin separat authentifizieren.
- Proxy und Homepage regelmäßig aktualisieren und Änderungen kontrolliert testen.
Homepage bietet optional OIDC und eine einfache Anmeldung. Welche Methode passt, hängt von der vorhandenen Identitätsinfrastruktur ab. Vermeiden Sie widersprüchliche Ketten, in denen Weiterleitungen oder Header zwischen mehreren Authentifizierungsschichten unklar sind.
8. Updates, Backups und laufende Kontrolle
Das Tag latest ermöglicht einfache Aktualisierung, aber Updates sollten trotzdem kontrolliert erfolgen: Image in einem Wartungsfenster ziehen, Release-Hinweise lesen, vorher sichern, danach Logs, Healthcheck, Widgets und Anmeldung prüfen.
cd /opt/homepage
tar -C /opt -czf "/var/backups/homepage-config-$(date +%F).tar.gz" homepage/config
docker compose pull
docker compose up -d
docker compose ps
Eine Sicherung der Konfiguration kann Geheimnisse enthalten und gehört verschlüsselt mit begrenztem Zugriff gespeichert. Für Container-Härtung, Secrets und Healthchecks ergänzt Docker Compose mit Secrets, Healthchecks und Non-Root absichern diese Maßnahmen.
- Monatlich prüfen, ob ein neues Image oder sicherheitsrelevante Release-Hinweise vorliegen.
- Nach Updates alle Widgets auf Authentifizierungsfehler und Zeitüberschreitungen kontrollieren.
- Konfigurationssicherungen regelmäßig durch eine Wiederherstellung in einer Testumgebung prüfen.
- Nicht mehr benötigte API-Token widerrufen und Widget-Rechte auf reine Leserechte begrenzen.
- Firewall-Regeln und erlaubte Hostnamen nach DNS- oder Proxy-Änderungen erneut testen.
Homepage zeigt Zustände übersichtlich an, ist aber kein vollwertiges Monitoring mit Alarmierung und Historie. Dafür eignet sich eine getrennte Lösung wie Beszel Server Monitoring mit Docker installieren.
9. Abnahmecheck für den produktiven Betrieb
Die Installation ist erst abgeschlossen, wenn auch die Grenzen überprüft wurden. Arbeiten Sie diese Punkte nach Änderungen an Compose, DNS, Proxy oder Authentifizierung erneut ab:
docker compose config --quietendet ohne Fehler.- Der Container läuft mit vorgesehener UID und GID statt als Root.
- Port 3000 lauscht nur auf der geplanten Adresse.
- Ein erlaubter Host-Header funktioniert, ein fremder wird abgewiesen.
- Der externe Zugriff nutzt ein gültiges TLS-Zertifikat.
- VPN oder Authentifizierung blockieren nicht angemeldete Nutzer.
- Konfigurationsdateien sind nicht für andere lokale Benutzer lesbar.
- API-Token der Widgets besitzen nur erforderliche Leserechte.
- Der Docker-Socket fehlt vollständig oder ist über einen eingeschränkten Proxy vermittelt.
- Backup und Wiederherstellung der YAML-Konfiguration wurden getestet.
Passende Anleitungen auf S-EDV
- Traefik als Docker-Reverse-Proxy mit automatischem HTTPS einrichten
- Docker Compose absichern: Secrets, Healthchecks und Non-Root-Betrieb
- Beszel als leichtgewichtiges Server-Monitoring per Docker installieren
Quellen
- Homepage auf GitHub, Projektbeschreibung, Plattformen, Sprachen und Integrationen.
- Offizielle Docker-Installation, Container-Image, Volumes, Umgebungsvariablen und erlaubte Hosts.
- Offizielle Konfiguration von Diensten, Aufbau und Felder der
services.yaml. - Offizielle Docker-Integration, Docker-Server, Socket und Container-Zuordnung.