Homelab MCP – Release-Verwaltung, Update & Rollback¶
Stand 09.09.2026: CT 109 besitzt eine privileggetrennte Release-, Update- und Rollback-Verwaltung. Neue Releases werden getrennt heruntergeladen, unprivilegiert getestet und zunächst nur als inaktive Releases installiert. Aktivierung und Rollback bleiben eigenständige, auditierte Admin-Aktionen.
Architektur¶
flowchart LR
UI["Admin UI"] --> API["Admin API"]
API --> RM["Release Manager"]
RM --> GIT["Git ls-remote / Clone"]
RM --> STAGE["Update-Staging"]
STAGE --> BUILDER["unprivilegierter Update Builder"]
BUILDER --> RELEASE["inaktives Release"]
RELEASE --> ACT["explizite Aktivierung"]
ACT --> VERIFY["Service- und MCP-Prüfung"]
VERIFY -->|Fehler| RB["automatischer Rollback"]
Dienste¶
Release Manager¶
Der Dienst läuft als root mit primärer Gruppe homelab-mcp, aber weiterhin mit leerer CapabilityBoundingSet und AmbientCapabilities.
Er bietet keine Shell-Schnittstelle. Die Kommunikation erfolgt nur über feste Release-/Update-Operationen auf:
Geprüfte Rechte auf CT 109:
Der normale MCP-Prozess kann den Socket nicht öffnen.
Update Builder¶
Der Builder läuft nur bei Bedarf als One-Shot-Dienst unter:
Er führt Paketinstallation und Tests des bereits heruntergeladenen Staging-Releases aus. Der private GitHub-Key wird ihm nicht zur Verfügung gestellt.
Release-Struktur¶
Der Laufzeitbenutzer kann aktive Releases lesen, aber nicht verändern.
Privilegierter Rollback-Zustand¶
Der vorherige Release-Stand liegt unter:
systemd verwaltet das Verzeichnis mit:
Geprüfte Rechte:
Damit benötigt der Release-Manager weder CAP_DAC_OVERRIDE noch CAP_CHOWN.
Update-Staging¶
Verzeichnis:
Es wird durch die mitgelieferte tmpfiles-Regel erzeugt:
Rechte:
Nur dieser Staging-Baum ist für den Builder persistent beschreibbar.
Gültiges Release¶
Ein Release muss ein echtes Verzeichnis direkt unter /opt/homelab-mcp/releases/ sein. Symlink-Releases und Pfad-Traversal werden abgewiesen.
Pflichtbestandteile sind inzwischen mindestens:
package.json
src/mcp/service.js
src/admin/service.js
src/release/update-builder.js
privileged/audit-writer.js
privileged/release-manager.js
tmpfiles.d/homelab-mcp.conf
systemd/homelab-mcp.service
systemd/homelab-mcp-admin.service
systemd/homelab-mcp-audit-writer.service
systemd/homelab-mcp-release-manager.service
systemd/homelab-mcp-update-builder@.service
Ältere Releases ohne diese Struktur werden als ungültig angezeigt und können nicht aktiviert werden.
Aktivierungsablauf¶
- aktuelles Release bestimmen;
- Zielrelease und Pflichtdateien validieren;
- kritische Node-Einstiegspunkte mit
node --checkprüfen; - Basis-systemd-Units des Zielreleases atomar nach
/etc/systemd/systemübernehmen; systemctl daemon-reload;currentatomar auf das Zielrelease setzen;- Audit-Writer und MCP neu starten;
- Dienste und MCP-Route innerhalb eines begrenzten Retry-Fensters prüfen;
- erst nach erfolgreicher Prüfung die vorherige Release-ID speichern;
- anschließend Release-Manager und Admin-Kontrollpfad vom neuen Release neu starten.
Verwaltete systemd-Units¶
Der Release-Manager darf nur diese Basis-Units ersetzen:
homelab-mcp.service
homelab-mcp-admin.service
homelab-mcp-audit-writer.service
homelab-mcp-release-manager.service
homelab-mcp-update-builder@.service
Lokale Drop-ins unter /etc/systemd/system/<unit>.d/ bleiben erhalten.
Automatischer Rollback¶
Scheitert ein Release nach Unit-Installation oder Symlink-Wechsel:
- Basis-Units des vorherigen Releases zurückspielen;
systemctl daemon-reload;currentauf das ursprüngliche Release zurücksetzen;- Audit-Writer und MCP neu starten;
- den zurückgesetzten Datenpfad erneut prüfen.
Die Admin-API erhält nur:
Die konkrete interne Fehlerursache bleibt im Journal des Release-Managers.
Live bestätigt¶
Der Fehlerpfad wurde auf CT 109 real mehrfach geprüft. Dabei wurden Aktivierungsfehler erkannt, das ursprüngliche Release automatisch wiederhergestellt und alle vier dauerhaften Dienste anschließend wieder als aktiv bestätigt.
Die erfolgreiche Aktivierung eines Testreleases ist automatisiert getestet. Der letzte bewusste Live-Aktivierungsaufruf wurde durch den übergeordneten Shell-Sicherheitsfilter blockiert und deshalb nicht erzwungen.
Private GitHub-Updatequelle¶
CT 109 besitzt einen eigenen ED25519-Key nur für Updates.
Private Datei:
Rechte:
Der private Deploy Key von CT 108 wurde ausdrücklich nicht kopiert.
Der GitHub-ED25519-Hostkey wurde auf CT 109 per ssh-keyscan ermittelt und vor Verwendung exakt mit dem bereits auf CT 108 vertrauenswürdigen GitHub-Hostkey verglichen.
Pinned Host-Datei:
StrictHostKeyChecking=yes bleibt zwingend aktiv.
Lokale Update-Konfiguration¶
Die Datei ist root:root 0600 und enthält lokal:
Repository: git@github.com:HerrBausW/homelab-mcp.git
Branch: main
Identity-Datei: /etc/homelab-mcp/update/github_deploy_key
Known-Hosts-Datei: /etc/homelab-mcp/update/known_hosts
Die generische Vorlage liegt im Repository unter:
Die Release-Manager-Unit erhält die lokale Konfiguration über ein installationsspezifisches systemd-Drop-in.
Aktueller GitHub-Status¶
Der neue CT-109-Public-Key ist seit dem 09.09.2026 im privaten Repository als read-only Deploy Key autorisiert.
Der Release-Manager bestätigt inzwischen:
Damit ist der private GitHub-Zugriff vollständig funktionsfähig. git ls-remote und ein realer Clone des privaten Repositorys wurden auf CT 109 erfolgreich geprüft.
Sicherer Download-Ablauf¶
1. Remote prüfen¶
Der root-Release-Manager führt nur ein festes git ls-remote für Repository und Branch aus. Repository-Code wird dabei nicht ausgeführt.
2. Commit festhalten¶
Die exakt zurückgegebene 40-stellige Commit-ID wird geprüft. Die ersten 12 Zeichen bilden die Release-ID.
3. Klonen¶
Der exakt konfigurierte Branch wird nach:
geklont. Anschließend muss HEAD exakt der zuvor ermittelten Commit-ID entsprechen.
4. Root führt keinen neuen Anwendungscode aus¶
Der root-Release-Manager führt nur Git und feste Dateisystem-/systemd-Operationen aus. npm ci und Tests des frisch geholten Codes laufen nicht als root.
5. Unprivilegiert installieren und testen¶
Der Builder führt aus:
Durch systemd sind für den Builder unter anderem gesperrt:
ProtectSystem=strict ist aktiv. Persistent beschreibbar ist nur der Update-Staging-Baum.
6. Finalisieren¶
Nach erfolgreichem Builder-Lauf:
.gitentfernen;- absolute Symlinks ablehnen;
- Symlinks außerhalb des Staging-Baums ablehnen;
- neues root-eigenes Release erzeugen;
- Release-Rechte wieder auf 0750/0640 härten;
- fertiges Release nochmals validieren;
currentnicht verändern.
Ein Update wird also zuerst nur installiert. Aktivierung ist immer eine zweite bewusste Aktion.
Admin-API¶
GET /api/system/update
POST /api/system/update/install
GET /api/system/releases
POST /api/system/releases/<release-id>/activate
POST /api/system/rollback
Mutationen benötigen Admin-Session, CSRF-Token und einen funktionierenden fail-closed Audit-Pfad.
Audit-Aktionen:
Admin-Oberfläche¶
Der System-Bereich kann inzwischen anzeigen beziehungsweise auslösen:
- aktives Release;
- vorheriges Release;
- installierte Releases;
- Release gültig/ungültig;
- Release aktivieren;
- Rollback;
- Updatequelle konfiguriert/erreichbar;
- neuesten Remote-Commit beziehungsweise Release-ID;
- bereits installiert ja/nein;
- neues Update installieren.
Update installieren aktiviert den Stand ausdrücklich nicht automatisch.
Noch ausstehender manueller Schritt¶
Der neue CT-109-Public-Key muss einmalig im privaten GitHub-Repository HerrBausW/homelab-mcp unter Settings → Deploy keys als read-only Deploy Key eingetragen werden.
Danach kann der neue Updater ohne weiteren SSH-/Server-Umbau direkt getestet werden.