Commit Graph

272 Commits

Author SHA1 Message Date
Micha e80e5dd49f renovate: komodo-Stack (inline-managed) aus Tracking nehmen
Der komodo-Stack wird in Komodo inline (file_contents) verwaltet, nicht aus dem Repo deployed. Renovate-PRs darauf wirken zur Laufzeit nicht und erzeugen Git-Komodo-Scheinsicherheit. Daher: ops/komodo/** in ignorePaths, mongo-Digest auf den real laufenden Stand zurueckgesetzt, Inline-Ausnahme in docs/RENOVATE.md und im Compose-Header dokumentiert.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-10 20:34:52 +02:00
Micha 3c339474a7 Merge pull request 'chore(deps): update mongo:8.0.23 docker digest to 73ee318' (#13) from renovate/mongo-8.0.23 into master
Reviewed-on: #13
2026-06-10 18:27:13 +00:00
renovate 9847baf327 chore(deps): update minor-and-patch-updates 2026-06-10 14:32:08 +00:00
renovate cf11b4d75b chore(deps): update mongo:8.0.23 docker digest to 73ee318 2026-06-10 04:21:10 +00:00
Micha cf9ca59eb1 docs: close baerchen veeam recovery test 2026-06-06 13:27:31 +02:00
Micha d2a9c3b8cb docs: record baerchen veeam recovery usb boot 2026-06-06 13:25:53 +02:00
Micha a4c79d9d81 docs: record guest iot preflight 2026-06-06 13:14:07 +02:00
Micha 18a90fbb4b ops: add guest iot network preflight 2026-06-06 13:13:01 +02:00
Micha 6e65f81503 docs: record restore freshness negative alert test 2026-06-06 13:04:42 +02:00
Micha 6123584a02 ops: make freshness negative ntfy call robust 2026-06-06 13:03:05 +02:00
Micha c33e29016b ops: add restore freshness negative alert test 2026-06-06 13:02:14 +02:00
Micha c3491eb382 tailscale: auf natives Plugin konsolidieren, redundanten Docker-Stack entfernen, ACL-Haertung dokumentieren
- host-services/tailscale/ (userspace-only Docker-Stack) entfernt; Komodo stop/destroy durch Operator, danach git rm
- Glance-Widget Tailscale-Docker entfernt
- HOMELAB_ARCHITECTURE/SERVICE_CATALOG/DISASTER_RECOVERY/CLAUDE/RESTORE_MATRIX: tailscale als natives Unraid-Plugin dokumentiert; Restore-State-Pfad korrigiert auf /boot/config/plugins/tailscale/state (Flash-Backup)
- NETWORK_INVENTORY: restriktive tag-basierte grants-ACL (2026-06-06; tag:server/tag:operator, tag:family vorbereitet) und Subnet-Router-Befund dokumentiert

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-06 10:58:59 +02:00
Micha 3a263a4846 docs: update dr workstation readiness 2026-06-06 09:17:23 +02:00
Micha 68d3ace598 ops: add dr workstation readiness check 2026-06-06 08:40:31 +02:00
Micha 0ef98a23e1 docs: close baerchen app license checks 2026-06-06 08:31:17 +02:00
Micha 6353da47c5 ops: add baerchen app license readiness check 2026-06-06 08:27:10 +02:00
Micha a687d9b73e docs: record redis restore test 2026-06-06 08:11:03 +02:00
Micha e3459c76d0 fix: use redis pre-cutover restore artifact 2026-06-06 08:08:52 +02:00
Micha 254eb81496 ops: add redis restore test 2026-06-06 08:07:11 +02:00
Micha 9a6d7123ce docs: record adguard restore test 2026-06-06 08:03:53 +02:00
Micha 151d253aff ops: add adguard restore test 2026-06-06 08:01:27 +02:00
Micha bc3ecad45a backup: windows image baseline for baerchen 2026-06-05 22:19:27 +02:00
Micha af2c6ee533 docs: record final games partition state 2026-06-04 17:37:11 +02:00
Micha f382c25696 docs: record post reboot boot check 2026-06-04 17:30:20 +02:00
Micha d710a506e8 docs: record boot cleanup execution 2026-06-04 17:26:55 +02:00
Micha 2ea65e906d docs: add boot cleanup plan 2026-06-04 15:06:58 +02:00
Micha 2d438cf02b docs: add drive restructure review follow-up 2026-06-04 14:40:42 +02:00
Micha 7ba10c893b docs: document drive restructure status 2026-06-04 14:25:10 +02:00
Micha fb948ac951 docs: add windows postdelta handoff 2026-06-04 11:51:22 +02:00
Micha ba87719de3 fix(restore): nextcloud-test create .ncdata marker in test data dir
Zweiter Lauf am 2026-06-03 ergab nach dem ersten Fix (config-Permissions)
einen neuen Fehler: HTTP 503 mit "Your data directory is invalid. Ensure
there is a file called .ncdata in the root of the data directory."

Hintergrund: Nextcloud prueft beim HTTP-Request eine Marker-Datei `.ncdata`
mit festem Inhalt im Datenverzeichnis. Produktiv liegt der Marker unter
/mnt/user/documents/nextcloud-data/.ncdata. Der Smoke-Test mountet diesen
Pfad bewusst nicht, also war das Test-data-Verzeichnis leer und Nextcloud
hat den Marker vermisst.

Fix: Marker vor dem Container-Start anlegen. Die anderen Tier-2-Tests
(Paperless, Mealie, Mail-Archiver) brauchten so etwas nicht, weil ihre
Apps keine entsprechende Validierungs-Pruefung haben.
2026-06-03 19:30:58 +02:00
Micha 53c34dca0e fix(restore): nextcloud-test disable check_data_directory_permissions
Erster Lauf am 2026-06-03 lief sauber durch alle Phasen (Borg-Extract,
pg_restore, Container alle gesund), schlug aber im HTTP-Smoke mit 503 fehl.
Ursache (aus dem preserved /mnt/user/backups/restore-lab/_failed/...):
- OC_Util.php:486 prueft die Permissions der data-Dir
- Skript hatte chmod -R a+rwX gesetzt (0777, letzte Stelle 7)
- Nextcloud versucht selbst chmod(0770) als www-data im Container
- Unraids shfs/FUSE lehnt chmod von Non-Root ab
- Nextcloud meldet "data directory readable by other people" -> 503

Fix: in der gepatchten config.php zusaetzlich
'check_data_directory_permissions' => false setzen. Nextcloud bietet
das in OC_Util:480 explizit als Opt-out an, fuer den isolierten Smoke
mit Wegwerf-Daten ist das vertretbar (kein Public, kein Traefik).
Produktiv bleibt der Check natuerlich an.

Patching erfolgt im bestehenden PHP-Injection-Block; idempotent (laeuft
keine Aenderung wenn beide Keys schon im config.php sind). Fallback-
sed-Pfad fuer Hosts ohne php ebenfalls erweitert.
2026-06-03 19:23:08 +02:00
Micha dd494046ce feat(restore): traefik restore smoke test
Borg-Extract von dynamic/ und letsencrypt/, Traefik startet mit
File-Provider gegen restaurierte Config, /ping Health antwortet.

Bewusst kein docker.sock (wuerde produktive Container discovern),
kein CF-Token (keine DNS-Challenge), keine produktiven Ports.
acme.json-Existenz und -Groesse wird geprueft, TLS-Validitaet nicht.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-06-03 14:42:56 +02:00
Micha a9b232195d feat(restore): mail-archiver restore smoke test
Borg-Extract der Data-Protection-Keys + pg_restore des 645M
mailarchiver-Dumps in isoliertes Test-Postgres + Container-Boot +
HTTP-Smoke. Wegwerf-DB-Connection und Auth-Password, kein produktiver
Stack-ENV, kein Authelia-ForwardAuth im Smoke.

Machbarkeit vorab verifiziert: Dump vorhanden, App-Image gepinnt,
Data-Protection-Keys im Borg, .NET-App hat kein shfs-chmod-Problem.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-06-03 14:01:47 +02:00
Micha 86435d4091 feat(restore): mealie restore test + freshness check negativ-test fix
Mealie-Restore-Test: Borg-Extract der App-Daten + pg_restore in
isoliertes Test-Postgres + Mealie-Boot + HTTP /api/app/about Smoke.
Machbarkeit vorab verifiziert (kein shfs-chmod-Problem, Mealie laeuft
als root und switcht intern auf PUID 99).

Freshness-Check: pg_header_ok() Docker-Fallback lieferte bei korruptem
Dump return 2 (unchecked) statt return 1 (invalid). Negativ-Test am
2026-06-03 bewiesen: korrupter mealie.dump wird jetzt als
DUMP_HEADER_INVALID erkannt (Critical, Exit 1).

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-06-03 13:49:51 +02:00
Micha 5e52316fab fix(restore): freshness check pg_header_ok returns 1 on corrupt dump
Negativ-Test 2026-06-03: korrupter mealie.dump wurde nicht erkannt,
weil der Docker-Fallback-Pfad nach gescheitertem pg_restore --list
zu return 2 (unchecked) durchfiel statt return 1 (invalid).

Fix: explizites if/else statt &&-Kette, damit fehlgeschlagene
Header-Validierung return 1 liefert und als DUMP_HEADER_INVALID
in den Critical-Zaehler geht.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-06-03 13:47:08 +02:00
Micha 8a4df239fa fix(restore): pin komodo test mongo to 8.0.23 matching production
Produktive Mongo ist 8.0.23, Test-Composes pinnten noch 7.0.32.
Eliminiert die Cross-Version-Warnung beim mongorestore.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-06-03 13:44:58 +02:00
Micha d1f9491b24 feat(restore): shared postgresql 18 cluster restore drill
Kompletter Restore-Drill fuer den Shared-PostgreSQL-18-Cluster:
globals (Rollen) + 5 per-DB Custom-Format-Dumps (paperless,
mailarchiver, authelia, nextcloud, mealie).

Bekannter mailarchiver-Bootstrap-Rollenkonflikt wird toleriert.
Authelia/Nextcloud/Mealie-Dumps als optional markiert.
Tabellen-Count pro DB als fachlicher Sanity-Check.

Machbarkeit vorab verifiziert: alle Dumps auf Host vorhanden,
pg_restore im postgres:18.4-Image verfuegbar, Postgres auf shfs
bewiesen durch bestehende Tests.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-06-03 13:02:16 +02:00
Micha 14de2f4801 docs(restore): komodo mongo restore successful, update matrix and backlog
Komodo-Mongo-Daten-Restore am 2026-06-03 erfolgreich: mongorestore
von komodo-mongo.archive.gz in Wegwerf-Mongo, 86904 Dokumente
(inkl. 32 Stack-Definitionen). Damit ist die kanonische Quelle fuer
KOMODO_*-Stack-ENV-Werte im DR-Fall als wiederherstellbar belegt.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-06-03 11:25:32 +02:00
Micha 90d1595285 fix(restore): komodo mongo restore own compose to avoid container name collision
Zweiter Lauf scheiterte mit Auth-Failure weil der Container-Name
restoretest-komodo-mongo mit dem alten Bootstrap-Test kollidierte
(stale Datadir auf shfs mit anderen Credentials).

Fix: eigenes Compose mit eigenem Container-Namen
(restoretest-komodo-mongorestore) und eigenem Project-Name, damit
keine Namenskollision mit dem bestehenden Bootstrap-Test entsteht.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-06-03 11:23:17 +02:00
Micha c1985e177b fix(restore): komodo mongorestore --noIndexRestore for auth compat
Erstlauf 2026-06-03: 86904 Dokumente (inkl. 32 Stack-Dokumente)
erfolgreich restored, aber Exit 1 weil der Index-Rebuild mit
"Command createIndexes requires authentication" scheitert (Test-User
hat keine dbAdmin-Rolle).

Fix: --noIndexRestore. Fuer den Smoke-Zweck (Stack-Definitionen lesbar,
KOMODO_*-ENV-Werte rekonstruierbar) reicht das. Indexe werden bei einem
echten Komodo-Restart ohnehin neu aufgebaut.

Nebenbefund: produktive Mongo ist 8.0.23, Test-Compose pinnt 7.0.32.
Cross-Version-Warning ist fuer den Lesetest harmlos, aber der
Bootstrap-Compose-Pin sollte separat auf 8.0 nachgezogen werden.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-06-03 11:20:53 +02:00
Micha a244f2d677 feat(restore): komodo mongo data restore test
Neuer Test: mongorestore von komodo-mongo.archive.gz in eine frische
Wegwerf-Mongo. Beweist, dass die Stack-Definitionen und damit die
KOMODO_*-Stack-ENV-Werte aus dem Dump rekonstruiert werden koennen
(kanonische Quelle laut docs/DISASTER_RECOVERY.md 6.2.1).

Machbarkeit vorab verifiziert: Dump 6.0M auf Host vorhanden,
mongorestore im mongo:7.0.32-Image verfuegbar, shfs-Write funktioniert.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-06-03 11:18:39 +02:00
Micha ef032f2dde docs(restore): document nextcloud shfs-chmod blocker
Nextcloud-Restore-Test Erstlauf 2026-06-03 nach 5 Iterationen als
strukturell blockiert durch Unraid shfs/FUSE eingestuft.

Ursache: Nextcloud 33 fuehrt zur Laufzeit chmod() auf Dateien unter
/var/www/html aus (OC_Util.php#486). Auf Unraids FUSE/shfs User Shares
ist chmod nicht moeglich - weder vom Host (chown ignoriert) noch aus dem
Container (Operation not permitted), auch nicht ohne no-new-privileges.
In Produktion funktioniert Nextcloud, weil die Daten dort auf einem
Cache-Drive (XFS/BTRFS direkt) statt ueber shfs liegen.

Scaffold (Skript + Compose) bleibt im Repo als Ausgangspunkt fuer die
Loesung. Drei Optionen dokumentiert:
a) Restore-Lab auf Cache-Drive
b) Docker-Volumes statt Bind-Mounts
c) tmpfs + rsync

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-06-03 11:14:39 +02:00
Micha 6fec64d0a1 fix(restore): nextcloud dump from host path instead of borg extract
Erstlauf 2026-06-03: borg_extract fuer den Nextcloud-Dump scheiterte
still (Pfad local/borg-dumps/latest/nextcloud.dump existiert im
Archiv moeglicherweise unter einem anderen Prefix). Der Dump liegt
taeglich frisch auf dem Host unter /mnt/user/backups/borg/dumps/latest/
und wird von dort in Borg gesichert - der Smoke-Wert ist identisch.

HTML (App-Code + config) kommt weiterhin aus dem Borg-Archiv.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-06-03 11:03:45 +02:00
Micha 5d1ae68705 fix(restore): nextcloud permissions on unraid shfs (no-new-privileges removal)
Zweiter Erstlauf 2026-06-03 scheiterte weiterhin mit 503, obwohl
config.php korrekt gepatcht war.

Ursache: Unraid's FUSE/shfs-Dateisystem auf User-Shares ignoriert
chown -R 33:33 still — Dateien bleiben bei sshd:sshd. Der
Nextcloud-Entrypoint versucht intern chmod/chown auf /var/www/html und
/var/www/html/data, was mit no-new-privileges:true blockiert wird.

Fix:
- no-new-privileges vom restoretest-nextcloud Container entfernt,
  damit der Entrypoint Rechte im Container selbst setzen kann
  (Test-Postgres und Test-Redis behalten no-new-privileges)
- Host-seitiger chown durch chmod a+rwX ersetzt (funktioniert auf shfs)
- Vertretbar im isolierten Smoke-Kontext (127.0.0.1, Wegwerf-Daten,
  kein Traefik)

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-06-03 10:55:56 +02:00
Micha 2913e1005f fix(restore): nextcloud chown 33:33 for www-data after borg extract
Erstlauf 2026-06-03 scheiterte mit dauerhaft 503. config.php-Patching
(Redis-Host + trusted_domains) war korrekt, aber Nextcloud konnte die
restaurierten Dateien nicht lesen/schreiben: "chmod(): Operation not
permitted at OC_Util.php#486".

Ursache: Borg-Extract ueber den borg-ui Container legt Dateien mit dem
borg-ui-User (sshd o.ae.) an. Nextcloud im Container laeuft als
www-data (UID 33). Mit no-new-privileges:true scheitert jeder chmod/
chown-Versuch im Container.

Fix: chown -R 33:33 auf html/ und data/ nach dem Extract, bevor der
Nextcloud-Container startet.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-06-03 10:44:12 +02:00
Micha 6f0e6f0d5a fix(restore): nextcloud config.php patching for redis host and trusted_domains
Erstlauf 2026-06-03 scheiterte mit 503: Redis-Host war noch auf dem
produktiven 'nextcloud-redis' statt 'restoretest-nextcloud-redis', und
trusted_domains enthielt kein 127.0.0.1 (Nextcloud blockt mit
"Access through untrusted domain").

Ursache: das sed-Pattern fuer Redis versuchte den ganzen Array-Block
einzeilig zu ersetzen, traf aber das PHP-Mehrzeilenformat nicht. Und
das trusted_domains-sed fand das Schliessmuster nicht zuverlaessig.

Fix:
- Redis-Host separat per sed patchen (nur den 'host'-Wert im Block)
- trusted_domains per PHP-CLI rewrite (robuster als sed auf PHP-Arrays)
- Fallback auf sed fuer Hosts ohne php

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-06-03 10:34:30 +02:00
Micha f473fbaa8b feat(restore): nextcloud restore smoke test scaffold
Nextcloud-Restore-Test nach dem Muster der anderen Restore-Smokes:
- Borg-Extract von html (App-Code + config.php) und nextcloud.dump
- pg_restore in isoliertes Test-Postgres (mit Retry-Schleife)
- config.php wird im Restore-Lab auf Test-DB-Credentials gepatcht
  (produktive Secrets werden nicht gemountet)
- Nextcloud startet gegen restaurierte Daten + Test-Redis
- Smoke prueft HTTP /status.php und occ status (maintenance mode)
- Produktive Nutzdaten unter /mnt/user/documents/nextcloud-data
  werden bewusst NICHT gemountet (zu gross fuer regelmaessigen Smoke)

Erster Lauf steht aus und braucht Operator-Freigabe auf dem Host.

Dispatcher und ntfy-Wrapper um Nextcloud erweitert.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-06-03 10:05:10 +02:00
Micha c922d1f241 docs(restore): finalize audit - handbook update, reifegrad matrix, backlog
Schliesst das Restore-Skills-Audit 2026-06-02/03 ab:

- RESTORE_HANDBOOK.md auf Stand 2026-06-03: alle 6 verifizierten Tests
  (Vaultwarden, Gitea, Paperless, Immich, Authelia, Komodo-Bootstrap)
  dokumentiert, Frequenz-Tabelle aktualisiert, Betriebsmodus auf V1+
  (mit ntfy), Schnellstart um Immich/Authelia/Komodo ergaenzt,
  Report-Aufbewahrungsregel dokumentiert, Ausbaustufen priorisiert.

- RESTORE_MATRIX.md: neue Sektion "Restore-Test-Reifegrad" mit
  Uebersichtstabelle (pro Dienst: Tier, letzter Test, Typ, naechster
  Lauf) und priorisierter Kandidatenliste fuer fehlende Tests.

- Gitea-Restore: SSH-Check im Report korrekt als "TCP connect only"
  benannt statt "SSH port open" (war Audit-Finding M3).

- AUDIT_2026-05-25_TODO.md: Restore-Audit-Backlog ergaenzt mit den
  verbleibenden 8 offenen Punkten (Nextcloud, Shared PG18, Komodo-Mongo,
  Mailarchiver, Mealie, Traefik, Negativ-Test, E2E-DR-Drill).

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-06-03 09:31:19 +02:00
Micha ba3ef8fcfc docs(restore): mark authelia smoke successful and schedule 2026-06-03 08:55:04 +02:00
Micha 52fc007123 fix(restore): authelia smoke without dump-restore, drop bogus env, disable ntp
Erstlauf 2026-06-03 hat einen by-design-Konflikt offengelegt: pg_restore des
produktiven postgresql17-authelia.dump in eine Test-Instanz mit Wegwerf
AUTHELIA_STORAGE_ENCRYPTION_KEY scheitert im Authelia-Startup-Check mit
"the configured encryption key does not appear to be valid for this database".
Productive Storage-Werte werden mit dem produktiven Key verschluesselt; ein
Wegwerf-Key kann sie nicht entschluesseln. Smoke ist deshalb explizit auf
Config-Restore + Boot reduziert, nicht Daten-Decrypt.

Zwei Nebenbefunde aus demselben Lauf:
- AUTHELIA__SERVER__ADDRESS (Doppel-Underscore) wurde von Authelia 4.39
  abgelehnt ("configuration environment variable not expected"). ENV
  entfernt; server.address kommt eh aus der generierten configuration.yml.
- ntp-Startup-Check schlug fehl ("Could not determine the clock offset
  ... lookup time.cloudflare.com on 127.0.0.1:53: server misbehaving"),
  weil das isolierte Test-Compose-Netz keinen DNS-Resolver fuer NTP hat.
  Neuer Test-Config-Block setzt ntp.disable_startup_check: true.

Doku nachgezogen (Plan + Runbook): Encryption-Key-Konflikt ist explizit
als "nicht Teil dieses Smokes" dokumentiert; Fehler-Matrix hat Eintraege
fuer Doppel-Underscore-ENV und NTP-Lookup.

Frische des produktiven authelia-Dumps wird unveraendert ueber
check-restore-freshness.sh ueberwacht; Daten-Decrypt-Drill ist eine eigene
DR-Aufgabe mit kontrollierter Schluessel-Verwendung.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-06-03 08:27:40 +02:00