Teil des WJ-Kreis-Digital-Standards. Referenz-Installation: Server "hafen" (WJ Konstanz-Hegau), Stand der Erhebung 2026-08-13. Vorige Kapitel beschreiben, was das System kann. Dieses Kapitel beschreibt, wie es läuft, wenn niemand hinschaut.
Wozu dieses Kapitel
Ein WJ-Kreis hat keinen Admin in Vollzeit. Wer das Digitalressort übernimmt, macht das im Ehrenamt, neben Job und Familie, und gibt das Amt nach ein bis zwei Jahren weiter. Ein System, das wöchentliche Handarbeit braucht, stirbt an der ersten Amtsübergabe. Der Standard setzt deshalb auf drei Prinzipien: Updates laufen automatisch und heilen sich selbst, Secrets liegen nie im Klartext in Dokumenten oder Repos, und das Monitoring ist so schlank, dass es tatsächlich gelesen wird. Alles in diesem Kapitel ist auf der Referenz-Installation im Einsatz oder als Empfehlung markiert.
1. Automatische Updates
1.1 Betriebssystem
Das OS (Ubuntu 24.04 auf der Referenz) spielt Sicherheitsupdates selbstständig ein: unattended-upgrades, bewusst ohne automatischen Reboot. Ein Reboot-Fenster plant ihr manuell, wenn ein Kernel-Update ansteht; alles andere läuft ohne Zutun.
1.2 Nextcloud: das Nachtscript mit Self-Heal
Kernstück des wartungsarmen Betriebs ist nextcloud-autoupdate.sh (im Standard-Repo unter wj/Nextcloud/, installiert als /usr/local/sbin/nextcloud-autoupdate.sh, getriggert über /etc/cron.d/nextcloud-autoupdate täglich um 02:30). Das Script macht drei Dinge:
- App-Updates:
occ app:update --allaktualisiert alle installierten Apps. - Core-Point-Releases:
updater/updater.phar --no-interactionzieht Patch-Versionen im stable-Channel (34.0.1 auf 34.0.2 und so weiter). Major-Upgrades macht es bewusst nicht. - Self-Heal: Nach dem Update prüft es den Zustand und repariert die beiden häufigsten Hänger selbst (Details in Abschnitt 4).
Alles landet im Log /var/log/nextcloud-autoupdate.log, monatlich rotiert per logrotate. Damit das Script ohne Passwort-Eingabe laufen kann, braucht es einen Sudoers-Eintrag, und zwar einen chirurgisch engen: NOPASSWD ausschließlich für das exakte occ-Pattern (sudo -u www-data php /var/www/html/occ ...) und für updater.phar. Alles andere bleibt passwortpflichtig. Das ist die Balance zwischen Automatisierbarkeit und Angriffsfläche.
1.3 Major-Upgrades bleiben Handarbeit
Ein Major-Sprung (etwa Nextcloud 32 auf 33) ist ein geplanter Eingriff, kein Nachtjob. Zwei Lehren aus der Referenz:
- Update-Channel prüfen: Steht der Channel auf
production, zieht der Updater nur Patch-Versionen und der Major-Sprung erscheint nie. Fix:occ config:system:set updater.release.channel --value stable. - Backup-Trio vorher: DB-Dump, Code+Data-Tarball, Config-Snapshot, abgelegt nach dem Muster
/var/backups/nextcloud-pre<major>/. Nach ein paar Wochen stabilem Betrieb dürft ihr das Trio löschen.
Nach jedem Core-Upgrade gehören die Docker-Sidecars (Talk-HPB, Collabora, Whiteboard) einmal durchgestartet: docker pull plus Container-Restart, auch wenn das Image "up to date" meldet. Die Container brauchen eine frische Verbindung zur upgegradeten Nextcloud.
2. Backup-Konzept
Ehrlicher Befund aus der Referenz: Das Backup-Regime ist dort gelebte Praxis, aber noch nicht vollständig als Script im Repo. Belegt sind das Backup-Trio vor Major-Upgrades (Abschnitt 1.3) und ein Cron-Backup des Kompetenz-Hubs alle 3 Stunden. Für den Standard formulieren wir daraus die Soll-Architektur; die Punkte ohne Repo-Artefakt sind als Empfehlung markiert.
Was ein Kreis-Backup abdecken muss:
| Was | Warum | Status Referenz |
|---|---|---|
| Nextcloud-Datenbank (Dump) | ohne DB sind die Dateien nur ein Haufen Blobs | vor Major-Upgrades belegt; täglich = Empfehlung |
| Nextcloud data-Verzeichnis | die eigentlichen Dateien | wie oben |
| Nextcloud config.php | Instanz-Identität, Salts, Secrets | im Backup-Trio enthalten |
n8n /opt/n8n/data | Workflows und verschlüsselte Credentials | offen, als Backup-Cron einzurichten |
N8N_ENCRYPTION_KEY | ohne ihn ist das n8n-Backup halb wertlos (siehe Abschnitt 3) | liegt root-only in der Compose-Datei, gehört zusätzlich in die sichere Ablage |
| Docker-Volumes weiterer Dienste (z. B. Demo-Instanz, Analytics) | je nach Kreis-Scope | teilweise (Kompetenz-Hub alle 3 h) |
Drei Empfehlungen dazu, alle drei ja/nein prüfbar:
- Täglicher Backup-Cron für DB-Dump und Data-Verzeichnis, mit Aufbewahrung von mindestens 7 Tagesständen.
- Offsite-Kopie: Ein Backup auf demselben Server schützt gegen "occ upgrade ging schief", aber nicht gegen "Server weg". Hetzner-Storage-Box, ein zweiter Server oder ein verschlüsseltes Ziel beim Kreis reichen.
- Restore-Probe einmal pro Amtsjahr: Ein Backup, das nie zurückgespielt wurde, ist eine Hoffnung, kein Backup. Die Demo-Replika-Mechanik (Kapitel Rollout-Runbook) eignet sich als Restore-Ziel.
3. Secrets-Handling: das Vault-Prinzip
Die eiserne Regel des Standards: Kein Secret-Wert steht jemals im Klartext in einem Dokument, einem Repo oder einer Chat-Nachricht. Dokumentiert werden nur Key-Namen, Ablageorte und Platzhalter wie <SIGNALING_SECRET>. Auf der Referenz ist das durchgezogen; so sieht es konkret aus:
- Secrets entstehen serverseitig. Das Bootstrap-Script der Demo-Replika generiert Passwörter per
openssl randdirekt auf dem Server in eine.env(root, chmod 600). Kein Mensch tippt sie, kein Repo enthält sie. - Secrets wandern per Datei, nie per Kommandozeile. Beim Recreate eines Containers werden die Env-Werte per env-file aus dem alten Container übernommen. So tauchen sie weder in der Shell-History noch in einer Session-Mitschrift auf.
- Jeder Dienst hat einen dedizierten Service-Account mit Minimalrechten. Auf der Referenz: drei VereinOnline-Service-User (Lesen, Anmelde-Writes, Event-Verwaltung) statt eines Admin-Tokens, und in Nextcloud der User
wj-botin der GruppeAutomationmit App-Token, bewusst ohne User-Create-Rechte. API-User sind ausdrücklich nie Admins. - Rotation ist definiert. VO-Tokens hängen am Passwort-Hash des Service-Users, Rotation heißt also Passwort wechseln. Nextcloud-App-Tokens sind per
occ user:auth-tokens:addneu erzeugbar. n8n-API-Keys rotieren über die Settings.
Ein Wert verdient besondere Aufmerksamkeit: der N8N_ENCRYPTION_KEY. Er verschlüsselt alle in n8n gespeicherten Credentials. Geht er verloren, sind sämtliche Zugänge unentschlüsselbar und müssen neu angelegt werden (die Workflows selbst bleiben intakt). Er liegt auf der Referenz root-only in der Compose-Datei; sichert ihn zusätzlich an einem zweiten sicheren Ort, getrennt vom Server.
Führt außerdem ein Secrets-Register: eine Tabelle mit Key-Namen und Ablageort je Secret, ohne Werte. Das Register darf in die Kreis-Doku, denn es verrät nichts, macht aber jede Amtsübergabe und jede Rotation zu einer Abhak-Übung statt einer Schatzsuche. Das Muster der Referenz steht im Inventar (meta/inventory-knowledge.md, Abschnitt 9).
Zum Schluss die Sonderfalle VereinOnline: Das VO-Token-Format ist A/<username>/<md5(passwort)>. MD5 ist kryptografisch gebrochen, das ist VO-Stand der Technik und nicht von euch änderbar. Konsequenz: langes Zufallspasswort für die Service-User, Transport ausschließlich über HTTPS. Und: Ein ungültiges VO-Token erzeugt keinen Fehler, sondern einen stillen Fallback auf anonyme Rechte. Write-Workflows sollten deshalb die Antwort auf den angemeldeten Usernamen prüfen, statt Erfolg anzunehmen.
4. Wenn der Wartungsmodus hängt: das Self-Heal-Pattern
Das häufigste Nextcloud-Betriebsproblem sieht so aus: Ein Update wird angestoßen (Web-Updater, Timeout, Verbindungsabbruch), bricht mittendrin ab, und die Instanz bleibt im Wartungsmodus stehen. Für alle Mitglieder ist "die Cloud kaputt", tatsächlich fehlen genau zwei Kommandos. Auf der Referenz ist genau das am 2026-08-13 passiert (abgebrochener Web-Updater beim Sprung auf 34.0.2), und aus dem Vorfall wurde das Self-Heal im Nachtscript.
Das Muster, erst als Handgriff, dann als Automatik:
Manuell (wenn ihr es live vor euch habt):
occ status # zeigt maintenance: true und ggf. needsDbUpgrade
occ upgrade # zieht eine hängende DB-Migration zu Ende
occ maintenance:mode --off # schaltet den Wartungsmodus ab
Wichtig ist die Reihenfolge: erst prüfen, ob eine DB-Migration aussteht (needsDbUpgrade: true in occ status), und die zuerst durchlaufen lassen. Den Wartungsmodus einfach abzuschalten, während die Datenbank halb migriert ist, verschiebt das Problem nur.
Automatisch: Das Nachtscript prüft nach jedem Lauf exakt diese beiden Zustände. Meldet occ status ein needsDbUpgrade: true, läuft occ upgrade nach. Steht der Maintenance-Mode noch, obwohl kein Upgrade mehr aussteht, schaltet das Script ihn ab. Damit heilt sich die häufigste Störung innerhalb von 24 Stunden selbst, ohne dass jemand gerufen wird. Wer nachts um 02:30 nicht warten will, führt das Script einfach manuell aus; es ist idempotent.
Die Meta-Lektion für euer Digitalressort: Jede Störung, die zweimal auftritt, gehört als Erkennung plus Reparatur ins Nachtscript, nicht ins Gedächtnis des aktuellen Amtsinhabers.
5. Monitoring-Minimum
Ihr braucht kein Grafana-Dashboard. Ihr braucht Antworten auf vier Fragen, und zwar mit minimalem Aufwand:
- Läuft die Cloud? Empfehlung: ein externer Uptime-Check auf
https://<eure-domain>/status.php(der Endpoint liefert JSON mit"installed":trueund der Version, das Bootstrap-Script der Replika nutzt ihn genauso). Externe Gratis-Dienste oder ein Cron auf einem anderen Server reichen. - Liefen die Updates durch? Ein Blick in
/var/log/nextcloud-autoupdate.log. Empfehlung als Ausbaustufe: das Script bei Fehlern eine Nachricht in einen Talk-Kanal schicken lassen, das Muster dafür (Talk-Chat-API mit Bot-User) existiert in den Flow-Workflows bereits. - Geht dem Server etwas aus? Die Nextcloud-App
serverinfo(auf der Referenz aktiv) zeigt RAM, Platte und Last direkt in der Admin-Oberfläche. Auf der Referenz sind nach dem Aufbau der Demo-Replika noch 2,7 GB RAM frei, der Server ist damit voll; genau solche Grenzen muss der Kreis kennen, bevor er den nächsten Dienst dazustellt. - Sind die Container gesund?
docker pszeigt die Health-Stati (HPB und Whiteboard laufen auf der Referenz mit Healthcheck). Für den Talk-HPB gibt es zusätzlich einen echten Funktionstest:curl https://<domain>/standalone-signaling/api/v1/welcomemuss antworten.
Dazu gehören die Bordmittel, die ohnehin installiert sind und im Standard-App-Set bleiben: logreader (Nextcloud-Log in der UI), updatenotification (Hinweis auf anstehende Major-Versionen), admin_audit (wer hat was geändert), suspicious_login und bruteforcesettings (Login-Anomalien). Einmal pro Monat fünf Minuten in die Admin-Übersicht zu schauen ist das ganze Monitoring-Ritual; alles Dringende soll euch erreichen, statt gefunden werden zu müssen.
6. Sicherheits-Baseline
Die Grundhärtung der Referenz, als Standard übernehmbar:
- Netzwerk-Muster: Alle Dienste binden nur auf
127.0.0.1und werden über Apache-vHosts mit Let's-Encrypt-TLS nach außen gereicht. Einzige Ausnahme: TURN/STUN auf Port 3478 (tcp/udp), das braucht Talk technisch. Zertifikats-Renewal läuft automatisch per certbot-Cron. - SSH: nur key-based (ED25519), kein Passwort-Login.
- 2FA: TOTP- und WebAuthn-Provider sind installiert. Auf der Referenz ist 2FA Stand 2026-08-13 Opt-in, nicht erzwungen; der Vorstands-Rollout ist dort der letzte offene Punkt. Empfehlung für den Standard: 2FA als Pflicht mindestens für Vorstand, Schatzmeister und alle Admin-Accounts, mit Passkey/WebAuthn als erster Wahl vor TOTP. Eine fertige Rollout-Anleitung für Nicht-Techniker existiert als Baustein.
- Passwort- und Login-Politik:
password_policy,bruteforcesettings,suspicious_login,admin_auditgehören zum Standard-App-Set. - Least Privilege überall: Sudoers nur für occ und updater.phar, Bot-User ohne Admin-Rechte, VO-Service-User mit Minimalrollen (Abschnitt 3).
7. Update-Gotchas bei geteilten Containern
Sobald ein Server mehr als eine Nextcloud bedient (Co-Tenant-Modell, Kapitel Rollout-Runbook), teilen sich die Instanzen Collabora und den Talk-HPB. Das spart Ressourcen, schafft aber zwei Update-Fallen, die beide schon real zugeschnappt haben beziehungsweise im Blueprint dokumentiert sind:
Talk-HPB (aio-talk-Container): Der Container generiert seine Signaling-Config bei jedem Start im Entrypoint neu, fest auf eine Domain. Multi-Tenant funktioniert deshalb über ein gepatchtes Startskript, das als read-only Bind-Mount über /start.sh gelegt wird (Overlay, auf der Referenz seit 2026-08-13 aktiv, Original gesichert). Daraus folgen zwei Pflichten bei jedem Image-Update:
- Den Overlay-Mount beim Recreate behalten. Wer den Container ohne den
-v ...:/start.sh:ro-Mount neu erstellt, trennt kommentarlos die zweite Instanz vom HPB. - Das Startskript aus dem neuen Image frisch extrahieren und neu patchen (
docker run --rm <image> cat /start.sh, dann Patch anwenden). Wer den alten Patch weiterverwendet, pinnt veraltete Upstream-Logik fest.
Dazu das allgemeine HPB-Update-Muster: env-file aus dem alten Container übernehmen (Secrets bleiben serverseitig), Ports 3478 tcp/udp plus 127.0.0.1:8081 setzen, und danach beide Instanzen per curl .../standalone-signaling/api/v1/welcome verifizieren. Eine bekannte, harmlose Warnung nach Updates: "Server unterstützt nicht alle Funktionen dieser Talk-Version" heißt nur, dass der Signaling-Server im Image der spreed-App hinterherhinkt; nur Admins sehen das, der Fix kommt mit dem nächsten Image-Release.
Collabora: Weitere Instanzen hängen per aliasgroupN-Env am selben Container. Beim Update oder Recreate müssen alle aliasgroup-Einträge im Env-File erhalten bleiben, sonst verliert eine der Instanzen ihr Office. Nach jedem Recreate beide (alle) angebundenen Nextclouds kurz prüfen: ein Dokument öffnen genügt.
Die Merkregel hinter beiden Fällen, wortwörtlich aus dem Blueprint der Referenz: Generiert ein Container seine Config im Entrypoint aus Env-Variablen, patcht man den Entrypoint per read-only Bind-Mount, nie die generierte Config im laufenden Container. Und generell gilt für geteilte Container: Ein Update betrifft immer alle angebundenen Instanzen gleichzeitig, also nach jedem Update jede Instanz einzeln verifizieren, nicht nur die Haupt-Instanz.
Checkliste
Einmalig bei der Einrichtung:
unattended-upgradesaktiv, Auto-Reboot aus?nextcloud-autoupdate.shinstalliert, Cron-Eintrag vorhanden, Log-Datei wächst?- Sudoers-Eintrag NOPASSWD nur für occ-Pattern und updater.phar, nichts weiter?
- Update-Channel steht auf
stable(occ config:system:get updater.release.channel)? - Backup-Cron für DB-Dump und Data-Verzeichnis eingerichtet, Offsite-Ziel definiert?
N8N_ENCRYPTION_KEYan einem zweiten sicheren Ort gesichert (getrennt vom Server)?- Secrets-Register angelegt (Key-Namen und Ablageorte, keine Werte)?
- Kein Secret-Wert in Repo, Doku oder Chat auffindbar (Stichproben-grep)?
- Alle Service-Accounts ohne Admin-Rechte (VO-User, NC-Bot)?
- Externer Uptime-Check auf
status.phpeingerichtet? - 2FA-Pflicht für Vorstand und Admin-Accounts entschieden und kommuniziert?
- Alle Dienste binden nur auf 127.0.0.1 (Ausnahme 3478), TLS via Let's Encrypt?
Wiederkehrend (monatliches 15-Minuten-Ritual):
/var/log/nextcloud-autoupdate.logauf Fehler durchgesehen?- Admin-Übersicht (serverinfo): RAM, Platte, Warnungen geprüft?
docker ps: alle Container Up, Healthchecks grün?- Jüngstes Backup vorhanden und plausibel groß?
Bei jedem Image-Update geteilter Container:
- HPB: Overlay-Mount beim Recreate dabei?
- HPB: Startskript aus dem neuen Image frisch extrahiert und neu gepatcht?
- HPB: env-file übernommen,
welcome-Endpoint beider Instanzen antwortet? - Collabora: alle
aliasgroupN-Einträge erhalten, Dokument-Öffnen auf jeder Instanz getestet?
Bei Major-Upgrades:
- Backup-Trio (DB-Dump, Code+Data-Tarball, Config-Snapshot) vorher gezogen?
- Nach dem Upgrade: Docker-Sidecars gepullt und neu gestartet?
occ statussauber (maintenance false, kein needsDbUpgrade)?
Referenz KNH
So läuft es bei Konstanz-Hegau konkret (Stand 2026-08-13):
| Baustein | Umsetzung auf hafen |
|---|---|
| OS-Updates | unattended-upgrades auf Ubuntu 24.04, ohne Auto-Reboot |
| NC-Updates | /usr/local/sbin/nextcloud-autoupdate.sh, täglich 02:30 via /etc/cron.d/nextcloud-autoupdate, Log /var/log/nextcloud-autoupdate.log, logrotate monatlich |
| Self-Heal | im Nachtscript: needsDbUpgrade löst occ upgrade aus, hängender Maintenance-Mode wird abgeschaltet; Anlassfall war der abgebrochene Web-Updater beim Sprung auf 34.0.2 am 2026-08-13 |
| Sudoers | NOPASSWD nur für das occ-Pattern und (seit 2026-08-13) updater.phar |
| Backups | Backup-Trio vor Major-Upgrades unter /var/backups/nextcloud-pre<major>/; Kompetenz-Hub alle 3 h per Cron; täglicher NC-Backup-Cron und n8n-Backup-Cron stehen als offene Punkte |
| Secrets | serverseitig generierte .env-Dateien (root, chmod 600), env-file-Übernahme bei Container-Recreates, N8N_ENCRYPTION_KEY root-only in /opt/n8n/, Secrets-Register im Inventar |
| Service-Accounts | VO: der Lese-User (read), der Write-User (Anmeldungen), der Event-User (Event-CRUD); NC: wj-bot in Gruppe Automation, App-Token, keine User-Create-Rechte |
| Monitoring | serverinfo, logreader, updatenotification, admin_audit, suspicious_login, bruteforcesettings aktiv; Container-Healthchecks für HPB und Whiteboard; RAM-Reserve nach Demo-Aufbau 2,7 GB (Server voll) |
| 2FA | TOTP + WebAuthn + Backup-Codes installiert, Opt-in; Vorstands-Rollout mit fertiger Anleitung ist der letzte offene Follow-up |
| Geteilte Container | Talk-HPB multi-tenant per start.sh-Overlay (backend-1 hafen, backend-2 wjhcloud-Demo, Original als hpb-start-orig.sh gesichert); Collabora bedient beide NCs per aliasgroup2 |
| Netzwerk | alles auf 127.0.0.1 hinter Apache + Let's Encrypt, offen nur 3478 (TURN/STUN); SSH key-based ED25519 |
Offene Punkte der Referenz, die ein nachbauender Kreis von Tag 1 an besser machen kann: täglicher Backup-Cron mit Offsite-Ziel, n8n-Backup, 2FA-Pflicht ab Einrichtung statt nachträglichem Rollout, und im HPB-Overlay ein eigener Secret-Eintrag pro Backend.