Zum Inhalt

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

homelab-mcp-release-manager.service

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:

/run/homelab-mcp-release/release.sock

Geprüfte Rechte auf CT 109:

root:homelab-mcp 0600

Der normale MCP-Prozess kann den Socket nicht öffnen.

Update Builder

homelab-mcp-update-builder@.service

Der Builder läuft nur bei Bedarf als One-Shot-Dienst unter:

User=homelab-mcp
Group=homelab-mcp

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

/opt/homelab-mcp/
  releases/<release-id>/
  current -> releases/<release-id>

Der Laufzeitbenutzer kann aktive Releases lesen, aber nicht verändern.

Privilegierter Rollback-Zustand

Der vorherige Release-Stand liegt unter:

/var/lib/homelab-mcp/release-manager/previous-release

systemd verwaltet das Verzeichnis mit:

StateDirectory=homelab-mcp/release-manager
StateDirectoryMode=0700

Geprüfte Rechte:

root:homelab-mcp 0700

Damit benötigt der Release-Manager weder CAP_DAC_OVERRIDE noch CAP_CHOWN.

Update-Staging

Verzeichnis:

/var/lib/homelab-mcp/update-builder

Es wird durch die mitgelieferte tmpfiles-Regel erzeugt:

tmpfiles.d/homelab-mcp.conf

Rechte:

homelab-mcp:homelab-mcp 0770

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

  1. aktuelles Release bestimmen;
  2. Zielrelease und Pflichtdateien validieren;
  3. kritische Node-Einstiegspunkte mit node --check prüfen;
  4. Basis-systemd-Units des Zielreleases atomar nach /etc/systemd/system übernehmen;
  5. systemctl daemon-reload;
  6. current atomar auf das Zielrelease setzen;
  7. Audit-Writer und MCP neu starten;
  8. Dienste und MCP-Route innerhalb eines begrenzten Retry-Fensters prüfen;
  9. erst nach erfolgreicher Prüfung die vorherige Release-ID speichern;
  10. 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:

  1. Basis-Units des vorherigen Releases zurückspielen;
  2. systemctl daemon-reload;
  3. current auf das ursprüngliche Release zurücksetzen;
  4. Audit-Writer und MCP neu starten;
  5. den zurückgesetzten Datenpfad erneut prüfen.

Die Admin-API erhält nur:

rollbackPerformed
rollbackHealthy

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:

/etc/homelab-mcp/update/github_deploy_key

Rechte:

root:root 0600

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:

/etc/homelab-mcp/update/known_hosts

StrictHostKeyChecking=yes bleibt zwingend aktiv.

Lokale Update-Konfiguration

/etc/homelab-mcp/update.json

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:

config/update.example.json

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:

{
  "configured": true,
  "reachable": true
}

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:

/var/lib/homelab-mcp/update-builder/<release-id>/source

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:

npm ci --no-audit --no-fund
npm test
node_modules entfernen
npm ci --omit=dev --no-audit --no-fund

Durch systemd sind für den Builder unter anderem gesperrt:

/etc/homelab-mcp/secrets
/etc/homelab-mcp/ssh
/run/homelab-mcp-audit
/run/homelab-mcp-release

ProtectSystem=strict ist aktiv. Persistent beschreibbar ist nur der Update-Staging-Baum.

6. Finalisieren

Nach erfolgreichem Builder-Lauf:

  • .git entfernen;
  • 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;
  • current nicht 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:

install-update
activate-release
rollback-release

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.