← Zurück zur Werkstatt

25. August 2026

Uptime-Monitor mit n8n: warum HTTP 200 nichts beweist

Mein Blog hat bis zu 34 Stunden lang auf rund 850 Unterseiten einen 404 ausgeliefert. Die Startseite antwortete die ganze Zeit normal, der Server war erreichbar, WordPress lief. Ein üblicher Uptime-Check hätte durchgehend grün gemeldet. Aus diesem Ausfall ist ein Workflow entstanden, der alle 15 Minuten sechs Pfade abruft und dabei nicht nur den Statuscode ansieht, sondern auch das, was tatsächlich zurückkommt.

  • n8n
  • Monitoring
  • WordPress
  • Apache
  • Telegram

Der Ausfall, den niemand bemerkt hat

Am 20. und 21. August 2026 lieferte hobbyblogging.de auf allen Unterseiten HTTP 404. Betroffen war praktisch der gesamte Bestand, rund 850 Seiten. Erreichbar blieb einzig die Startseite. Aufgefallen ist es niemandem — nicht mir, und auch kein Leser hat sich gemeldet.

Den Zeitraum konnte ich nachträglich einkreisen, weil bei mir ein anderer Workflow jede Nacht um Mitternacht die WordPress-REST-API abfragt. Der Lauf am 20. August um 00:02 Uhr war erfolgreich. Der Lauf am 21. August um 00:00 Uhr lief in einen 404. Gegen 09:45 Uhr desselben Tages war der Fehler behoben. Der Ausfall dauerte damit mindestens 10 und höchstens 34 Stunden.

Genauer wird es nicht. Und das ist im Rückblick der eigentliche Befund: Ohne Monitoring bleibt am Ende ein Zeitfenster von einem ganzen Tag, in dem man nur raten kann, wie lange die eigene Seite kaputt war. Für einen Blog, der auch über Suchmaschinen gefunden werden soll, ist das mehr als ein Schönheitsfehler — Googlebot bekam in dieser Zeit auf jede Unterseite dieselbe Antwort wie ein Besucher.

Die Ursache

Die 404-Antwort war 196 Byte groß, kam in charset=iso-8859-1 und enthielt den Satz „The requested URL was not found on this server.“ Das ist Apaches eigene Standard-Fehlerseite. Hätte WordPress geantwortet, wäre die 404-Seite meines Themes gekommen, rund 115 KB groß. Allein die Größe der Antwort sagt also schon, wer da geantwortet hat.

Die Gegenprobe bestätigte es: /wp-login.php und /index.php?rest_route=/wp/v2/posts lieferten beide HTTP 200. WordPress lief, die Datenbank lief, PHP lief. Die Anfragen kamen dort nur nicht mehr an.

Damit war die Diagnose eindeutig: mod_rewrite griff nicht. Anfragen an sprechende Permalinks erreichten WordPress gar nicht erst. Apache suchte im Dateisystem nach einer Datei namens home-assistant-dashboard, fand keine und antwortete selbst. Behoben war es durch einmaliges Speichern der Permalink-Einstellungen — dabei schreibt WordPress die .htaccess neu.

Warum ein klassischer Uptime-Check grün gemeldet hätte

Die Startseite ist der einzige Pfad, der ohne Rewrite-Regel funktioniert. Sie wird direkt auf die index.php im DocumentRoot abgebildet, dafür braucht es keine .htaccess. Jeder andere Pfad läuft über die Rewrite-Kette.

Ein Monitor, der nur die Startseite anfragt, prüft also ausgerechnet den einen Pfad, der von genau diesem Fehler nicht betroffen sein kann. Er hätte während des gesamten Ausfalls HTTP 200 gemeldet, in korrekter Größe, mit korrektem Inhalt. Das ist keine Ausnahme, sondern die Standardkonfiguration der meisten Uptime-Dienste.

Prüfe immer einen Pfad, der die Rewrite-Kette durchläuft.

Das ist die Lehre, aus der der Workflow entstanden ist. Die zweite steckt gleich daneben: Ein Statuscode allein beweist nichts. Eine leere Antwort, eine WordPress-Fehlerseite oder ein abgeschnittenes HTML kommen alle mit HTTP 200 zurück. Deshalb prüft hier jeder Check zwei Dinge — den Code und den Inhalt.

Der Workflow im Überblick

Aufbau des Monitor-Workflows Ein Zeitplan startet alle 15 Minuten sechs Checks gegen den Blog. Das Ergebnis wird mit dem gespeicherten Zustand verglichen; nur bei einem Wechsel oder beim Tagescheck geht eine Telegram-Nachricht raus, sonst endet der Lauf still. Die vollständige Beschreibung steht in den Abschnitten unter der Grafik. Zeitplan alle 15 Minuten Sechs Checks Statuscode und Inhalt Zustand vergleichen ok gegen down Meldung nötig? Wechsel oder Tagescheck ja Telegram Alarm, Entwarnung, Lebenszeichen Test-Webhook vorhanden, abgeschaltet hobbyblogging.de sechs Pfade, je ein GET Zustandsspeicher state, failStreak, downSince Lauf endet still keine Nachricht nein
Ein Lauf alle 15 Minuten. In den allermeisten Fällen endet er nach dem vierten Schritt, ohne dass etwas passiert.

Der Workflow besteht im Kern aus zwei Code-Nodes. Der erste führt die sechs Abrufe aus und liefert ein Ergebnisobjekt zurück: ob insgesamt alles in Ordnung ist, welche Checks fehlgeschlagen sind und mit welcher Begründung. Der zweite vergleicht dieses Ergebnis mit dem Zustand des letzten Laufs und entscheidet, ob eine Nachricht rausgeht.

Dass der zweite Node bei „nichts Neues“ null Items zurückgibt, ist Absicht: Eine leere Ausgabe beendet den Zweig, der Telegram-Node wird gar nicht erst erreicht. Das ist in n8n der sauberste Weg, eine Kette still enden zu lassen — kein IF-Node, kein toter Pfad, keine Fehlermeldung.

Der Zustand selbst liegt in den statischen Workflow-Daten, die n8n zwischen Ausführungen aufbewahrt. Dort stehen fünf Werte: der aktuelle Zustand, die Zahl der Fehlschläge in Folge, der Zeitpunkt des Ausfallbeginns, der Zeitpunkt der letzten Meldung und der Zeitpunkt des letzten erfolgreichen Laufs. Mehr braucht es nicht, und vor allem braucht es dafür keine Datenbank.

Die sechs Checks

PfadBestanden, wennPrüft
/HTTP 200 und HTML größer als 40 KBServer und PHP antworten
/mit-home-assistant-startenHTTP 200, größer als 20 KB, <title> enthält „home assistant“Rewrite-Kette und Theme
/home-assistant-dashboardHTTP 200, größer als 20 KB, <title> enthält „dashboard“zweiter Beitrag, anderer Titel
/category/smarthomeHTTP 200 und größer als 20 KBArchivseiten
/sitemap.xmlHTTP 200 und <urlset> oder <sitemapindex> im BodySitemap-Generierung
/wp-json/wp/v2/posts?per_page=1HTTP 200 und gültiges JSON-Array mit echtem PermalinkWordPress-Kern und Datenbank

Die Auswahl ist nicht zufällig. Sie deckt vier Ebenen ab, die unabhängig voneinander ausfallen können: die Infrastruktur, die Rewrite-Kette samt Theme, die Sitemap und die Datenbank. Der Titelvergleich bei den beiden Beiträgen erkennt zusätzlich den Fall, dass zwar eine Seite ausgeliefert wird, aber die falsche — bei einem Cache-Problem oder einer verrutschten Weiterleitung wäre das sonst unsichtbar.

Genau der Pfad, der den Ausfall verursacht hat, ist heute Check Nummer drei. Hätte es ihn im August gegeben, wäre die Sache nach spätestens einer halben Stunde auf meinem Handy gewesen statt nach einem Tag durch Zufall.

Wann sich der Monitor meldet

Zustandswechsel und die daraus folgenden Nachrichten Aus dem Zustand ok wird nach zwei Fehlschlägen in Folge der Zustand down; sind alle Checks wieder in Ordnung, geht es zurück. Im Zustand ok kommt alle 24 Stunden ein Lebenszeichen, beim Wechsel zurück eine Entwarnung mit Ausfalldauer, beim Wechsel nach down ein einmaliger Alarm. Zustand: ok alle sechs Checks bestanden Zustand: down mindestens ein Check fehlt zwei Fehlschläge in Folge alle Checks wieder ok Lebenszeichen alle 24 Stunden Entwarnung mit Ausfalldauer Alarm einmal, beim Wechsel
Nachrichten hängen am Zustandswechsel, nicht am Prüfergebnis. Solange sich nichts ändert, bleibt es still.

Die Regel „nur bei Wechsel“ ist die wichtigste von allen. Ohne sie kämen bei einem Ausfall 96 Nachrichten pro Tag an, und nach dem dritten Vorfall würde ich den Kanal stummschalten — womit der Monitor seinen Zweck verloren hätte. Alarmmüdigkeit ist kein theoretisches Problem, sie ist der übliche Grund, warum Monitoring irgendwann nicht mehr wirkt.

Dass zwei Fehlschläge nötig sind, kostet Erkennungszeit und ist es wert. Ein einzelner Aussetzer im Netz, ein Neustart des Webservers, ein kurzer Timeout — das sind alles Dinge, die in 15 Minuten vorbei sind und über die ich nichts erfahren muss. Bei zwei Läufen in Folge dauert die Erkennung längstens 30 Minuten. Gegenüber den 34 Stunden von damals ist das die Größenordnung, auf die es ankommt.

Die Entwarnung enthält die Ausfalldauer, berechnet aus dem gespeicherten Ausfallbeginn. Damit steht die Information, die mir im August gefehlt hat, künftig direkt in der Nachricht — ohne dass ich Ausführungslisten durchsehen muss.

Das tägliche Lebenszeichen ist der Gegenpol dazu: Ein Monitor, der nur bei Problemen schreibt, ist von einem Monitor, der gar nicht mehr läuft, nicht zu unterscheiden. Eine Nachricht alle 24 Stunden löst das mit dem geringstmöglichen Aufwand.

Zwei Einstellungen, die ich korrigiert habe

Zum Testen hatte der Workflow neben dem Zeitplan einen Webhook, über den sich ein Durchlauf sofort auslösen ließ. Nach dem Ende-zu-Ende-Test habe ich ihn abgeschaltet, aber im Workflow gelassen. Ein offener, nicht authentifizierter Endpunkt, der auf Zuruf sechs Anfragen gegen die eigene Seite auslöst, muss nicht dauerhaft erreichbar sein — als Werkzeug für den nächsten Umbau ist er dagegen praktisch.

Die zweite Korrektur war ein handfester Denkfehler. Anfangs habe ich erfolgreiche Ausführungen nicht speichern lassen, um die Liste sauber zu halten. Das Ergebnis: Der Monitor sah in n8n aus, als liefe er überhaupt nicht. Für einen Workflow, dessen einziger Zweck Sicherheit ist, war das genau falsch herum gedacht — Sichtbarkeit schlägt Ordnung. Seitdem werden erfolgreiche wie fehlerhafte Läufe gespeichert.

Der Rest ist unspektakulär: Zeitzone Europe/Berlin, damit die Zeitangaben in den Nachrichten stimmen, ein Ausführungstimeout von 300 Sekunden, und ein zentraler Error-Handler, der greift, wenn der Lauf selbst abbricht statt nur einen Fehler zu finden.

Was der Monitor nicht kann

Der Wächter ist nicht bewacht

Der Monitor läuft auf derselben n8n-Instanz, die er mit absichern soll. Steht n8n — Container tot, Update misslungen, Server aus —, prüft niemand und alarmiert niemand. Das tägliche Lebenszeichen fängt das nur passiv ab: Man muss bemerken, dass eine Nachricht ausgeblieben ist, und das ist deutlich schwerer, als eine Nachricht zu lesen, die ankommt.

Die saubere Lösung wäre ein externer Dead-Man's-Switch: Der Workflow pingt nach jedem erfolgreichen Lauf eine Adresse bei einem fremden Dienst, und bleibt dieser Ping aus, schlägt der fremde Dienst Alarm. Umgesetzt ist das noch nicht, es steht als nächster Schritt an.

Ein einziger Alarmkanal

Fällt der Telegram-Bot oder die Telegram-API aus, kommt kein Alarm an. Der Error-Handler greift zwar, meldet aber an einen Dienst im lokalen Netz — was bei einem Ausfall des Heimnetzes ebenfalls nichts nützt.

Kein Zertifikats-Check

Die Restlaufzeit des SSL-Zertifikats wird nicht geprüft. Dafür bräuchte es Zugriff auf das tls-Modul, das in n8n-Code-Nodes standardmäßig gesperrt ist. Ein abgelaufenes Zertifikat würde der Monitor erst bemerken, wenn die Abrufe daran scheitern — also erst, wenn es zu spät ist.

Feste Pfadliste

Die sechs Pfade stehen im Code. Wird einer dieser Beiträge umbenannt oder gelöscht, schlägt der Monitor Alarm, obwohl die Seite in Ordnung ist. Bei sechs Pfaden ist das überschaubar, aber es ist eine Stelle, an die man denken muss.

Mein Fazit

Der Workflow ist klein: ein Zeitplan, zwei Code-Nodes, ein Telegram-Node. Der Aufwand steckte nicht im Bauen, sondern in der Frage, was überhaupt geprüft werden muss, damit ein „grün“ etwas bedeutet. Diese Frage hat mir der Ausfall beantwortet, und zwar deutlicher, als es jede Checkliste gekonnt hätte.

Was ich mitnehme, gilt über diesen einen Blog hinaus: Ein Monitor prüft nicht, ob der Server läuft, sondern ob das Produkt funktioniert. Der Unterschied klingt akademisch, bis man einmal 34 Stunden lang eine Seite betreibt, die für jeden Besucher und für Googlebot kaputt war und für den Uptime-Check tadellos.