Homelab-Monitoring: von Ausfällen wissen, bevor die Familie sie bemerkt
Ein paar Dutzend Container, die täglich von der ganzen Familie genutzt werden, erzwingen irgendwann ein Monitoring. Diese Fallstudie zeigt, wie mein Stack funktioniert — Metriken, Logs, Alerting und lokale KI, die Lärm in nützliche Benachrichtigungen verwandelt.

Schwerpunkt
Observability
Niveau
Fortgeschritten
Stack
Ein Homelab geht leise kaputt
Nichts explodiert. Eines Abends startet einfach der Film nicht, die Einkaufsliste synchronisiert nicht mehr oder die Morgenerinnerung kommt nie an. Am Anfang war mein Monitoring-System die Familie: absolut zuverlässig, meldet aber ausschließlich nach dem Ausfall — und meistens im ungünstigsten Moment.
Mit einer Handvoll Containern lässt sich so leben. Bei ein paar Dutzend — mit Datenbanken, Automatisierungen und darunter — war „läuft wahrscheinlich” keine Antwort mehr. Wenn ich mein Zuhause wie ein kleines Produktivsystem behandle, dann ist ein Produktivsystem ohne Monitoring bloß Raterei, die um eine Katastrophe bittet.
Der Observability-Stack: sammelt Metriken, mit Promtail die Logs, Alertmanager entscheidet, wer wann benachrichtigt wird, ist das Fenster auf das Ganze, und mit einem lokalen KI-Modell verwandelt rohe Alerts in lesbare Nachrichten. Alles in Containern, alles lokal.
Drei Fragen, drei Werkzeuge
Die Arbeitsteilung ist simpel. Metriken sagen dir, dass etwas passiert: ein Container frisst Speicher, eine Platte läuft voll, die Antwortzeiten steigen. Logs sagen dir, warum. Alerts entscheiden, ob es jemand jetzt wissen muss oder ob der Morgen reicht.
Der Datenfluss ist einfacher, als die Menge an Namen vermuten lässt. Alle paar Sekunden fragt Prometheus die Exporter nach Metriken von Containern, Host und einzelnen Diensten ab; Promtail liest währenddessen die Logs aller Container und schickt sie an Loki. Die Alert-Regeln leben in der Prometheus-Konfiguration, und wenn eine feuert, wählt Alertmanager die Route — wer es erfahren soll, über welchen Kanal und ob diese Uhrzeit überhaupt angemessen ist. Das letzte Stück, vom rohen Alert zur Nachricht, die ein Mensch lesen will, gehört n8n.
Grafana ist in dieser Kette bewusst nichts weiter als ein Fenster. Ein Dashboard, auf das niemand schaut, ist kein Monitoring — es ist ein Bildschirmschoner. Die eigentliche Arbeit machen die Alert-Regeln, und die tun am meisten weh. Jede der folgenden Geschichten ist ein Fehlalarm, der mich erst geweckt und dann etwas gelehrt hat.
Lektion 1: Metriken lügen höflich
Die erste Version meines Speicher-Alerts nutzte container_memory_usage_bytes. Klingt nach genau dem, was man braucht — und demnach belegte mein Werbeblocker 433 MB, unangenehm nah am Limit. Der Haken: Diese Metrik zählt den Dateisystem-Cache mit, den der Kernel sofort wieder hergibt, sobald ihn jemand braucht. Der tatsächliche Verbrauch, gemessen über container_memory_working_set_bytes, lag bei 326 MB. Hundert Megabyte Unterschied — und ein Alert, der vor Speicher warnte, der jederzeit freigegeben werden konnte.
# Falsch: zählt FS-Cache mit, 30-100% zu hoch
container_memory_usage_bytes{name="adguard"}
# Richtig: der Speicher, den der Container wirklich braucht
container_memory_working_set_bytes{name="adguard"}
Lektion 2: der Alert, der nie erlischt
Counter in Prometheus steigen nur. Eine Regel wie „alarmiere, wenn der Restart-Zähler größer als null ist” sieht harmlos aus, hat aber eine amüsante Eigenschaft: Ein Container, der einmal neu gestartet ist, vor drei Wochen, erfüllt sie bis ans Ende der Zeit. Der Alert geht an und nie wieder aus.
# Falsch: für immer wahr nach dem ersten Neustart
container_restart_count > 0
# Richtig: gab es einen Neustart in den letzten 5 Minuten
increase(container_restart_count[5m]) > 0
Die Frage, die ein Alert beantworten soll, ist nicht „ist das je passiert”, sondern „passiert das gerade jetzt”. Der Unterschied zwischen diesen beiden Abfragen ist der Unterschied zwischen Monitoring und einer Chronik.
Lektion 3: das Monitoring, das sich selbst überwachte
Die schönste Schleife, die ich je aus Versehen gebaut habe. Eine Loki-Regel suchte in den Logs nach Wörtern, die auf getötete Prozesse hindeuten — unter anderem „oom” und „killed”. Nur: Loki loggt auch die eigenen Abfragen. Meine Abfrage nach „oom” landete in Lokis Logs, wo sie prompt von genau der Regel gefunden wurde, die sie abgeschickt hatte. Das Monitoring stellte erfolgreich fest, dass es monitort.
Bonus: Ein nacktes „oom” ohne Wortgrenzen passt auch auf „Room” und „Zoom”. Ein Container mit einem Zimmernamen im Log reicht für einen Alert über einen angeblich getöteten Prozess.
# Richtig: Wortgrenzen + Lokis eigene Logs ausschließen
{job="containerlogs", container_name!="loki"} |~ "(?i)\\boom\\b|\\bkilled\\b"
Ein Alert soll eine Nachricht sein, kein Stack-Dump
Ein roher Alertmanager-Alert liest sich wie eine Nachricht von einem Roboter an einen anderen: Labels, Werte, Bezeichner. Um sieben Uhr morgens, auf dem Handy, liest das niemand. Deshalb steht zwischen Alertmanager und Handy n8n mit einem kleinen lokalen Sprachmodell, das den Alert verständlich zusammenfasst: was passiert ist, welcher Container betroffen ist und wo man anfangen sollte.
Die Route ist kurz, aber jede Station hat ihre Aufgabe. Alertmanager schickt einen Webhook an n8n, das Labels und Beschreibungen unterschiedlicher Regeln in ein einheitliches Format bringt und ein lokales Modell in um eine Zusammenfassung bittet. Die Dringlichkeit des Alerts ist nicht die Meinung des Modells — sie kommt aus den Labels der Regel; die KI übersetzt, sie entscheidet nicht. Die fertige Nachricht erreicht den Empfänger über seinen Kanal: oder Telegram.
# Die Route eines Alerts:
# Prometheus → Alertmanager → Webhook → n8n
# → Labels und Beschreibungen in ein Format normalisieren
# → lokales Modell (Ollama): verständliche Zusammenfassung
# → Routing pro Nutzer: ntfy | Telegram
# → Ruhezeiten: Warteschlange → Zustellung am Morgen
Das Modell läuft auf der CPU des Servers — einen Alert zusammenzufassen ist keine Konversation, zehn bis einige Dutzend Sekunden reichen völlig. Im Gegenzug verlässt keine Beschreibung dessen, was in meinem Haus passiert, jemals das Haus. Es ist derselbe Kompromiss wie beim KI-Agenten in der Home App: Lokale KI ist langsamer als eine Cloud-API, aber Privatsphäre steht hier über ein paar Sekunden.
Darüber hinaus gilt normale Benachrichtigungshygiene: Kritische Alerts kommen immer durch, der Rest respektiert Ruhezeiten und wartet in der Warteschlange bis zum Morgen. Ein System, das Menschen wegen eines unkritischen Anstiegs der Festplattennutzung weckt, bittet darum, stummgeschaltet zu werden — und stummgeschaltetes Monitoring ist die teuerste Form von keinem Monitoring.

Wer bewacht den Wächter
Das schlimmste Szenario ist kein Dienstausfall. Es ist ein Monitoring-Ausfall — Stille, die wie Ruhe aussieht. Eine Weile lebte ich im Glauben, keine Alerts bedeuteten ein gesundes System, bis ich entdeckte, dass sie auch einen toten Benachrichtigungskanal bedeuten können.
Die Lösung ist so alt wie die Eisenbahn: ein Dead-Man's-Switch. Ein Kontrollsignal ist immer aktiv, weckt aber keinen Menschen alle paar Minuten — es bestätigt still, dass der gesamte Weg von Prometheus über n8n bis zum Handy funktioniert. Erst sein Ausbleiben ist der Alarm. Dazu prüft ein separater Watchdog, ob geplante Jobs tatsächlich gelaufen sind. Stille ist keine gute Nachricht mehr; die gute Nachricht ist ein regelmäßiger Puls.
Aus derselben Kategorie: Nach einem Server-Neustart kann der Container-Metrik-Exporter in einem Zustand hochkommen, in dem er nichts meldet. Alles sieht grün aus, weil es keine Daten gibt, die rot sein könnten. Von solchen Dingen erfährst du nur, wenn du auch das Monitoring monitorst.
Kompromisse
Dieser Stack ist nicht gratis. Es sind mehrere zusätzliche Container, ein spürbares Stück RAM und Regeln, die wie Code gepflegt werden wollen — meine leben in einem Git-Repository, mit Änderungshistorie und dem Grund für jede Anpassung in der Commit-Message. Ohne das erinnert sich nach einem halben Jahr niemand, warum ein Alert genau diesen Schwellenwert hat und ob der Weisheit war oder Panik.
Was sich geändert hat
Drei Dinge sind im Alltag sichtbar. Fehlalarme sind nach den beschriebenen Korrekturen fast verschwunden — und die Alerts, die ankommen, lesen sich wie eine Nachricht von einem Menschen, nicht wie ein Systemauszug. Von den meisten Ausfällen erfahre ich vom Handy, bevor zu Hause jemand etwas bemerkt: Ein Container, der nachts gestorben ist, ist am Morgen beschrieben — und meistens repariert —, bevor jemand zur Einkaufsliste greift. Und ein toter Benachrichtigungskanal, früher wochenlang unsichtbar, meldet sich heute selbst — durch das Ausbleiben seines Pulses.
Die Familie meldet weiterhin Fehler. Nur nicht mehr als Erste.
Was mich dieser Stack gelehrt hat
Dass das Schwerste am Monitoring nicht das Sammeln von Daten ist — sammeln ist leicht, Container erzählen bereitwillig alles über sich. Das Schwerste ist zu entscheiden, was davon um drei Uhr nachts jemandes Aufmerksamkeit verdient. Jeder meiner Fehlalarme war im Kern eine falsche Antwort auf diese Frage.
Und dass Monitoring selbst ein Dienst ist, der kaputtgeht. Seit der Dead-Man's-Switch Wache hält, traue ich der Stille — aber nur, weil die Stille alle paar Minuten mit Namen unterschreibt.
Häufige Fragen
Ist Monitoring für einen Heimserver nicht übertrieben?
Solange der Server nur dir dient und fünf Container laufen — vielleicht. Aber sobald die Familie davon abhängt, ist ein Ausfall kein Hobby mehr. Monitoring ist der Unterschied zwischen leise reparieren und sich hinterher rechtfertigen.
Gehen Monitoring-Daten in die Cloud?
Nein. Metriken, Logs und Alerts bleiben auf dem Server zu Hause. Selbst die Zusammenfassungen schreibt ein lokales Sprachmodell — keine Beschreibung dessen, was in meinem Haus passiert, erreicht je eine externe API.
Womit fange ich an, wenn ich noch nichts habe?
Mit Healthchecks in Docker Compose und einem einzelnen Kontrollsignal, das prüft, ob der Benachrichtigungsweg überhaupt funktioniert. Alerts kommen erst dazu, wenn du weißt, wie deine Dienste an einem normalen Tag aussehen — sonst verbringst du die erste Woche damit, Fehlalarme abzuschalten.