Die Konfiguration, die sich selbst ausrollt
Ein Dienst im Rechenzentrum in der Wohnung wird nicht von der CI ausgerollt. Die Smart-Home-Zentrale holt sich den geprüften Branch selbst, mergt ihn, fährt Home Assistants eigene Konfigurationsprüfung gegen den gemergten Baum und setzt auf den letzten funktionierenden Commit zurück, wenn die Prüfung fehlschlägt — oder wenn sie gar nicht erst laufen kann. Im Gegenzug darf die laufende Maschine ihre Änderungen aus der Oberfläche ungeprüft direkt auf diesen geschützten Branch committen. Diese Notiz handelt von diesem Tausch und den Kontrollen, die ihn überlebbar machen: ein Branch, den niemand umschreiben kann, ein Tor, das im Zweifel schließt, und ein Commit-Pfad, der eine geheimnisförmige Datei ablehnt, bevor der Commit existiert. Den letzten gibt es, weil Ignorieren allein nicht genügte. Und sie ist ehrlich darin, was die Pipeline nicht beweisen kann: Keine Automation ist getestet, keine Firmware wird kompiliert, und vieles an der laufenden Instanz liegt in einem Speicher, den Git nie sieht. Stand 2026-09-08.
Alles andere in dieser Flotte ändert sich auf dieselbe Weise: Ein Merge Request wird geprüft, eine Pipeline läuft, und ein Mensch drückt den Knopf, der den neuen Zustand anwendet. Das Smart Home läuft andersherum.
Holen statt schicken
Der Container der Zentrale trägt eine geforkte Deploy-Integration, die den geprüften Branch beobachtet, ihn alle fünf Minuten holt und in sein eigenes Konfigurationsverzeichnis mergt. Es gibt keinen Deploy-Job und keine Login-Naht: Nichts aus der CI erreicht die laufende Instanz.
Dashboards, Szenen und Skripte werden in der Oberfläche von Hand bearbeitet, und ein einseitiger Push aus der CI würde diese Arbeit bei jedem Deploy überschreiben. Deshalb läuft die Synchronisation in beide Richtungen, und alles Weitere existiert, um das sicher zu machen.
Mergen, prüfen, zurückrollen
Die Integration merkt sich den Commit, auf dem sie steht, mergt den eingehenden Branch und fährt erst dann Home Assistants eigene Konfigurationsprüfung gegen den gemergten Baum. Meldet die Prüfung Fehler, setzt sie hart auf den gemerkten Commit zurück. Nichts lädt neu; die Kiste bedient weiter den Baum, der funktioniert hat.
Der andere Zweig wiegt schwerer. Wirft der Prüfer selbst einen Fehler — eine Hilfsfunktion, deren Signatur sich verschoben hat, ein fehlgeschlagener Import —, dann winkt er den Baum nicht durch. Er blockiert, und der Kommentar im Code ist eine Zeile: Ein Tor, das nicht laufen kann, muss blockieren.
Ein Pull, der durchgeht, wirkt in die andere Richtung: Ein Event feuert, und eine in Git verwaltete Automation wendet es an — ein Reload, oder ein vollständiger Neustart, wenn sich die Kernkonfiguration oder der Code einer Integration geändert hat. Ein Merge auf den geprüften Branch kann das Haus neu starten, auf einem Baum, den die Prüfung bereits validiert hat.
Die Maschine schreibt zurück
Änderungen aus der Oberfläche werden auf der Kiste automatisch committet und direkt auf den geschützten Branch gepusht. Kein Merge Request, kein Review — und dies ist das einzige Repository der Flotte, in dem das erlaubt ist. Die CI läuft auf diesen Commits weiterhin, aber erst, wenn sie schon auf dem Branch sind; deshalb sind die unten beschriebenen Wächter die Tore auf diesem Weg, nicht die Pipeline.
Es ist als bewusst akzeptierte Abweichung festgehalten: Jede Dashboard-Änderung beim nächsten Pull zu verlieren wurde als das größere Übel bewertet. Die Kontrollen, die im selben Atemzug genannt werden, tragen das Gewicht; drei davon zählen hier.
Der Branch bleibt geschützt. Kein Force-Push, von niemandem. Ein Geheimnis, das in die Historie gelangt, lässt sich rotieren, aber nie wieder herausschreiben — deshalb muss der Wächter gegen Geheimnisse greifen, bevor ein Commit überhaupt existiert.
Das Tor vor dem Ausrollen schließt im Zweifel, siehe oben: Die Maschine, die auf den Branch schreiben darf, ist auch die, die sich weigert, einen Baum zu behalten, der nicht laden würde.
Der Commit-Pfad verweigert geheimnisförmige Pfade. Die Kiste nimmt alles in den Index auf, gleicht die aufgenommenen Pfade dann gegen eine Musterliste ab und setzt bei jedem Treffer den Index zurück und verweigert. Der Commit entsteht gar nicht erst.
Diesen Wächter gibt es, weil Ignorieren allein nicht genügte — ein unbeaufsichtigter Commit, der alles einsammelt, kann einen Pfad mitnehmen, den die Ignorier-Regeln übersehen, und die Sicherungskopie einer ignorierten Datei fällt nicht unter das Muster des Originals. Die Verweigerung ist bewusst total: Der automatische Pull legt zuerst seinen eigenen Sicherungs-Commit an, also blockiert ein blockierter Commit auch den Pull, und Merges erreichen das Haus nicht mehr, bis der störende Pfad verschwunden ist.
Was die Pipeline beweist — und was nicht
Zwölf Jobs sind über zwei Stufen definiert, Lint und Validate. Eine Deploy-Stufe gibt es nicht.
Die Konfigurationsprüfung fährt Home Assistants eigene Prüfung im offiziellen Image, per Tag und Digest auf die Version gepinnt, die in Produktion läuft, und sie blockiert den Merge Request. Die Prüfung allein ist ein falsches Grün: Home Assistant protokolliert einen schemawidrigen Eintrag, deaktiviert genau diesen Eintrag und macht weiter, sodass nur ein Syntaxfehler oder ein Fehler im Kernblock einen Fehlercode liefert. Deshalb wird das mitgeschriebene Log zusätzlich nach den Fehlerzeichenketten durchsucht. Ein eigener Job durchsucht die gesamte Git-Historie nach Geheimnissen.
Die Pipeline beweist, dass die Konfiguration unter einem gepinnten Image geparst wird und lädt, und dass die lokalen Patches am eingebetteten Fremdcode noch an Ort und Stelle sind. Keine einzige Automation, keine Template- und keine Anwesenheitsregel hat einen Test.
Vieles an der laufenden Instanz steht nicht in Git und kann es auch nicht. In der Oberfläche angelegte Szenen und Skripte, Dashboards, jeder Konfigurationseintrag einer Integration und jede Zugangsinformation liegen im eigenen Speicher der Zentrale, bewusst ungetrackt. Für die Dateien, die Git führt, ist das Repository die laufende Konfiguration — außer solange ein Tor die Kiste auf einem älteren Baum hält, was genau der Sinn der Tore ist.
Kompiliert wird hier ebenfalls nichts: Neun Knotenkonfigurationen werden in der CI validiert, gebaut wird aber in einem Container auf dem Host, und ein Build, der nie läuft, ist für Git und CI gleichermaßen unsichtbar. Nichts beweist, dass die Firmware auf einem bestimmten Knoten aus der Konfiguration gebaut wurde, die Git dafür führt. Was diese Knoten tragen und welche von ihnen Firmware fahren, die hier geschrieben und nicht bloß hier konfiguriert wurde, steht in der Notiz über die Funknetze.
Noch etwas ändert den Baum ohne einen Menschen darin. Die auf der Zentrale installierten Fremd-Integrationen aktualisieren sich in einem wöchentlichen Fenster am Sonntagvormittag selbst, und der automatische Commit veröffentlicht die neuen Versionen anschließend auf dem Branch — eine ungeprüfte Änderung am laufenden Haus, mit Absicht, auf derselben akzeptierten Abweichung wie die Bearbeitungen in der Oberfläche. Das Fenster ist bewusst schmal. Es lässt Firmware jeder Art aus, denn ein Update über die Luft würde die hier geschriebene Lampen-Firmware überschreiben, die Zugangsdaten von den Sensorknoten löschen und einen Entwicklungsstand auf den Funk-Koordinator schieben. Es lässt ein Update aus, das die Speicherbox neu startet. Und es lässt die Handvoll Komponenten mit lokalen Patches aus, denn eine Installation darüber zerstört den Patch, und der Commit veröffentlicht die Zerstörung.
Ein einziger Druck zeigte, wie wenig das Repository steuert. Am 2026-08-24 wurde die Update-Entität des Herstellers gedrückt; sie flashte das Werksimage, das keinerlei Zugangsdaten trägt, mit denen irgendetwas die Hardware noch erreichen könnte, und alle vier Apollo-Multisensor-Knoten verschwanden auf einmal aus dem Netz. Diese Entität und der Firmware-Knopf des Herstellers sind auf allen acht Hersteller-Knoten inzwischen ausgeblendet — wer nur die Entität ausblendet, lässt denselben Flash nur einen Tastendruck entfernt, weil der Knopf ihn aufruft. Inzwischen gehen die Knoten weiter als Ausblenden: Der eigene Web-Updater der Firmware ist ganz abgeschaltet, und der Notfall-Access-Point, den jeder Knoten aufspannt, wenn er das Netz nicht findet, trägt jetzt ein Passwort — derselbe Flash ist über die Luft also gar nicht mehr erreichbar.
Was fehlt und was geplant ist
- Die Sicherung außerhalb der Kiste wurde entschlüsselt und isoliert gestartet; ein Neuaufbau von null auf eine leere Maschine noch nicht. Der Bootstrap stellt den ungetrackten Zustand wieder her — aus der Sicherung außerhalb der Kiste, entschlüsselt mit dem dafür verwahrten Notfallschlüssel — und zwar auf ein leeres Konfigurationsverzeichnis; von dort übernimmt die Synchronisation. Die Backup-Notiz hat beide Hälften: die Wiederherstellung, die tatsächlich durchgeführt wurde, und den Beweis über die ganze Flotte, der weiter aussteht.
- Geplant: ein Durchgang über die physischen Bedienelemente — jeden Knopf, jeden Drehregler und jedes Pad inventarisieren, dann die Zuordnung pro Raum entscheiden, gemeinsam mit dem Ausmustern der Lichtabläufe, die noch in einer Hersteller-Bridge laufen, damit nie zwei Systeme dieselben Lampen fahren.
Beide Punkte benennen dieselbe Lücke: Nichts davon ist dadurch bewiesen, dass man es hat arbeiten sehen. Die Tore beweisen, dass ein Baum lädt — nicht, dass das Haus, das darauf läuft, neu aufgebaut werden könnte, und nicht, dass seine physischen Bedienelemente mit ihm übereinstimmen.
Deploy-Integration, Pipeline und Knotenkonfigurationen am 2026-09-08 im Smart-Home-Konfigurationsrepository gelesen, die gepinnten Validierungs-Images in den geteilten CI-Vorlagen; datierte Vorfälle tragen das Datum, das mit ihnen festgehalten ist, und geplante Punkte sind als geplant markiert.