Zum Inhalt
Bytearium

Keine Werbung und keine Partnerlinks aktiv

Homelab & Storage

Homelab überwachen mit Prometheus und Grafana

Homelab überwachen mit Prometheus und Grafana: Compose-Stack mit geprüften Image-Tags, Speichergrenze, Mail-Alarm und der Unterschied zu Uptime Kuma.

Uptime Kuma weckt dich um drei Uhr nachts, weil der Server ausgefallen ist. Dass die Platte seit Wochen jede Woche ein bisschen schneller vollläuft, sagt es dir nicht. Ein Diagramm schon, und zwar an einem Dienstagnachmittag statt um drei Uhr nachts.

Kurz gesagt

Wie funktioniert Homelab-Monitoring mit Prometheus und Grafana? Du startest vier Container mit Docker Compose. Prometheus holt in festen Abständen Zahlen von deinen Rechnern und speichert sie. node_exporter macht CPU, Arbeitsspeicher, Platten und Netzwerk eines Linux-Hosts für Prometheus lesbar. Grafana zeichnet den Verlauf, und Alertmanager schickt eine Nachricht, wenn eine Regel auslöst [1][4][11][12][16]. Prometheus zieht die Daten selbst: Es fragt jedes Ziel nach den aktuellen Werten, standardmäßig einmal pro Minute [4]. Dieser Guide legt Image-Tags fest, die es nachweislich gibt (geprüft am 25. Okt. 2026), hält jeden Dienst auf der Loopback-Adresse, begrenzt den Plattenplatz für den Verlauf und liefert zwei Alarmregeln: Ein Dienst antwortet nicht mehr, und eine Platte ist in 24 Stunden voll. Unsere Einschätzung: Prometheus beantwortet „Wie entwickelt sich das?“, Uptime Kuma beantwortet „Ist es erreichbar?“. Nimm beides, denn beides fällt auf andere Weise aus.

So funktioniert’s

Vier Rollen. Ein Exporter ist ein kleines Programm, das die Messwerte eines Systems unter einer Webadresse zeigt, meist /metrics. node_exporter macht das für Linux-Hosts und lauscht standardmäßig auf Port 9100 [12]. Prometheus „scrapt“ (holt) alle eingetragenen Ziele, legt die Messwerte in einer Zeitreihen-Datenbank auf der lokalen Platte ab und speichert für jeden Abruf eine Reihe up mit 1 oder 0 [4][9]. Grafana speichert selbst keine Messwerte. Es fragt Prometheus über eine Datenquelle ab und zeichnet das Ergebnis [28][29]. Alertmanager verschickt die Benachrichtigungen. Laut Prometheus-Doku stellen Alarmregeln nur fest, was gerade kaputt ist, und für Zusammenfassen, Begrenzen und Stummschalten braucht es eine weitere Schicht. Im Prometheus-Umfeld ist das der Alertmanager [6].

Festgelegte Versionen. Prometheus 3.15.1 (veröffentlicht am 21. Okt. 2026) [18], node_exporter 1.12.1 (14. Juli 2026) [19], Alertmanager 0.34.1 (17. Sept. 2026) [20] und Grafana 13.2.4 (13. Okt. 2026) [21]. Jeder Tag existiert laut Docker Hub am 25. Okt. 2026 [22][23][24][25]. Wir nehmen nicht latest, damit ein Update eine Entscheidung von dir ist und nicht beim nächsten pull passiert.

Wo der Stack läuft. Die Docker-Images sind außer für x86-64 auch für 64-Bit-ARM und 32-Bit-ARM (v7) gelistet [22][23][24][25]. Darüber hinaus hängt die Wahl von deiner Lage ab:

OptionPasst, wennDarauf achten
Mini-PC oder alter PC mit LinuxEr läuft ohnehin rund um die UhrMiss zuerst seinen Stromverbrauch; siehe die Stromguides unten
Raspberry PiDu willst die kleinste, leiseste KistePrometheus schreibt dauernd auf die Platte: ein Write-ahead-Log und alle zwei Stunden einen neuen Block [1]. Unsere Einschätzung: nimm eine SSD statt einer SD-Karte. Verschleißzahlen haben wir nicht, dieser Teil ist unbelegt
Auf dem überwachten Host selbstDu willst am schnellsten startenFällt der Host aus, fällt das Monitoring mit aus und schweigt
VPSDu willst einen Blick von außenPrometheus zieht die Daten, deine Exporter zu Hause müssten also aus dem Internet erreichbar sein. Das Projekt sagt, seine Endpunkte sollen nicht in öffentlichen Netzen stehen [10]

Unsere Einschätzung: Setz den Stack auf einen kleinen Dauerläufer zu Hause und die Sicht von außen (Uptime Kuma) auf ein anderes Gerät oder einen VPS. Willst du Prometheus doch auf einem VPS, verbinde ihn per VPN mit deinem Heimnetz, statt Exporter-Ports zu öffnen; siehe den Guide zu WireGuard und Tailscale unten.

Warum das Uptime Kuma nicht wiederholt. Uptime Kuma fragt von außen, ob etwas antwortet. Prometheus liest Zahlen von innen und behält sie:

Uptime KumaPrometheus mit node_exporter
Typische FrageIst Seite, Port oder Host erreichbar?Wie voll ist die Platte, und wie schnell füllt sie sich?
DatenquellePrüfungen, die es selbst ausführtExporter auf den Systemen
Was bleibtVerlauf von Up und Down, AntwortzeitenJede Zahl, die die Exporter liefern, so lange du es erlaubst
Typischer Alarm„Seit 2 Minuten nicht erreichbar“„In 24 Stunden voll“

Beide lassen sich verbinden: Uptime Kuma gibt seine Monitore unter /metrics als Prometheus-Metriken aus, standardmäßig mit Basic Authentication. Prometheus kann sie abholen, und Grafana zeigt die Verfügbarkeit neben der Last [36].

Den Verlauf begrenzen. Ohne Vorgabe gilt eine Aufbewahrung von 15 Tagen [1][3]. Setze Zeit und Größe. Beide gelten, und die Grenze, die zuerst greift, gewinnt [1]. Seit der Änderung in Prometheus von 2025 sind die beiden Kommandozeilen-Flags als veraltet markiert, und dieselben Einstellungen stehen in prometheus.yml unter storage.tsdb.retention; sie haben Vorrang vor den Flags [3][5]. Viele Anleitungen nutzen noch die Flags [37]. Die Größengrenze sollte höchstens 80 bis 85 Prozent des zugewiesenen Plattenplatzes betragen, weil die Verdichtung alte und neue Blöcke gleichzeitig ablegen muss [1].

Türen schließen. Prometheus lauscht standardmäßig auf 0.0.0.0:9090 [3]. Sein Sicherheitsmodell geht davon aus, dass nicht vertrauenswürdige Nutzer alles lesen können, was es ausliefert, und sagt, die Endpunkte gehören nicht in öffentliche Netze [10]. Docker legt eine Falle dazu: Ports, die du mit -p veröffentlichst, werden umgeleitet, bevor ufw sie sieht [34], und ein schlichtes -p 9090:9090 ist für alles offen, was den Host erreicht [33]. Wir umgehen beides, indem die Container im Host-Netzwerk laufen und jeder Dienst an 127.0.0.1 gebunden ist (nur Linux; Docker Desktop haben wir nicht getestet). Das README von node_exporter verlangt für die Host-Überwachung selbst Host-Netzwerk und Host-PID [12], und Docker legt für das Host-Netzwerk keine Firewall-Regeln an, sodass deine eigene Firewall weiter gilt [34].

Einrichten

Alles liegt in einem Ordner. Lege ihn und die folgenden Dateien an:

monitoring/
├── compose.yaml
├── .env                 # GRAFANA_ADMIN_PASSWORD=ein-langes-passwort  (nie einchecken)
├── prometheus/
│   ├── prometheus.yml
│   └── rules.yml
├── alertmanager/
│   ├── alertmanager.yml
│   └── smtp_password    # dein Mail-Passwort, sonst nichts in der Datei
└── grafana/provisioning/datasources/prometheus.yml

compose.yaml. Gibst du dem Prometheus- oder Alertmanager-Image ein command:, ersetzt du die Voreinstellungen des Images, deshalb stehen Konfigurations- und Speicher-Flag noch einmal drin [2][17]:

name: monitoring

services:
  prometheus:
    image: prom/prometheus:v3.15.1
    restart: unless-stopped
    network_mode: host
    command:
      - --config.file=/etc/prometheus/prometheus.yml
      - --storage.tsdb.path=/prometheus
      - --web.listen-address=127.0.0.1:9090
    volumes:
      - ./prometheus/prometheus.yml:/etc/prometheus/prometheus.yml:ro
      - ./prometheus/rules.yml:/etc/prometheus/rules.yml:ro
      - prometheus-data:/prometheus

  node-exporter:
    image: prom/node-exporter:v1.12.1
    restart: unless-stopped
    network_mode: host
    pid: host
    command:
      - --path.rootfs=/host
      - --web.listen-address=127.0.0.1:9100
    volumes:
      - /:/host:ro,rslave

  alertmanager:
    image: prom/alertmanager:v0.34.1
    restart: unless-stopped
    network_mode: host
    command:
      - --config.file=/etc/alertmanager/alertmanager.yml
      - --storage.path=/alertmanager
      - --web.listen-address=127.0.0.1:9093
      - --cluster.listen-address=
    volumes:
      - ./alertmanager/alertmanager.yml:/etc/alertmanager/alertmanager.yml:ro
      - ./alertmanager/smtp_password:/etc/alertmanager/smtp_password:ro
      - alertmanager-data:/alertmanager

  grafana:
    image: grafana/grafana:13.2.4
    restart: unless-stopped
    network_mode: host
    environment:
      GF_SERVER_HTTP_ADDR: 127.0.0.1
      GF_SECURITY_ADMIN_PASSWORD: ${GRAFANA_ADMIN_PASSWORD:?set GRAFANA_ADMIN_PASSWORD in .env}
    volumes:
      - ./grafana/provisioning/datasources:/etc/grafana/provisioning/datasources:ro
      - grafana-data:/var/lib/grafana

volumes:
  prometheus-data:
  alertmanager-data:
  grafana-data:

Warum diese Zeilen zählen:

  • --path.rootfs=/host zusammen mit dem Bind-Mount /:/host:ro,rslave ist das Rezept aus dem node_exporter-README. Ohne beides misst der Exporter nur seinen eigenen Container [12]. Das Präfix wird aus dem Label mountpoint entfernt, deine Systemplatte erscheint also als / [13].
  • --cluster.listen-address= (leer) schaltet das Clustering des Alertmanagers ab. Es ist standardmäßig an und lauscht auf 0.0.0.0:9094 [16]. Im Host-Netzwerk würde das einen Port für dein ganzes LAN öffnen.
  • --web.listen-address ist das Flag für die Bind-Adresse bei Prometheus und Alertmanager [3][38]. node_exporter teilt es über das Exporter-Toolkit von Prometheus, das auch --web.config.file für TLS und Passwörter bietet, falls du später über das LAN scrapen musst [14]. Prüfe es bei dir mit docker run --rm prom/node-exporter:v1.12.1 --help.
  • GF_SERVER_HTTP_ADDR ist die Umgebungsvariablen-Form von http_addr im Abschnitt [server] [27]. Das Admin-Passwort wird nur beim ersten Start gelesen [27], und :? lässt Compose abbrechen, wenn .env es nicht enthält [35]. Docker Secrets über GF_SECURITY_ADMIN_PASSWORD__FILE sind die Alternative [26].
  • Die Datei smtp_password und die Konfigurationen liest der Container-Nutzer nobody [17], sie müssen für ihn lesbar sein.

prometheus.yml. Der Standard-Abstand beim Scrapen ist eine Minute [4]. Wir nehmen 15 Sekunden, das passt für eine Handvoll Hosts:

global:
  scrape_interval: 15s
  evaluation_interval: 1m

storage:
  tsdb:
    retention:
      time: 30d
      size: 4GB

rule_files:
  - /etc/prometheus/rules.yml

alerting:
  alertmanagers:
    - static_configs:
        - targets: ["127.0.0.1:9093"]

scrape_configs:
  - job_name: prometheus
    static_configs:
      - targets: ["127.0.0.1:9090"]

  - job_name: node
    static_configs:
      - targets: ["127.0.0.1:9100"]

Lass den Job node so heißen: Das Dashboard „Node Exporter Full“ erwartet genau diesen Namen [32]. Für weitere Rechner installierst du node_exporter dort und trägst deren adresse:9100 bei den node-Zielen ein. Binde den Exporter dann an die LAN-Adresse dieses Rechners und lass nur den Monitoring-Host heran. Mach ihn nicht breiter zugänglich [10].

rules.yml. Zwei Alarme reichen für den Anfang. Der erste stammt direkt aus der Prometheus-Dokumentation, der zweite schaut nach vorn [6][8]:

groups:
  - name: homelab
    rules:
      - alert: InstanceDown
        expr: up == 0
        for: 5m
        labels:
          severity: critical
        annotations:
          summary: "{{ $labels.job }} on {{ $labels.instance }} has not answered for 5 minutes"

      - alert: DiskFullWithin24h
        expr: predict_linear(node_filesystem_avail_bytes{job="node", fstype!~"tmpfs|overlay|squashfs"}[6h], 24 * 3600) < 0
        for: 30m
        labels:
          severity: warning
        annotations:
          summary: "{{ $labels.mountpoint }} on {{ $labels.instance }} will be full within 24 hours at the current rate"

for lässt Prometheus warten, bevor ein Alarm als ausgelöst gilt, damit ein einzelner verpasster Abruf dich nicht weckt [6]. predict_linear legt eine Gerade durch die letzten sechs Stunden und liest sie 24 Stunden später ab. Es funktioniert nur bei Gauges und braucht mindestens zwei Messwerte [8]. Unsere Einschätzung: Ein großer einmaliger Schreibvorgang, etwa ein Backup, das auf der Platte landet, kann die Gerade verbiegen. Die 30 Minuten bei for sind ein Kompromiss, den du anpassen darfst.

alertmanager.yml. Die Werte unten sind Platzhalter. Ersetze Host, Adressen und Benutzer durch die deines Mail-Anbieters. Alertmanager kann das SMTP-Passwort aus einer Datei lesen und verlangt TLS zum Server, solange du das nicht änderst [15]:

global:
  smtp_smarthost: "smtp.example.org:587"
  smtp_from: "alerts@example.org"
  smtp_auth_username: "alerts@example.org"
  smtp_auth_password_file: /etc/alertmanager/smtp_password

route:
  receiver: mail
  group_by: ["alertname", "instance"]

receivers:
  - name: mail
    email_configs:
      - to: "you@example.org"
        send_resolved: true

Wähle einen Kanal, der nicht vom Homelab selbst abhängt. Ein Postfach bei einem externen Anbieter erfüllt das. Ein Mailserver auf der Maschine, die gerade abgestürzt ist, nicht.

Grafana-Datenquelle. Grafana liest Provisioning-Dateien beim Start [28]. Lege Folgendes in grafana/provisioning/datasources/prometheus.yml. Eine so angelegte Datenquelle lässt sich danach nicht mehr in der Weboberfläche bearbeiten [29]:

apiVersion: 1

datasources:
  - name: Prometheus
    type: prometheus
    access: proxy
    url: http://127.0.0.1:9090
    isDefault: true
    editable: false

Starten und prüfen. Führe im Ordner docker compose up -d aus. Danach:

  • ss -tlnp sollte die Ports 9090, 9100, 9093 und 3000 nur auf 127.0.0.1 zeigen.
  • curl -s http://127.0.0.1:9090/-/healthy liefert den Health-Check von Prometheus [39]. Der von Grafana ist GET /api/health [30].
  • Öffne Prometheus unter http://127.0.0.1:9090, führe up aus und erwarte zwei Reihen mit dem Wert 1.
  • Prüfe eine geänderte Regel oder Konfiguration mit docker compose exec prometheus promtool check rules /etc/prometheus/rules.yml und promtool check config /etc/prometheus/prometheus.yml [7]. Lade sie dann mit docker compose kill -s SIGHUP prometheus neu. Ein Neuladen per HTTP geht auch, aber nur mit --web.enable-lifecycle; das ist standardmäßig aus, und wir lassen es aus [3][10].

Von einem anderen Rechner kommst du per SSH-Tunnel heran: ssh -L 3000:127.0.0.1:3000 benutzer@monitoring-host, dann öffnest du http://127.0.0.1:3000. Willst du Grafana direkt im LAN erreichen, setze GF_SERVER_HTTP_ADDR auf die LAN-Adresse des Hosts statt auf 0.0.0.0 und leite keinen Port am Router weiter. Für eine ordentliche Adresse mit HTTPS stell einen Reverse Proxy davor; siehe den Guide unten.

Grafana-Dashboard. Melde dich als admin mit dem Passwort aus .env an. Ohne diesen Schritt gilt admin/admin [27], überspring ihn also nicht. Das schnellste Dashboard ist das der Community: Dashboards, New, Import, ID 1860 („Node Exporter Full“), Datenquelle wählen [31][32]. Die Seite empfiehlt für einige Panels die zusätzlichen Optionen --collector.systemd und --collector.processes bei node_exporter [32]. Wir haben sie nicht eingeschaltet, deshalb können einzelne Panels leer bleiben. Für dein eigenes erstes Dashboard genügen diese Abfragen:

PanelAbfrageQuelle
CPU im System-Modusrate(node_cpu_seconds_total{mode="system"}[1m])Prometheus-Guide zu node_exporter [11]
Freier Plattenplatznode_filesystem_avail_bytes[11]
Netzwerk empfangenrate(node_network_receive_bytes_total[1m])[11]
Arbeitsspeicher verfügbarnode_memory_MemAvailable_bytes / node_memory_MemTotal_bytesMetrikname aus einer Anleitung [37], prüfe ihn in deinem eigenen Prometheus

Praxisbeispiel

Wie groß wird der Verlauf? Die Prometheus-Doku nennt eine grobe Formel: Plattenbedarf = Aufbewahrung in Sekunden × Messwerte pro Sekunde × Bytes pro Messwert, im Schnitt 1 bis 2 Bytes pro Messwert [1]. Deine eigene Zahl liefert scrape_samples_scraped{job="node"}; sie zeigt, wie viele Messwerte ein Abruf zurückgab [9]. Hier ein Rechenbeispiel mit einem erfundenen Wert von 1.500 Messwerten pro Abruf:

15 s Abstand          →  1.500 / 15 = 100 Messwerte pro Sekunde
30 Tage               →  30 × 86.400 s = 2.592.000 s
Messwerte in 30 Tagen →  100 × 2.592.000 = 259.200.000
bei 1 Byte  pro Wert  →  etwa 0,26 GB
bei 2 Bytes pro Wert  →  etwa 0,52 GB

Die 1.500 sind für die Methode ausgedacht; miss deine eigene Zahl. Wir weisen dem Prometheus-Volume 5 GB zu und setzen size: 4GB. Das sind 80 Prozent und folgt dem Rat von 80 bis 85 Prozent [1]. Die Größengrenze zählt das Write-ahead-Log mit, gelöscht werden zu ihrer Einhaltung aber nur gespeicherte Blöcke [1]. Zum Testen des Alarms stoppst du den Exporter mit docker compose stop node-exporter. Nach fünf Minuten plus einem Auswertungsintervall sollte InstanceDown auslösen, und eine Mail sollte ankommen. Starte ihn danach wieder und warte auf die „resolved“-Mail.

Prüfliste

  • Prüfe vor dem Kopieren, ob jeder Image-Tag auf Docker Hub existiert, und notiere das Datum.
  • Setze GRAFANA_ADMIN_PASSWORD in .env vor dem ersten Start, und halte .env aus git heraus.
  • Binde jeden Dienst an 127.0.0.1, und bestätige es mit ss -tlnp.
  • Schalte das Alertmanager-Clustering ab, wenn du ihn im Host-Netzwerk betreibst.
  • Setze Aufbewahrungszeit und -größe in prometheus.yml, und halte die Größe unter 85 Prozent des zugewiesenen Platzes.
  • Miss scrape_samples_scraped, bevor du einer Größenschätzung traust.
  • Führe vor jedem Neuladen promtool check config und promtool check rules aus.
  • Löse einen Alarm absichtlich aus, und bestätige, dass die Mail außerhalb deines Homelabs ankommt.
  • Überwache Grafana und den Host mit Uptime Kuma von einem zweiten Gerät aus, damit der Wächter selbst bewacht wird.
  • Entscheide, ob der Messwert-Verlauf ein Backup verdient. Die Prometheus-Doku empfiehlt Snapshots, und die brauchen die Admin-API [1][10]. Wir lassen sie aus und sichern stattdessen den Compose-Ordner und das Grafana-Volume.

Passt dazu: Uptime Kuma: merken, wenn das Homelab ausfällt; Prometheus-Exporter; Container und OCI; Homelab-Stromverbrauch richtig messen; Homeserver oder VPS: die Stromrechnung; Reverse Proxy im Homelab; WireGuard oder Tailscale fürs Homelab; Raspberry Pi 5: SD, USB-SSD oder NVMe?; Homelab-Backup mit restic oder Borg.

Primärquellen

Diese Quellen sind die Grundlage der Seite. Das heißt nicht, dass jede Aussage einzeln nachgeprüft wurde; ob ein Prüfbeleg vorliegt, steht oben unter „Stand“. Einordnung und Prüfliste sind unsere eigene Arbeit.

Für diese Fassung liegt noch kein dokumentierter Prüfbeleg vor. Der Text stützt sich auf die genannten Quellen.

Entstehung: Bytearium erstellt diese Seiten mit Unterstützung von KI und verantwortet die Veröffentlichung. KI kann sich irren, deshalb nennen wir Quellen und Prüfstand offen.

  1. Prometheus projectStorage
  2. Prometheus projectInstallation
  3. Prometheus projectprometheus command-line flags
  4. Prometheus projectConfiguration
  5. Prometheus projecttsdb: Deprecate retention flags; add tsdb.retention runtime configuration
  6. Prometheus projectAlerting rules
  7. Prometheus projectDefining recording rules
  8. Prometheus projectQuery functions
  9. Prometheus projectJobs and instances
  10. Prometheus projectSecurity model
  11. Prometheus projectMonitoring Linux host metrics with the Node Exporter
  12. Prometheus projectnode_exporter
  13. Prometheus projectstrip rootfs prefix for run in docker
  14. Prometheus projectWeb configuration
  15. Prometheus projectAlertmanager configuration
  16. Prometheus projectAlertmanager README
  17. Prometheus projectAlertmanager Dockerfile
  18. Prometheus projectReleases · prometheus/prometheus
  19. Prometheus projectReleases · prometheus/node_exporter
  20. Prometheus projectReleases · prometheus/alertmanager
  21. Grafana LabsReleases · grafana/grafana
  22. Docker Hubprom/prometheus tag v3.15.1
  23. Docker Hubprom/node-exporter tag v1.12.1
  24. Docker Hubprom/alertmanager tag v0.34.1
  25. Docker Hubgrafana/grafana tag 13.2.4
  26. Grafana LabsConfigure a Grafana Docker image
  27. Grafana LabsConfigure Grafana
  28. Grafana LabsProvision Grafana
  29. Grafana LabsConfigure the Prometheus data source
  30. Grafana LabsOther HTTP API
  31. Grafana LabsMonitoring a Linux host with Prometheus, Node Exporter, and Docker Compose
  32. Grafana LabsNode Exporter Full
  33. Docker Inc.Port publishing and mapping
  34. Docker Inc.Packet filtering and firewalls
  35. Docker Inc.Interpolation in Compose files
  36. Uptime Kuma projectPrometheus Integration
  37. RootwerkstattGrafana + Prometheus: Homelab-Monitoring, das funktioniert
  38. NSRCSecure your Prometheus install
  39. Prometheus projectManagement API

Auf dieser Seite gibt es keine Werbung und keine Partnerlinks.