Zum Inhalt springen
Serverküche
Suche

Die Suche wird geladen … (nur in der veröffentlichten Seite verfügbar).

Anwendungen Schwierigkeit: Fortgeschritten

Homepage: das Dashboard für alle deine selbstgehosteten Dienste

Ein aufgeräumtes Start-Dashboard für deinen Server: Homepage verlinkt alle Dienste, zeigt Systemlast und live den Docker-Container-Status – hinter Traefik.

· 8 Min. Lesezeit ·Dauer: ca. 45 Minuten
Inhaltsverzeichnis

Je mehr Dienste du selbst hostest, desto mehr Lesezeichen und IP-Adressen musst du dir merken. Ein Dashboard löst das: eine einzige Startseite, die alle deine selbstgehosteten Dienste verlinkt, die Systemlast zeigt und dir sogar sagt, welche Container gerade laufen. Homepage ist dafür das schönste und schnellste Werkzeug.

Was bauen wir?

Ein zentrales Dashboard mit Homepage (v2.4.0) hinter Traefik, das du komplett über einfache YAML-Dateien konfigurierst. Am Ende hast du eine aufgeräumte Startseite mit Kacheln für alle Dienste, Widgets für CPU/RAM/Festplatte, ein Suchfeld – und die Killer-Funktion: Homepage liest den Docker-Socket und zeigt live an, ob ein Container läuft. Seit Version 2 bringt Homepage außerdem eine eigene Anmeldung mit, sodass das Dashboard nicht offen im Netz steht (Schritt 7). Alles statisch generiert, ohne Datenbank, mit winzigem Ressourcenbedarf.

Voraussetzungen

🍳 Empfehlung Anzeige

VPS 1000 G12.5

4 vCore · 8 GB RAM · 128 GB SSD

ab 14,50 €/Monat

Homepage ist extrem genügsam – läuft problemlos neben deinem übrigen Stack.

Zu netcup →

💶 1 Monat gratis:

Einmal einlösbar, gilt für VPS 1000 G12.5. Im Warenkorb einlösen →

💶 5,95 € Gutschein für netcup-Neukunden: immer gültig · nicht für Domains und VPS Lite

Alle netcup-Gutscheine →

Schritt für Schritt

Schritt 1: Projekt und Konfigurationsordner anlegen

Homepage wird ausschließlich über YAML-Dateien in einem config-Ordner gesteuert. Lege die Struktur an:

Terminal
mkdir -p /opt/homepage/config /opt/homepage/icons && cd /opt/homepage

Schritt 2: Grundeinstellungen

Die config/settings.yaml bestimmt Aussehen und Layout. Wir definieren zwei Gruppen als Zeilen-Layout mit je drei Spalten:

YAML
title: Meine Serverküche
theme: dark
color: slate
headerStyle: boxed
layout:
  Infrastruktur:
    style: row
    columns: 3
  Medien:
    style: row
    columns: 3

Die Namen unter layout: (Infrastruktur, Medien) müssen später exakt mit den Gruppennamen in der Dienste-Datei übereinstimmen – nur dann greift das Layout.

Schritt 3: Dienste verlinken

Die config/services.yaml ist das Herzstück – deine Kacheln. Jeder Dienst bekommt einen Namen, eine URL, eine Beschreibung und ein Icon (Homepage lädt passende Icons automatisch aus einem großen Katalog, wenn du name.png angibst):

YAML
- Infrastruktur:
    - Nextcloud:
        href: https://cloud.DEINE_DOMAIN
        description: Eigene Cloud
        icon: nextcloud.png
    - Vaultwarden:
        href: https://vault.DEINE_DOMAIN
        description: Passwortmanager
        icon: vaultwarden.png
- Medien:
    - Immich:
        href: https://fotos.DEINE_DOMAIN
        description: Fotos
        icon: immich.png
    - Jellyfin:
        href: https://media.DEINE_DOMAIN
        description: Medienserver
        icon: jellyfin.png

So verlinkst du deine bereits installierten Dienste wie Nextcloud, Immich, Jellyfin oder Vaultwarden an einer zentralen Stelle.

Schritt 4: Widgets für Systemlast und Suche

Die config/widgets.yaml steuert die Info-Leiste oben. Ressourcen-Anzeige, ein Suchfeld und Datum/Uhrzeit:

YAML
- resources:
    cpu: true
    memory: true
    disk: /
- search:
    provider: duckduckgo
    target: _blank
- datetime:
    text_size: xl
    format:
      dateStyle: full
      timeStyle: short

Das resources-Widget zeigt die Auslastung des Hosts. CPU und RAM liest Homepage direkt aus dem Container heraus (kein Docker-Socket nötig); den Socket binden wir erst im nächsten Schritt für den Container-Status ein.

Schritt 5: Mit Traefik verbinden – und der entscheidende Host-Schutz

Jetzt die compose.yaml. Ersetze DEINE_DOMAIN durch deine echte Subdomain:

YAML
services:
  homepage:
    image: ghcr.io/gethomepage/homepage:v2.4.0
    restart: unless-stopped
    environment:
      HOMEPAGE_ALLOWED_HOSTS: DEINE_DOMAIN
    volumes:
      - ./config:/app/config
      - ./icons:/app/public/icons
    networks: [proxy]
    labels:
      - "traefik.enable=true"
      - "traefik.http.routers.homepage.rule=Host(`DEINE_DOMAIN`)"
      - "traefik.http.routers.homepage.entrypoints=websecure"
      - "traefik.http.routers.homepage.tls.certresolver=le"
      - "traefik.http.services.homepage.loadbalancer.server.port=3000"

networks:
  proxy:
    external: true

HOMEPAGE_ALLOWED_HOSTS ist Pflicht

Seit Version 1.x weigert sich Homepage aus Sicherheitsgründen (Schutz vor DNS-Rebinding), Anfragen unter einem unbekannten Hostnamen zu beantworten. Ohne die Umgebungsvariable HOMEPAGE_ALLOWED_HOSTS mit deiner Domain bekommst du statt des Dashboards ein HTTP 400 mit {"error":"Host validation failed. See logs for more details."}. Trage dort exakt deine Domain ein – mehrere durch Komma getrennt.

Starte das Dashboard:

Terminal
docker compose up -d

Prüfe von außen, dass es mit gültigem HTTPS antwortet:

Terminal
curl -sI https://DEINE_DOMAIN/ | head -1
Ausgabe
HTTP/2 200

Im Browser siehst du jetzt dein Dashboard mit den Kacheln und der Info-Leiste:

Das Homepage-Dashboard mit Gruppen für Infrastruktur und Medien, Ressourcen-Widgets und Suchfeld
Das fertige Dashboard – Dienste-Kacheln, CPU/RAM/Disk und Suche auf einer Seite

Schritt 6: Live-Container-Status über den Docker-Socket

Die stärkste Funktion: Homepage kann direkt aus Docker lesen, ob ein Container läuft, und CPU/RAM je Container anzeigen. Dafür legst du config/docker.yaml an:

YAML
my-docker:
  socket: /var/run/docker.sock

Dann bindest du den Socket schreibgeschützt in den Container ein – ergänze in der compose.yaml unter volumes::

YAML
      - /var/run/docker.sock:/var/run/docker.sock:ro

Und verknüpfst eine Kachel mit ihrem Container (server verweist auf den Namen aus docker.yaml, container auf den echten Container-Namen):

YAML
- Infrastruktur:
    - Traefik:
        description: Reverse Proxy
        icon: traefik.png
        server: my-docker
        container: traefik-traefik-1

Nach docker compose up -d zeigt die Kachel ein grünes Status-Abzeichen, sobald der Container läuft:

Das Dashboard mit einer Traefik-Kachel, die live den Status RUNNING aus Docker anzeigt
Live-Status: die Traefik-Kachel meldet direkt aus dem Docker-Socket „RUNNING“

Der Docker-Socket ist mächtig – nur lesend einbinden

Zugriff auf /var/run/docker.sock ist faktisch Root-Zugriff auf den Host (siehe Benutzer & Rechte). Binde ihn deshalb immer mit :ro (read only) ein und veröffentliche Homepage nicht ungeschützt im Internet. Ab hier gehört eine Anmeldung davor – die baut der nächste Schritt ein.

Schritt 7: Das Dashboard mit einem Passwort schützen

Bis Version 1 hatte Homepage keine eigene Anmeldung; man musste eine BasicAuth-Middleware in Traefik davorhängen. Seit Version 2 bringt Homepage einen Login mit. Für ein Dashboard, das den Docker-Socket liest, ist er Pflicht.

Secret und Passwort gehören nicht in die compose.yaml, sondern daneben in eine .env. Erzeuge zuerst ein zufälliges Secret – damit signiert Homepage das Sitzungs-Cookie, es muss mindestens 32 Zeichen haben:

Terminal
echo "HOMEPAGE_AUTH_SECRET=$(openssl rand -base64 32)" > .env

Häng dein Passwort an und nimm der Datei die Leserechte für alle anderen. Ersetze DEIN_DASHBOARD_PASSWORT durch ein langes, nur hier verwendetes:

Terminal
echo "HOMEPAGE_AUTH_PASSWORD=DEIN_DASHBOARD_PASSWORT" >> .env
chmod 600 .env

Ergänze in der compose.yaml unter environment: diese vier Zeilen. HOMEPAGE_EXTERNAL_URL ist die Adresse, unter der du das Dashboard im Browser aufrufst; die beiden ${…} holt Compose automatisch aus der .env, sodass die Geheimnisse nicht in der Compose-Datei stehen:

YAML
      HOMEPAGE_AUTH_ENABLED: "true"
      HOMEPAGE_EXTERNAL_URL: https://DEINE_DOMAIN
      HOMEPAGE_AUTH_SECRET: ${HOMEPAGE_AUTH_SECRET}
      HOMEPAGE_AUTH_PASSWORD: ${HOMEPAGE_AUTH_PASSWORD}

Neu starten:

Terminal
docker compose up -d

Jetzt landet jeder Aufruf zuerst auf der Anmeldeseite. Von außen siehst du das daran, dass / nicht mehr mit 200 antwortet, sondern weiterleitet:

Terminal
curl -sI https://DEINE_DOMAIN/ | head -1
Ausgabe
HTTP/2 307

Im Browser erscheint die Anmeldemaske – mit dem Titel aus deiner settings.yaml:

Die Anmeldeseite von Homepage mit dem Dashboard-Titel und einem einzelnen Passwortfeld
Der eingebaute Login seit Homepage 2 – ein Passwortfeld, kein Benutzername

Einen Benutzernamen gibt es nicht, nur dieses eine Passwort.

Homepage bremst Rate-Attacken nicht selbst

Falsche Anmeldeversuche laufen ungebremst durch – Homepage hat kein eigenes Rate-Limit. Steht das Dashboard offen im Internet, gehört eine Ratenbegrenzung vor die Login-Route /api/auth/callback/credentials, etwa mit Traefiks rateLimit-Middleware oder fail2ban. Und die .env mit Secret und Passwort gehört in kein Git-Repository.

Schritt 8: Lesezeichen ergänzen (optional)

Neben Diensten kann Homepage auch reine Lesezeichen anzeigen – über config/bookmarks.yaml:

YAML
- Entwicklung:
    - Serverküche:
        - abbr: SK
          href: https://serverkueche.de

Damit hast du Dienste, Systemlast, Suche und Lesezeichen an einem Ort. Änderungen an den YAML-Dateien übernimmt Homepage automatisch – ein Neuladen im Browser genügt meist, kein Neustart nötig.

Wenn es nicht funktioniert

„Host validation failed" statt Dashboard. Die häufigste Stolperfalle: HOMEPAGE_ALLOWED_HOSTS fehlt oder enthält die falsche Domain. Genau die Domain eintragen, unter der du zugreifst, dann docker compose up -d.

Die Ressourcen-Widgets zeigen keine oder falsche Werte. CPU und RAM liest Homepage aus dem Container heraus (kein Socket nötig). Zeigt disk: / das Container-Dateisystem statt der Host-Platte, binde den gewünschten Pfad zusätzlich als Volume ein (z. B. - /:/host:ro und disk: /host).

Ein Icon wird nicht geladen. Der Name passt nicht zum Icon-Katalog. Schreibe den Dienstnamen klein und ohne Leerzeichen (nextcloud.png), oder lege ein eigenes Bild in den icons-Ordner (gemountet nach /app/public/icons) und referenziere es als /icons/name.png.

Die Container-Kachel zeigt keinen Status. Der Wert bei container: muss der exakte Container-Name sein. Finde ihn mit docker ps --format '{{.Names}}' – bei Compose ist das meist ordner-dienst-1 (z. B. traefik-traefik-1).

Änderungen an den YAML-Dateien greifen nicht. Ein Syntaxfehler bricht das Einlesen ab. YAML ist einrückungsempfindlich – prüfe die Logs mit docker compose logs homepage auf error-Zeilen und achte auf konsequente Leerzeichen (keine Tabs).

Statt der Anmeldemaske kommt „Authentication error – Auth is disabled or misconfigured". Dann ist HOMEPAGE_AUTH_ENABLED gesetzt, aber Secret oder Passwort kommen leer im Container an – meist, weil die .env im falschen Ordner liegt oder eine Zeile daraus fehlt. Im Log steht dazu Password auth is enabled but required settings are missing; docker compose config zeigt dir, welche Werte Compose wirklich einsetzt.

Dein Problem ist nicht dabei? Alle Fehlermeldungen durchsuchen →

Wartung & Backups

  • Updates sind unkritisch. Homepage hat keinen persistenten Zustand außer deinen Config-Dateien. Bump den Image-Tag (ghcr.io/gethomepage/homepage:v2.4.0) gelegentlich auf die neue Version und docker compose up -d; das übernimmt sonst dein normaler Update-Prozess. Prüfe nach größeren Sprüngen die Release-Notes, da sich Config-Optionen ändern können. Beim Sprung von 1.x auf 2.x bleiben settings.yaml, services.yaml, widgets.yaml, bookmarks.yaml und docker.yaml unverändert gültig – neu ist nur die Anmeldung aus Schritt 7.
  • Das Backup ist winzig. Sichere den config-Ordner (und ggf. eigene icons) – das ist deine gesamte Konfiguration. Er gehört ins Restic-Backup; die Anwendung selbst wird jederzeit aus dem Image neu erzeugt. Die .env mit Secret und Passwort sicherst du getrennt davon, zum Beispiel im Passwortmanager – geht das Secret verloren, sind nur die offenen Sitzungen ungültig, du meldest dich einfach neu an.
  • Sicherheit nicht vergessen. Ein Dashboard mit Docker-Einblick ist ein lohnendes Ziel. Betreibe es nur hinter HTTPS (erledigt Traefik), lass die Anmeldung aus Schritt 7 aktiv und wechsle das Passwort, wenn du es je über einen unsicheren Kanal geteilt hast.

Zuletzt aktualisiert: 23.09.2026

Feedback per E-Mail: feedback@serverkueche.de

Das könnte dir auch schmecken