diff --git a/HOMELAB_ARCHITECTURE_MASTER_V2.md b/HOMELAB_ARCHITECTURE_MASTER_V2.md index 3943268..6d40504 100644 --- a/HOMELAB_ARCHITECTURE_MASTER_V2.md +++ b/HOMELAB_ARCHITECTURE_MASTER_V2.md @@ -286,7 +286,7 @@ Legende Status: | `plex` | ✅ | `host` | Traefik via `plex.kaleschke.info` + Plex native Auth; LAN direkt `:32400` | Compose-Stack unter `host-services/plex/`; Host-Netz bleibt fuer Discovery / Plex GDM dokumentierte Ausnahme; Traefik routet per File-Provider-Ausnahme auf `http://192.168.178.58:32400`, weil Docker-Labels Host-Netz-Container aus Traefik heraus auf `127.0.0.1` routen wuerden; kein direkter WAN-Port 32400 und Plex Remote Access bleibt aus; Server geclaimt von `Xeridos`; Smart-TVs (Schlafzimmer, Wohnzimmer) ueber WLAN-LAN per mDNS | — | | `super-productivity` | ✅ vorbereitet | `frontend_net` | Traefik + Middleware | Persoenliche Task-PWA des Operators; Issues kommen aus Gitea `Micha/mails` via n8n-Mail-Workflow | Deploy + Webhook + DNS-Eintrag offen | | `n8n` | ✅ vorbereitet | `frontend_net` | Traefik, native Auth (keine pauschale Authelia) | Workflow-Automation; erster Workflow: GMX-Mail -> OpenAI-Extraktion -> Gitea-Issue in `Micha/mails`; `N8N_ENCRYPTION_KEY` ist Stack-ENV-Pflichtsecret | Deploy + Webhook + Owner-Setup offen | -| `dawarich_app` | ✅ | `frontend_net`, `backend_net` | Traefik via `dawarich.kaleschke.info`; UI hinter Authelia, API-Key-Pfade ohne ForwardAuth | Standort-Historie (Google-Timeline-Ersatz) mit eigener PostGIS-DB + Redis; `SELF_HOSTED=true`, `STORE_GEODATA=true`, keine externe Geocoding-Egress in der Compose gesetzt; Sidekiq-Worker im `backend_net` | Backup-Scope (`dawarich.dump` + Appdata) noch nicht verdrahtet, siehe `docs/MASTER_TODO.md` | +| `dawarich_app` | ✅ | `frontend_net`, `backend_net` | Traefik via `dawarich.kaleschke.info`; UI hinter Authelia, API-Key-Pfade ohne ForwardAuth | Standort-Historie (Google-Timeline-Ersatz) mit eigener PostGIS-DB + Redis; `SELF_HOSTED=true`, `STORE_GEODATA=true`, keine externe Geocoding-Egress in der Compose gesetzt; Sidekiq-Worker im `backend_net` | Backup-Scope (`dawarich.dump` + Appdata) repo-seitig verdrahtet; erster Host-Dump/Restore-Smoke offen | ### 7.5 Admin / Operations diff --git a/docs/EXTERNAL_DEPENDENCIES.md b/docs/EXTERNAL_DEPENDENCIES.md index dc6a15c..bf08276 100644 --- a/docs/EXTERNAL_DEPENDENCIES.md +++ b/docs/EXTERNAL_DEPENDENCIES.md @@ -18,14 +18,41 @@ Dieses Dokument beschreibt externe Anbieter und Konten, von denen Betrieb, Recov | GitHub Mirror | Externer Repo-Mirror `michaelkaleschke-spec/homelab-infra` (privat) | mittel/hoch | Gitea-Verlust abfederbar, aber Bare-Metal-Bootstrap braucht Read-Zugang (PAT oder SSH-Deploy-Key); ohne diesen ist der Mirror im DR nicht klonbar | GitHub-Konto; Push-PAT liegt in Gitea-Mirror-Settings; **Read-PAT/Deploy-Key fuer DR muss zusaetzlich offline im DR-Kit liegen** | Mirror-Status regelmaessig pruefen; lokalen Clone als zweite Kopie behalten; Read-PAT mit Scope `repo:read` separat erzeugen und im DR-Kit ablegen | | Tailscale | Remote-/Operator-Zugang | hoch | Remote-Zugriff erschwert, lokale Bedienung bleibt | Tailnet-Konto; Node `Kallilabcore`, IPv4 `100.80.98.33` | Break-glass per LAN und physischem Zugriff; Tailnet-Recovery-Codes sichern | | GMX SMTP | Authelia Notifier, Vaultwarden-Einladungen, Ops-Report-Mail | mittel | Mail-Notifier und Vaultwarden-Einladungen fallen aus; Login selbst nicht zwingend | GMX-Konto; SMTP-Secrets liegen hostseitig | ntfy/zweiter SMTP als Fallback pruefen | -| OpenAI API | Paperless-GPT LLM/Vision-OCR (Dokumenttext/-bilder) **und** n8n Mail->LLM->Gitea-Workflow (GMX-Mailinhalt bis ~8000 Zeichen) | mittel | Automatische Dokument-Titel/Tags/Korrespondenten/LLM-OCR und die n8n-Mail-Extraktion fallen aus; Paperless und n8n laufen sonst weiter | je eigener OpenAI-API-Key ausserhalb Repo (Paperless-GPT Stack-ENV; n8n Credentials Store) | Keys in Vaultwarden/Komodo sichern, bei Offenlegung rotieren; Kosten/Usage im OpenAI-Projekt beobachten. **Datenklasse/Retention/Loeschpfad je Egress-Pfad noch offen** (`docs/HOMELAB_REVIEW_MATRIX.md` Domaene 12, `docs/MASTER_TODO.md`) | +| OpenAI API | Paperless-GPT LLM/Vision-OCR (Dokumenttext/-bilder) **und** n8n Mail->LLM->Gitea-Workflow (GMX-Mailinhalt bis ~8000 Zeichen) | mittel | Automatische Dokument-Titel/Tags/Korrespondenten/LLM-OCR und die n8n-Mail-Extraktion fallen aus; Paperless und n8n laufen sonst weiter | je eigener OpenAI-API-Key ausserhalb Repo (Paperless-GPT Stack-ENV; n8n Credentials Store) | Keys in Vaultwarden/Komodo sichern, bei Offenlegung rotieren; Kosten/Usage im OpenAI-Projekt beobachten. Datenklasse/Retention/Loeschpfad stehen unten in "Data Privacy / Egress-Kontrollen"; konkrete OpenAI-Projekt-Settings bleiben live zu pruefen | | Let's Encrypt | TLS-Zertifikate | hoch | Cert-Erneuerung faellt aus | automatisch via Traefik und Cloudflare DNS-Challenge | Cert-Expiry Alert einrichten; Cloudflare-Token und Traefik-Storage pruefen | | Container Registries | Image Pulls von Docker Hub, GHCR, LSCR, Gitea Registry u. a. | mittel | Redeploy/Update blockiert | ueberwiegend oeffentlich; keine produktiven Registry-Tokens im Repo | Gepinnte Digests und lokale Runtime helfen kurzfristig; Updates geplant und einzeln deployen | | Plex Konto | Plex native Auth, Claim und Client-Zugriff ueber `plex.kaleschke.info` | mittel | Plex-Web/App-Login und Clients koennen ausfallen; LAN-Medienpfade bleiben lokal | Plex-Konto ausserhalb Repo; `PLEX_CLAIM` nur fuer Setup | Plex Remote Access bleibt aus; externer Zugriff laeuft ueber Traefik/443. Konto-Recovery separat sichern | -| Mobile Push | ntfy (self-hosted) und ggf. mobile Plattform-Pushes; Egress = Alert-Payloads/Topic-Namen an Upstream-Push | niedrig/mittel | Alerts erreichen Mobilgeraete ggf. nicht | App-/Device-seitig | Kritische Alerts zusaetzlich in Grafana/Glance sichtbar halten; Payloads/Topics ohne PII/Pfade/Secrets halten (Naming-Regel offen, `docs/HOMELAB_REVIEW_MATRIX.md` Domaene 12) | +| Mobile Push | ntfy (self-hosted) und ggf. mobile Plattform-Pushes; Egress = Alert-Payloads/Topic-Namen an Upstream-Push | niedrig/mittel | Alerts erreichen Mobilgeraete ggf. nicht | App-/Device-seitig | Kritische Alerts zusaetzlich in Grafana/Glance sichtbar halten; Payloads/Topics ohne PII/Pfade/Secrets halten; konkrete Live-Namen periodisch screenen | | healthchecks.io (Cloud) | Externer Dead-Man's-Switch fuer Host-down-/Backup-Stillstand: Borg-Pre-Hook, baerchen-Nearline-Pull, geplanter Monitoring-Watchdog (#8); interne Job-Checks laufen self-hosted | mittel | Stiller Ausfall von Borg-/Nearline-Lauf wird nicht extern sichtbar; Backups selbst laufen weiter | healthchecks.io-Account; Ping-/Capability-URLs als Host-Secrets (`docs/SECRETS_MAP.md`) | Datenklasse = operative Metadaten (Check-Name/Timing); Naming ohne PII/Pfade/Secrets. Skripte sind endpoint-agnostisch -> bei Bedarf auf self-hosted `hc.kaleschke.info` umstellbar. Bewusste Architektur (DECISIONS 2026-06-23): Host-down-Waechter bleiben extern | | Operator-DR-Workstation | Bare-Metal-Recovery-Arbeitsplatz (Gaming-PC Windows, lokaler Repo-Clone `G:\Gitea_Clone\homelab-infra`) | kritisch | Ohne Workstation kein Borg-Extract, kein Hetzner-Zugriff, kein Repo-Bootstrap; der Unraid-Host ist im Bare-Metal-Fall gerade weg | Operator-PC, WSL2 + Borg-Client, SSH-Key fuer Hetzner Storage Box, Offline-Kopie der Borg-Passphrase | Setup als bewusste DR-Vorbedingung pflegen (siehe Abschnitt "DR-Workstation Bare-Metal-Kit") | +## Data Privacy / Egress-Kontrollen + +Stand: 2026-06-26, gegen Repo und offizielle Anbieter-Doku eingeordnet. Diese +Tabelle beschreibt erlaubte externe Pfade und die erwartete Datenhygiene. Sie +ersetzt keine Live-Kontrolle der konkreten Account-Schalter. + +| Egress-Pfad | Repo-Beleg | Datenklasse | Token / Account | Retention beim Dritten | Loesch-/Export-/Opt-out-Pfad | Naheliegende Optimierung | +|---|---|---|---|---|---|---| +| Paperless-GPT -> OpenAI API | `apps/paperless-gpt/docker-compose.yml`, `docs/SERVICE_CATALOG.md` | Dokumenttext, Dokumentbilder, Metadaten, ggf. personenbezogene Inhalte | `OPENAI_API_KEY` als Stack-ENV/Host-Secret | OpenAI API: Standard-Retention bis zu 30 Tage fuer API Inputs/Outputs; Responses-API Application State standardmaessig 30 Tage; API-Daten werden laut OpenAI standardmaessig nicht zum Training genutzt, sofern nicht explizit opt-in | App deaktivieren oder Provider wechseln; API-Key rotieren/loeschen; OpenAI-Projekt/Logs pruefen; ZDR nur fuer geeignete Accounts/Endpoints beantragen; bei Responses-API `store=false`/Feature-Nutzung bewusst setzen, falls die App dies unterstuetzt | Nur Allowlist/Tags an Paperless-GPT senden; keine sensiblen Dokumenttypen ohne bewusste Freigabe | +| n8n Mail -> OpenAI -> Gitea | n8n-Workflow-JSONs und `docs/SERVICE_CATALOG.md`; Live-Aktivitaet separat pruefen | GMX-Mailinhalt bis Workflow-Limit, extrahierte Aufgaben/Metadaten | n8n Credential Store: GMX/OpenAI/Gitea-Credentials; `N8N_ENCRYPTION_KEY` fuer Restore noetig | OpenAI wie oben; Gitea speichert erzeugte Issues lokal und ggf. im GitHub-Mirror, falls dort committed/gespiegelt | Workflow deaktivieren; Credentials rotieren/loeschen; n8n Credential-Export nur verschluesselt behandeln; Gitea-Issues loeschen/exportieren | Workflow standardmaessig inaktiv halten oder Mail-Absender/Ordner allowlisten; Prompts auf minimale Datenweitergabe kuerzen | +| GMX IMAP/SMTP | Authelia/Vaultwarden/Mail-Archiver/n8n Mailpfade in Service-Doku | E-Mail-Inhalte, Absender/Empfaenger, SMTP-/IMAP-Metadaten | GMX-Konto + Host-Secrets | GMX: Content-/Nutzungsdaten werden nach 180 Tagen Inaktivitaet geloescht; bei Kuendigung werden Userdaten geloescht, sofern keine gesetzlichen Aufbewahrungsfristen greifen | GMX Account verwalten/kuendigen; Mails via IMAP/POP3/Export sichern; personenbezogene Accountdaten im Kundencenter exportieren | n8n/Mail-Archiver nur mit dediziertem Postfach oder dedizierten Ordnern betreiben; keine privaten Vollpostfaecher ungefiltert an LLM-Workflows geben | +| healthchecks.io Cloud | Externe Borg-/Nearline-/Host-down-Waechter in `docs/MASTER_TODO.md`, `ops/h-drive-nearline/README.md` | Checknamen, Ping-Zeitpunkte, IP-/Log-Metadaten, Capability-URLs | healthchecks.io-Account; Ping-URLs als Host-Secrets | Healthchecks.io: inaktive Accounts werden nach Hinweis geschlossen; Daten koennen nach Loeschung/Account-Schliessung bis zu 2 Monate in DB-Backups wiederherstellbar sein | Checks/Account loeschen; Capability-URLs rotieren; Pfad bei Bedarf auf self-hosted `hc.kaleschke.info` umstellen | Checknamen abstrakt halten, keine Hostpfade/Personennamen/Secrets im Namen oder Payload | +| ntfy / Mobile Push | `ops/ntfy`, Monitoring/Alertmanager-Bridge, Service-Doku | Alert-Payloads, Topicnamen, ggf. operative Metadaten | ntfy-User/Topic/Device; mobile Push ueber App-Plattform | ntfy: Nachrichten werden standardmaessig 12h gecached, Attachments 3h; bei Play/App-Store-Versionen koennen Metadaten/Inhalte ueber FCM laufen | Payload loeschen/Cache abwarten; mobile Push abmelden; F-Droid-App oder Self-host/Instant-Delivery nutzen, wenn FCM vermieden werden soll | Payloads weiter minimieren: keine PII, keine Pfade, keine Secrets, keine aussagekraeftigen internen Hostnamen | +| Borg -> Hetzner Storage Box | Borg-Scope, `ops/borg-ui/BACKUP_SCOPE.md`, `docs/RESTORE_MATRIX.md` | Verschluesselte Offsite-Kopie aller Borg-Quellen inkl. personenbezogener Appdaten und Secrets | Hetzner-Konto, Storage-Box-SSH-Key, Borg-Passphrase | Retention liegt primaer in Borg-Retention; Hetzner verarbeitet als Dienstleister nach DPA/Produktstandort, Non-Cloud-Produkte laut Hetzner innerhalb EU | Borg prune/delete/compact; Storage-Box-Daten loeschen/Account kuendigen; Crypto-Shred durch Vernichtung der Borg-Passphrase/Keys als letzte Kontrolle | DPA im Hetzner-Account aktuell halten; Restore und Loesch-/Prune-Lauf periodisch belegen | +| GitHub Mirror | `docs/EXTERNAL_DEPENDENCIES.md`, Gitea-Push-Mirror | Repo-Inhalt: Infrastruktur-Code/Doku, keine Secret-Werte; ggf. interne Host-/Pfadnamen | GitHub-Konto; Push-PAT in Gitea; DR-Read-Deploy-Key offline | GitHub behandelt private Repos als vertraulich; konkrete Repo-/Account-Loeschung ueber GitHub-Settings, Actions-Artefakt-Retention separat falls genutzt | Mirror deaktivieren/Repo loeschen; PAT/Deploy-Key widerrufen; Audit-/Access-Listen exportieren, soweit Account/Plan es erlaubt | Mirror weiter privat halten; Branch-/Token-Inventar live pruefen; Secret-Scanner gegen History laufen lassen | + +Quellen fuer Anbieter-Regeln: + +- OpenAI API Data Controls: `https://developers.openai.com/api/docs/guides/your-data` +- OpenAI Enterprise Privacy/API Retention: `https://openai.com/enterprise-privacy/` +- GMX Privacy/Data Collection: `https://www.gmx.com/company/privacypolicy/`, `https://www.gmx.com/company/data-collection/mail-client/` +- GMX Export: `https://support.gmx.com/account/managing/export-data.html` +- Healthchecks.io Privacy: `https://healthchecks.io/privacy/` +- ntfy Privacy: `https://docs.ntfy.sh/privacy/` +- Hetzner DPA/Data Protection: `https://docs.hetzner.com/general/company-and-policy/data-protection-at-hetzner/` +- GitHub private repo confidentiality/deletion/export: `https://docs.github.com/site-policy/github-terms/github-terms-of-service` + ## Kritische Secrets ausserhalb des Repos Authoritativ ist `docs/SECRETS_MAP.md`. Diese Liste markiert nur externe Abhaengigkeiten. diff --git a/docs/HOMELAB_REVIEW_MATRIX.md b/docs/HOMELAB_REVIEW_MATRIX.md index 6c20f28..5ac562b 100644 --- a/docs/HOMELAB_REVIEW_MATRIX.md +++ b/docs/HOMELAB_REVIEW_MATRIX.md @@ -36,7 +36,7 @@ Exposure, Identity, Backup-Restore, Data Privacy/Egress, GitOps-Control-Plane. | 9 | Observability-Luecken | ? | - | Alert-on-Absence/Dead-Man-Switch belegt, weiter beweisen | | 10 | Exit & Portierbarkeit | ? | - | | | 11 | Update- & Patch-Hygiene | ? | teilweise | Renovate belegt; Host/Engine/Auth-Layer separat betrachten | -| 12 | Data Privacy / Egress / Datenklassifikation | 2 | 2026-06-26 | OpenAI-/Mail-/Healthchecks-/ntfy-/Borg-Egress kartiert; Retention/Loeschpfade und Dawarich-Abdeckung offen | +| 12 | Data Privacy / Egress / Datenklassifikation | 3 | 2026-06-26 | OpenAI-/Mail-/Healthchecks-/ntfy-/Borg-Egress inkl. Datenklasse/Retention/Loeschpfad dokumentiert; Live-Account-Pruefungen und Dawarich Host-Dump/Restore-Smoke offen | | 13 | GitOps-Control-Plane & Drift | 3 | 2026-06-26 | Repo-Soll stark; Live-Abgleich fuer Komodo/Runtime/Traefik/Authelia offen; Self-Stack und manuelle Sync-Ausnahmen sind hoechster Hebel | ## 12 - Data Privacy / Egress / Datenklassifikation @@ -68,23 +68,24 @@ rg -n "Dawarich|dawarich|OpenAI|healthchecks.io|ntfy.sh|GitHub Mirror|Hetzner|GM | Pfad | Belegt | Risiko | |---|---|---| -| Paperless-GPT -> OpenAI | `apps/paperless-gpt/docker-compose.yml` nutzt OpenAI fuer LLM/Vision OCR | Dokumenttext/Bilder/Metadaten koennen extern verarbeitet werden; Retention/Loeschpfad nicht im Repo dokumentiert | +| Paperless-GPT -> OpenAI | `apps/paperless-gpt/docker-compose.yml` nutzt OpenAI fuer LLM/Vision OCR; Provider-Regeln in `docs/EXTERNAL_DEPENDENCIES.md` | Dokumenttext/Bilder/Metadaten koennen extern verarbeitet werden; Live-Account-Settings/ZDR/`store`-Verhalten offen | | n8n Mail -> OpenAI -> Gitea | Workflow-JSON im Repo, Export war inaktiv; live nicht verifiziert | Mailinhalt bis 8000 Zeichen kann an OpenAI gehen; Live-Status und Retention offen | -| GMX IMAP/SMTP | n8n, Vaultwarden, Authelia/Mailpfade dokumentiert | Mailprovider-Retention und Scope nicht als Matrix erfasst | +| GMX IMAP/SMTP | n8n, Vaultwarden, Authelia/Mailpfade dokumentiert; Retention/Exportpfad in `docs/EXTERNAL_DEPENDENCIES.md` | Vollpostfach-Egress waere hochriskant; dedizierte Ordner/Postfaecher bevorzugen | | Borg -> Hetzner | `EXTERNAL_DEPENDENCIES.md`, Borg-Scope | Verschluesselte Offsite-Kopie vieler Datenklassen; Immutability/Retention weiter beweisen | -| ntfy/Healthchecks | self-hosted + externe Cloud-Waechter dokumentiert | Alert-/Checknamen koennen operative Metadaten leaken | -| Dawarich | Service Catalog + Compose vorhanden | Standortdaten sind hochsensibel; Architecture/Auth/Restore/Backup-Abdeckung war nicht konsistent sichtbar | +| ntfy/Healthchecks | self-hosted + externe Cloud-Waechter dokumentiert; Retention/Loeschpfade in `docs/EXTERNAL_DEPENDENCIES.md` | Alert-/Checknamen koennen operative Metadaten leaken; Live-Namen screenen | +| Dawarich | Service Catalog + Compose + Borg-Scope vorhanden | Standortdaten sind hochsensibel; repo-seitig jetzt `dawarich.dump` + `/local/appdata/dawarich`, erster Host-Dump/Restore-Smoke offen | **Naechste Optimierungen** -- OpenAI-Retention, Datenkontrollen, Loesch-/Exportpfad und erlaubte Datenklassen - fuer Paperless-GPT und n8n dokumentieren. +- OpenAI-Projekt live pruefen: ZDR/Retention-Status, Logs, verwendete API-Features + und ob Paperless-GPT/n8n `store=false` oder vergleichbare Nicht-Speicherpfade + unterstuetzen. - Paperless-GPT nur ueber Tag-/Allowlist oder klare Ausschlussregel auf Dokumente anwenden. -- Dawarich in Architecture/Auth/Restore/Backup-Scope konsistent eintragen oder - bewusst als Ausnahme dokumentieren. -- Healthchecks/ntfy-Naming-Regel: keine PII, keine Pfade, keine Secrets, keine - aussagekraeftigen internen Namen in Payloads. +- Dawarich auf Unraid belegen: `pre-backup-dumps.sh` laufen lassen, + `dawarich.dump`-Frische pruefen und isolierten PostGIS-17-Restore-Smoke planen. +- Healthchecks/ntfy live screenen: keine PII, keine Pfade, keine Secrets, keine + aussagekraeftigen internen Namen in Payloads oder Checknamen. ## 13 - GitOps-Control-Plane & Drift diff --git a/docs/MASTER_TODO.md b/docs/MASTER_TODO.md index ee15814..8b323d0 100644 --- a/docs/MASTER_TODO.md +++ b/docs/MASTER_TODO.md @@ -25,7 +25,7 @@ Host-Reports (`/mnt/user/backups/restore-reports/`) und in der Git-Historie. | Restore-Test Tailscale | Operator | State-Validierung + Reconnect nur auf Wegwerf-Host/VM, danach Geraet in Tailscale-Admin entfernen | `ops/restore-tests/tailscale-runbook.md` | | Authelia OIDC fuer Apps | Operator/Codex | Live: Grafana + Mealie login-verifiziert; Paperless Secret verdrahtet und Service-Smoke am 2026-06-17 gruen, finaler Browser-Login mit Operator-Account offen. Immich + Nextcloud bewusst geparkt bis Family-Onboarding (siehe `docs/DECISIONS.md` 2026-06-06) | `docs/AUTHELIA_OIDC_PLAN.md` | | Home Assistant Tibber | Operator/Codex | Tibber per HA-UI-Config-Flow verbinden. Danach Energy-Dashboard um echte Kosten/Preisquelle ergaenzen; SolarEdge-PV, Netz und Speicher sind bereits konfiguriert und validiert | `docs/runbooks/smart-home-bootstrap.md`, `docs/DECISIONS.md` | -| Review-Follow-up Data Privacy/Egress | Operator/Codex | (1) Datenklasse + Retention/Loeschpfad je externem Egress-Pfad dokumentieren (OpenAI fuer Paperless-GPT+n8n, GMX, healthchecks.io, ntfy-Upstream, Hetzner, GitHub-Mirror). (2) **Dawarich-Backup-Scope schliessen** (Standortdaten aktuell nicht DR-gesichert): `dawarich.dump` in `pre-backup-dumps.sh`, Pfad in Quellliste + Borg-UI-Mount + `BACKUP_SCOPE.md`, danach `RESTORE_MATRIX.md` Tier-2-Zeile + Reifegrad. Dawarich in Architecture §4.2/§7.4/§10 + `AUTH_MATRIX.md` ist am 2026-06-26 angeglichen. | `docs/HOMELAB_REVIEW_MATRIX.md` Domaene 12 | +| Review-Follow-up Data Privacy/Egress | Operator/Codex | Datenklasse + Retention/Loeschpfad je externem Egress-Pfad ist in `docs/EXTERNAL_DEPENDENCIES.md` dokumentiert. Offen bleiben Live-Belege: OpenAI-Projekt-Settings/ZDR bzw. `store`-Verhalten fuer Paperless-GPT+n8n pruefen, n8n-Workflow-Aktivitaet live bestaetigen, Healthchecks-/ntfy-Namen auf PII/Pfade/Secrets screenen. Dawarich-Backup-Scope ist repo-seitig verdrahtet (`dawarich.dump` + `/local/appdata/dawarich`); naechster Host-Schritt: auf Unraid `pre-backup-dumps.sh` laufen lassen, `dawarich.dump`-Frische pruefen und isolierten Restore-Smoke terminieren. | `docs/HOMELAB_REVIEW_MATRIX.md` Domaene 12 | | Review-Follow-up GitOps-Control-Plane | Operator/Codex | Auf Unraid `compose-runtime-drift.sh`, `komodo-stack-hygiene.sh`, `authelia-diff.sh` und `traefik-dynamic-diff.sh` laufen lassen; danach Branch-Protection/Hooks/PATs in Gitea live inventarisieren | `docs/HOMELAB_REVIEW_MATRIX.md` Domaene 13 | | Nearline-Pull Dead-Man's-Switch | Operator | **S4U-Root-Cause 2026-06-21 behoben + verifiziert:** Task `KalliLab H Drive Nearline Pull` von S4U auf LogonType `Interactive` ("Nur wenn Benutzer angemeldet") umgestellt (kein Passwort noetig, da `michi` Dauer-Konsolen-User) -> per Planer mit `0x0` bestaetigt. Spiegel frisch, Exit-Code-Leak gefixt, Heartbeat-Pings gepusht. **Verbleibt (optional, niedrige Dringlichkeit):** je einen Healthchecks-Check anlegen + Capability-URL hinterlegen (baerchen ENV `HEALTHCHECKS_NEARLINE_URL`/Datei; Unraid `/mnt/user/appdata/secrets/healthchecks_borg_url`) | `ops/h-drive-nearline/README.md` | | Healthchecks self-hosted (interne Jobs) | Operator | **Live seit 2026-06-23** auf `https://hc.kaleschke.info` (Komodo-Stack-ID `6a3acf2ca7867a4fbab9bfc1`, beide Container healthy, Superuser angelegt). Gitea->Komodo-Webhook seit 2026-06-23 aktiv. Projekt `KalliLab CORE` + ntfy-Integration (`homelab-alerts`). **7 interne Jobs verdrahtet + verifiziert (Status `up`):** `posture-check` (stuendlich), `cert-token-check`/`compose-runtime-drift`/`daily-status-report` (taeglich), `komodo-stack-hygiene` (woechentlich), `renovate`/`gitea-bundle-mirror` (alle 6h) - je endpoint-agnostischer Ping via EXIT-Trap, Capability-URL als Host-Secret `healthchecks__url`. **Bewusst NICHT self-hosted:** Borg-Pre-Hook + Nearline bleiben healthchecks.io-Cloud (Host-down-Erkennung); guarded Restore-Jobs (Vaultwarden/Gitea/Paperless/Authelia/Immich) sind wegen Shell-Guard nicht je Cron-Trigger monitorbar. **Verbleibt nur noch optional:** die 2 externen Cloud-Checks scharfschalten. | `ops/healthchecks/README.md` | diff --git a/docs/RESTORE_MATRIX.md b/docs/RESTORE_MATRIX.md index 2aa74da..02a7ffe 100644 --- a/docs/RESTORE_MATRIX.md +++ b/docs/RESTORE_MATRIX.md @@ -61,6 +61,7 @@ Sie ist die fachliche Ergaenzung zu `docs/DISASTER_RECOVERY.md`. | ntfy | Borg / Share | `/mnt/user/appdata/ntfy` | keine | keine besonderen Secret-Dateien dokumentiert | Traefik | UI und Push-Endpunkt erreichbar | | Paperless-GPT | Borg / Share | `/mnt/user/appdata/paperless-gpt` | keine eigene DB | `PAPERLESS_API_TOKEN`, `OPENAI_API_KEY` | Traefik, Paperless, OpenAI API | UI startet, Konfiguration vorhanden; LLM-Provider zeigt `openai` / `gpt-5.4-mini` | | n8n | Borg + Dump | `/mnt/user/appdata/n8n/data` | `n8n.sqlite.dump`; Credentials sind nur mit dem passenden `N8N_ENCRYPTION_KEY` entschluesselbar | `N8N_ENCRYPTION_KEY`, GMX/OpenAI/Gitea-Credentials in n8n | Traefik, GMX IMAP, OpenAI API, Gitea API | UI startet, Owner-Login funktioniert, kritischer Mail->LLM->Gitea-Workflow ist vorhanden und deaktiviert/aktiv wie vor Restore | +| Dawarich | Borg + Dump | `/mnt/user/appdata/dawarich` | `dawarich.dump` aus `dawarich_db` (PostGIS 17) | `dawarich_postgres_password.txt`, `dawarich_redis_password.txt`, `dawarich_secret_key_base.txt` | `dawarich_db`, `dawarich_redis`, Traefik, Authelia; optional Home Assistant Push | UI startet, `/api/v1/health` meldet ok, Standortpunkte/Tracks sind sichtbar; optional Test-Push an OwnTracks-kompatiblen API-Key-Endpunkt | | Home Assistant | Borg + HA-native Backups + Fachrepo | `/mnt/user/appdata/homeassistant` inkl. `.storage`, `secrets.yaml`, `trusted_proxies.yaml`, `custom_components` (HACS, `solaredge_modbus_multi`); Fach-YAML aus `/mnt/user/services/smart-home-kalli/home-assistant` | HA-native Backup-Artefakte unter `/mnt/user/appdata/homeassistant/backups`; erstes Artefakt 2026-06-13 erzeugt und tar-lesbar (`backup.json`, `homeassistant.tar.gz`); Backup nach SolarEdge-Integration: `Custom_backup_2026.6.1_2026-06-13_14.59_48645373.tar`; Backup nach Energy-Dashboard-Konfiguration: `Custom_backup_2026.6.1_2026-06-13_15.59_25670583.tar`; keine externe DB in Phase 1 | HA-Secrets in `secrets.yaml`, Integrations-Tokens in `.storage`, MQTT-Credentials, Agent-API-Tokens als Host-Secrets `ha_token_codex`/`ha_token_claude` (nur mit erhaltenem `.storage`-Auth-State nutzbar), spaeter Tibber/InfluxDB-Tokens | Traefik, `frontend_net`, `smarthome_net`, Mosquitto, Fachrepo-Clone, SolarEdge-Wechselrichter `192.168.178.111:1502` | Restore-Test am 2026-06-13 erfolgreich: HA-native Backup + Mosquitto-Appdata + Fachrepo-Clone isoliert gestartet, HA HTTP/API/check_config gruen; produktiv danach HA-MQTT-Config-Entry `smarthome-mosquitto` geladen, SolarEdge Local `solaredge_modbus_multi` loaded mit 68 Entitaeten und Energy Dashboard fuer Netz/PV/Speicher per `energy/validate` ohne Issues; Report `/mnt/user/backups/restore-reports/homeassistant-2026-06-13.md` | | Smart-Home MQTT / Mosquitto | Borg / Share | `/mnt/user/appdata/mosquitto/config`, `/mnt/user/appdata/mosquitto/data`, `/mnt/user/appdata/mosquitto/log` | Mosquitto persistiert retained messages/subscriptions dateibasiert | `passwordfile`, `aclfile`, spaeter per-Device-User | `smarthome_net`, Home Assistant, spaeter ESPHome/Zigbee2MQTT | Restore-Test am 2026-06-13 erfolgreich: authentifizierter Publish/Subscribe-Smoke mit `homeassistant`-User und retained Topic nach Broker-Restart gruen; produktiv verbindet sich HA als User `homeassistant` | | Smart-Home Fachrepo | Gitea + Borg-Repo-Clone | `/mnt/user/services/smart-home-kalli` | keine | keine echten Secrets im Repo; `secrets-template/` nur Beispiele | Gitea, Home Assistant Mounts | `git status` sauber, HA liest `configuration.yaml` und `packages/` aus dem Clone | @@ -106,6 +107,7 @@ Aktuell relevante Dump-Artefakte unter `/mnt/user/backups/borg/dumps/latest`: - `borg-ui.sqlite` - `grafana.sqlite` - `n8n.sqlite.dump` +- `dawarich.dump` - `unraid-flash-config.tar.gz` plus `unraid-flash-config.tar.gz.sha256` und Manifest - Monitoring-Stack: keine verpflichtenden Dump-Artefakte; Prometheus/Loki/Grafana named volumes sind Diagnose-/Dashboard-Zustand, keine primaere Restore-Quelle. - `komodo-mongo.archive.gz` (noch gesondert verifizieren) @@ -167,6 +169,7 @@ Stand 2026-06-06. Pro Dienst auf einen Blick: Wurde der Restore schon einmal rea | Borg UI | 3 | - | rebuildbar | - | | Filebrowser | 3 | - | rebuildbar | - | | baerchen Windows Image | Workstation | 2026-06-06 | Full-Backup geschrieben; Recovery-USB-Boot, SMB-Mount und Restore-Point-Sichtpruefung erfolgreich; vor echtem Restore abgebrochen | nach Image-Aenderungen oder quartalsweise | +| Dawarich | 2 | - | PostGIS-Dump + Appdata verdrahtet, Restore-Smoke offen | erster Host-Dump und isolierter Restore-Smoke nach naechstem Borg-Lauf | | Home Assistant + Mosquitto | 2 | 2026-06-13 | HA-native Backup + Mosquitto-Appdata + Fachrepo-Clone, isolierte Testcontainer, HA HTTP/API/check_config, MQTT Publish/Subscribe + retained Topic nach Broker-Restart | vor groesseren Smart-Home-Aenderungen oder nach relevanten HA/Mosquitto-Architekturaenderungen | --- diff --git a/docs/SECRETS_MAP.md b/docs/SECRETS_MAP.md index 71b5c3e..5f84a88 100644 --- a/docs/SECRETS_MAP.md +++ b/docs/SECRETS_MAP.md @@ -70,7 +70,7 @@ Dieses Dokument listet sensible Daten, deren Ablageorte und die vorgesehene Einb | Mealie OIDC (Authelia) | Client Secret | Stack-ENV `${MEALIE_OIDC_CLIENT_SECRET}` in `/mnt/user/services/stacks/mealie/apps/mealie/.env` (Komodo-Stack-ENV); pbkdf2-Hash im Authelia-Host-Config-Client `mealie` (kein Wert im Repo) | aktiv (2026-06-06) | | Dawarich | DB Password | `/mnt/user/appdata/secrets/dawarich_postgres_password.txt` -> Docker Secret `/run/secrets/dawarich_postgres_password`; Postgres nutzt `POSTGRES_PASSWORD_FILE`, App/Sidekiq lesen per Entrypoint-Export | aktiv | | Dawarich | Redis Password | `/mnt/user/appdata/secrets/dawarich_redis_password.txt` -> Docker Secret `/run/secrets/dawarich_redis_password`; Redis `--requirepass`, App/Sidekiq `REDIS_URL` | aktiv | -| Dawarich | Rails `SECRET_KEY_BASE` | `/mnt/user/appdata/secrets/dawarich_secret_key_base.txt` -> Docker Secret `/run/secrets/dawarich_secret_key_base` | geplant | +| Dawarich | Rails `SECRET_KEY_BASE` | `/mnt/user/appdata/secrets/dawarich_secret_key_base.txt` -> Docker Secret `/run/secrets/dawarich_secret_key_base` | aktiv laut Compose; Host-Datei bei naechstem Unraid-Check bestaetigen | | Dawarich Metrics | Basic-Auth Password | `/mnt/user/appdata/secrets/dawarich_metrics_password.txt` -> Docker Secret `/run/secrets/dawarich_metrics_password`; Prometheus `password_file` | aktiv | | Grafana -> Dawarich | Read-only DB Password | `/mnt/user/appdata/secrets/dawarich_grafana_ro_password.txt` -> Docker Secret `/run/secrets/dawarich_grafana_ro_password`; Grafana-Env `DAWARICH_GRAFANA_RO_PASSWORD` | aktiv | | Renovate Bot | Gitea Service-Account PAT | `/mnt/user/appdata/secrets/renovate_token.txt` -> Host-Datei (chmod 600), gelesen von `ops/renovate/run-renovate.sh` und an Renovate-Container als `RENOVATE_TOKEN` weitergegeben | aktiv nach Operator-Setup (siehe `docs/RENOVATE.md`) | diff --git a/docs/SERVICE_CATALOG.md b/docs/SERVICE_CATALOG.md index 7aef108..47a613b 100644 --- a/docs/SERVICE_CATALOG.md +++ b/docs/SERVICE_CATALOG.md @@ -43,8 +43,8 @@ Secret-Werte sind nicht enthalten. Es werden nur Secret-Namen, Env-Key-Namen und | `immich_machine_learning` | Immich ML | `apps/immich/docker-compose.yml` | intern | `immich_default`, `immich_egress` | `model-cache` | rebuildbar | nein | keine Traefik-Route; `immich_egress` (nicht-internal) nur fuer Modell-Download zu huggingface, sonst scheitert Smart Search/Gesichtserkennung an DNS | | `mealie` | Rezeptverwaltung | `apps/mealie/docker-compose.yml` | `https://mealie.kaleschke.info` | `mealie-postgres`, Traefik | `/mnt/user/appdata/mealie/data` | Tier 2, Borg + `mealie.dump` | ja | App + DB in internem Netz getrennt | | `mealie-postgres` | Mealie-Datenbank | `apps/mealie/docker-compose.yml` | intern | `mealie_internal` | `/mnt/user/appdata/mealie/postgres18`, archivierter Rollback-Altstand `/mnt/user/appdata/_archive/pg18-immich-rollback-volumes-20260602/mealie-postgres17`, `mealie_postgres_password.txt` | Dump `mealie.dump` | nein | interne DB; PostgreSQL 18 | -| `dawarich_app` | Standort-Historie / Google-Timeline-Ersatz | `apps/dawarich/docker-compose.yml` | `https://dawarich.kaleschke.info` | eigene PostGIS-DB, eigene Redis, Traefik + Authelia, optional Home Assistant Push | `/mnt/user/appdata/dawarich/{postgres17,redis,shared,public,watched,storage}`, `dawarich_*.txt` Secrets | Tier 2 (Ziel); **Backup-Scope noch offen** - `dawarich.dump` + Appdata sind weder in `ops/borg-ui/BACKUP_SCOPE.md` noch in der Quellliste/`pre-backup-dumps.sh`; bis dahin Standortdaten **nicht** DR-gesichert (siehe `docs/MASTER_TODO.md`) | ja + Authelia | UI hinter Authelia; API-Key-Tracking-Endpunkte fuer OwnTracks/Overland/Traccar ohne ForwardAuth priorisiert (Auth-Sicht: `docs/AUTH_MATRIX.md`, Ausnahme: Architecture §10). App und Sidekiq nutzen `freikin/dawarich:1.8.1`; Prometheus-Scrape nach aktueller Dawarich-Doku ueber `dawarich_app:3000/metrics`, Sidekiq-Metriken intern ueber `:9394`. | -| `dawarich_db` | Dawarich PostGIS-Datenbank | `apps/dawarich/docker-compose.yml` | intern | `backend_net` | `/mnt/user/appdata/dawarich/postgres17`, `dawarich_postgres_password.txt`, `dawarich_grafana_ro_password.txt` | Dump `dawarich.dump` **geplant** (noch nicht in `pre-backup-dumps.sh`); raw DB nur bei gleichem PG/PostGIS und sauberem Shutdown | nein | PostGIS 17-3.5 Alpine; Grafana-Read-only-User `dawarich_grafana_ro` per Init-Script | +| `dawarich_app` | Standort-Historie / Google-Timeline-Ersatz | `apps/dawarich/docker-compose.yml` | `https://dawarich.kaleschke.info` | eigene PostGIS-DB, eigene Redis, Traefik + Authelia, optional Home Assistant Push | `/mnt/user/appdata/dawarich/{postgres17,redis,shared,public,watched,storage}`, `dawarich_*.txt` Secrets | Tier 2; repo-seitig via `dawarich.dump` + `/local/appdata/dawarich` im Borg-Scope verdrahtet, erster Host-Dump/Restore-Smoke offen | ja + Authelia | UI hinter Authelia; API-Key-Tracking-Endpunkte fuer OwnTracks/Overland/Traccar ohne ForwardAuth priorisiert (Auth-Sicht: `docs/AUTH_MATRIX.md`, Ausnahme: Architecture §10). App und Sidekiq nutzen `freikin/dawarich:1.8.1`; Prometheus-Scrape nach aktueller Dawarich-Doku ueber `dawarich_app:3000/metrics`, Sidekiq-Metriken intern ueber `:9394`. | +| `dawarich_db` | Dawarich PostGIS-Datenbank | `apps/dawarich/docker-compose.yml` | intern | `backend_net` | `/mnt/user/appdata/dawarich/postgres17`, `dawarich_postgres_password.txt`, `dawarich_grafana_ro_password.txt` | `dawarich.dump` in `pre-backup-dumps.sh`; raw DB nur bei gleichem PG/PostGIS und sauberem Shutdown | nein | PostGIS 17-3.5 Alpine; Grafana-Read-only-User `dawarich_grafana_ro` per Init-Script | | `dawarich_redis` | Dawarich Cache/Queue-Backend | `apps/dawarich/docker-compose.yml` | intern | `backend_net` | `/mnt/user/appdata/dawarich/redis`, `dawarich_redis_password.txt` | Teil von Dawarich-Restore, aber aus DB/Appdaten rekonstruierbar | nein | Redis 8.8 Alpine, keine Host-Ports | | `mail-archiver` | Mail-Archivierung | `apps/mail-archiver/docker-compose.yml` | `https://mail.kaleschke.info` | PostgreSQL 18, Internet/IMAP, Traefik, Authelia | `/mnt/user/appdata/mailarchiver/data-protection-keys` | Tier 2, `postgresql17-mailarchiver.dump` | ja + Authelia | Hybrid-Dienst: `frontend_net` fuer Internet, `backend_net` fuer DB; App-eigene Auth bleibt zusaetzliche Schutzschicht; Dump-Dateiname behaelt den historischen Cluster-Namen | | `nextcloud` | Datei-/Cloud-Dienst | `apps/nextcloud/docker-compose.yml` | `https://cloud.kaleschke.info` | eigene PostgreSQL, eigene Redis, Traefik | `/mnt/user/appdata/nextcloud/html`, `/mnt/user/documents/nextcloud-data` | Tier 2, `nextcloud.dump` + Share | ja | native App-Auth ohne zentrale ForwardAuth; WebDAV/CardDAV beachten | @@ -63,7 +63,7 @@ Secret-Werte sind nicht enthalten. Es werden nur Secret-Namen, Env-Key-Namen und | `komodo-core` | GitOps UI/API/Stack-Manager | `ops/komodo/docker-compose.yml` | `https://komodo.kaleschke.info` | Mongo, Gitea, Traefik | `/mnt/user/appdata/komodo/core`, `komodo_keys` | Tier 1 | ja, native Auth | keine pauschale Authelia-ForwardAuth; Gitea DNS override; **Self-Stack ist inline in Komodo verwaltet** (`repo=""`, `webhook_enabled=false`, kein GitOps-Push), `ops/komodo/docker-compose.yml` ist nur Spiegel/Recovery-Anker - Repo-Aenderungen wirken nicht automatisch live (DECISIONS 2026-05-04 / 2026-06-23); IP-Allowlist statt public | | `komodo-mongo` | Komodo Datenbank | `ops/komodo/docker-compose.yml` | intern | `komodo_net` | `/mnt/user/appdata/komodo/mongo`, `komodo_mongo_password.txt` | Tier 1, `komodo-mongo.archive.gz` | nein | Dump am 2026-05-04 bestaetigt; nach Major-Upgrades pruefen | | `komodo-periphery` | Komodo Host-Agent | `ops/komodo/docker-compose.yml` | intern Core -> Periphery | Docker socket, `/mnt/user/services`, `frontend_net`, `komodo_net` | `/mnt/user/appdata/komodo/periphery`, `komodo_keys` | Tier 1 | nein | Docker-Socket-Ausnahme; `/mnt/user/services` Mount fuer Stack-Workspaces | -| `borg-ui` | Borg Backup-/Restore UI | `ops/borg-ui/docker-compose.yml` | `https://borg.kaleschke.info` | Traefik + Authelia, Borg repo credentials | `/mnt/user/appdata/borg-ui/data`, `/mnt/user/backups/borg/dumps`, Restore-Ziel | Tier 3 / Backup kritisch, `borg-ui.sqlite` | ja + Authelia | breite Mounts bewusst; `/local/secrets` im DR-Scope; Nextcloud-Daten werden read-only nach `/local/nextcloud/data` eingebunden | +| `borg-ui` | Borg Backup-/Restore UI | `ops/borg-ui/docker-compose.yml` | `https://borg.kaleschke.info` | Traefik + Authelia, Borg repo credentials | `/mnt/user/appdata/borg-ui/data`, `/mnt/user/backups/borg/dumps`, Restore-Ziel | Tier 3 / Backup kritisch, `borg-ui.sqlite` | ja + Authelia | breite Mounts bewusst; `/local/secrets` im DR-Scope; Nextcloud-Daten werden read-only nach `/local/nextcloud/data` eingebunden; Dawarich-Appdata ist ueber `/local/appdata/dawarich` im Borg-Scope | | `glances` | System-/Container-Monitoring | `ops/glances/docker-compose.yml` | `https://glances.kaleschke.info` | Docker socket, rootfs, Traefik + Authelia | kein kritischer Zustand | Tier 3, rebuildbar | ja + Authelia | Dokumentierte Host-Observability-Ausnahme: `pid: host`, `/:/rootfs:ro`, `/var/run/docker.sock:/var/run/docker.sock:ro`, `/etc/os-release:/etc/os-release:ro`; keine Appdaten ausserhalb `/mnt/user/...` | | `scrutiny` | Laufwerks-/SMART-Monitoring | `ops/scrutiny/docker-compose.yml` | `https://scrutiny.kaleschke.info` | Device mounts, Traefik + Authelia | `/mnt/user/appdata/scrutiny/config`, `/mnt/user/appdata/scrutiny/influxdb` | Tier 3, Metrics nicht kritisch | ja + Authelia | Dokumentierte Host-Observability-Ausnahme: `privileged: true`, `/run/udev:/run/udev:ro`, `/dev/sdb:/dev/sdb`, `/dev/sdc:/dev/sdc`, `/dev/nvme0n1:/dev/nvme0n1`; keine Appdaten ausserhalb `/mnt/user/...` | | `speedtest-tracker` | Speedtest-Monitoring | `ops/speedtest/docker-compose.yml` | `https://speedtest.kaleschke.info` | Traefik + Authelia | `/mnt/user/appdata/speedtest-tracker/config` | Tier 3, `speedtest-tracker.sqlite.dump` | ja + Authelia | `APP_KEY`, `ADMIN_PASSWORD` Stack ENV | diff --git a/ops/borg-ui/BACKUP_SCOPE.md b/ops/borg-ui/BACKUP_SCOPE.md index eef5326..45105a7 100644 --- a/ops/borg-ui/BACKUP_SCOPE.md +++ b/ops/borg-ui/BACKUP_SCOPE.md @@ -49,6 +49,7 @@ The Unraid flash configuration archive is intentional as well and must be treate | Filebrowser | file-backed state dump + file data | `/local/borg-dumps`, `/local/appdata/filebrowser` | | InfluxDB 3 Core | file data | `/local/appdata/influxdb3/data`, `/local/appdata/influxdb3/plugins` | | n8n | SQLite dump + encrypted workflow/credential state | `/local/borg-dumps`, `/local/appdata/n8n/data` | +| Dawarich | PostGIS dump + file data | `/local/borg-dumps`, `/local/appdata/dawarich` | | Home Assistant | HA-native backup + file state | `/local/appdata/homeassistant`, `/local/services/smart-home-kalli` | | Smart-Home MQTT / Mosquitto | file data | `/local/appdata/mosquitto/config`, `/local/appdata/mosquitto/data` | | Zigbee2MQTT (planned) | file data + coordinator state | `/local/appdata/zigbee2mqtt`, `/local/services/smart-home-kalli` | @@ -79,22 +80,23 @@ Filebrowser serviert `/mnt/user/projekte`, `/mnt/user/documents` und `/mnt/user/ - **`/mnt/user/projekte`** ist aktuell in **keinem** Borg-Scope. Ad-hoc-Dateien, die direkt unter `documents/` oder `photos/` (ausserhalb der genannten App-Ordner) abgelegt werden, ebenfalls nicht. - Entscheidung Operator offen (Eintrag in `docs/MASTER_TODO.md`): Entweder `projekte` als eigenen read-only Borg-UI-Mount + Quelllisten-Eintrag aufnehmen, oder bewusst als "nur lokal, nicht DR-relevant" bestaetigen. Bis zur Entscheidung gilt: dort liegende Originaldaten sind **nicht** wiederherstellbar. -### Dawarich (Standortdaten) - noch nicht im Scope +### Dawarich (Standortdaten) - repo-seitig verdrahtet, Host-Lauf offen Dawarich (`apps/dawarich/docker-compose.yml`) speichert hochsensible Standort-Historie in einer eigenen PostGIS-DB unter `/mnt/user/appdata/dawarich/{postgres17,redis,shared,public,watched,storage}`. -`docs/SERVICE_CATALOG.md` nennt als Ziel "Tier 2, Borg + `dawarich.dump`", aber: +Repo-seitig ist der Scope jetzt geschlossen: -- Es gibt **keinen** `dawarich`-Eintrag in der Service Inventory oben. -- `pre-backup-dumps.sh` erzeugt **kein** `dawarich.dump` (PostGIS-`pg_dump`). -- Die Quellliste (`all-important-sources.txt`) enthaelt **keinen** - `/local/appdata/dawarich`-Pfad, und Borg-UI mountet ihn nicht. +- `pre-backup-dumps.sh` erzeugt `dawarich.dump` aus `dawarich_db`. +- `all-important-sources.txt` enthaelt `/local/appdata/dawarich`. +- Borg-UI sieht den Pfad ueber den bestehenden read-only Mount + `/mnt/user/appdata:/local/appdata:ro`. -Konsequenz: Standortdaten sind aktuell **nicht** DR-gesichert. Schliessen -(Operator + Host): `dawarich.dump` in `pre-backup-dumps.sh` (PostGIS), Pfad in -Quellliste + Borg-UI-Mount + diese Tabelle aufnehmen, danach `RESTORE_MATRIX.md` -Tier-2-Zeile + Reifegrad ergaenzen. Tracking: `docs/MASTER_TODO.md`. +Offen bleibt der erste Host-Lauf: auf Unraid `pre-backup-dumps.sh` ausfuehren, +Vorhandensein/Frische von `/mnt/user/backups/borg/dumps/latest/dawarich.dump` +pruefen und danach einen Restore-Smoke in einer isolierten PostGIS-17-Instanz +terminieren. Bis dieser Host-Beleg existiert, ist der Status "verdrahtet, noch +nicht restore-validiert". ### Komodo keys @@ -113,6 +115,7 @@ Production still stores Komodo Core/Periphery keys in the Docker named volume `k - `mealie` - `immich` - `nextcloud` +- `dawarich` ### Other Databases @@ -129,6 +132,8 @@ Production still stores Komodo Core/Periphery keys in the Docker named volume `k - `/mnt/user/appdata/mealie/postgres18` - `/mnt/user/appdata/immich_postgres_vectorchord` - `/mnt/user/appdata/nextcloud/postgres18` +- `/mnt/user/appdata/dawarich/postgres17` +- `/mnt/user/appdata/dawarich/redis` - `/mnt/user/appdata/komodo/mongo` - `/mnt/user/appdata/redis` - `/mnt/user/appdata/scrutiny/influxdb` diff --git a/ops/borg-ui/all-important-sources.txt b/ops/borg-ui/all-important-sources.txt index ad6b4c8..9855666 100644 --- a/ops/borg-ui/all-important-sources.txt +++ b/ops/borg-ui/all-important-sources.txt @@ -21,6 +21,7 @@ /local/appdata/nextcloud/html /local/nextcloud/data /local/appdata/n8n/data +/local/appdata/dawarich /local/appdata/filebrowser /local/appdata/influxdb3/data /local/appdata/influxdb3/plugins diff --git a/ops/borg-ui/scripts/pre-backup-dumps.sh b/ops/borg-ui/scripts/pre-backup-dumps.sh index 0ffd5df..7d025d0 100755 --- a/ops/borg-ui/scripts/pre-backup-dumps.sh +++ b/ops/borg-ui/scripts/pre-backup-dumps.sh @@ -314,6 +314,15 @@ main() { warn "Skipping missing container: nextcloud-postgres" fi + if need_container "dawarich_db"; then + dawarich_password="$(cat /mnt/user/appdata/secrets/dawarich_postgres_password.txt)" + dawarich_user="$(docker exec dawarich_db sh -lc 'printf "%s" "${POSTGRES_USER:-dawarich}"')" + dawarich_db="$(docker exec dawarich_db sh -lc 'printf "%s" "${POSTGRES_DB:-dawarich_production}"')" + dump_pg_db "dawarich_db" "$dawarich_password" "$dawarich_user" "$dawarich_db" "$LATEST_DIR/dawarich.dump" + else + warn "Skipping missing container: dawarich_db" + fi + # SQLite databases dump_sqlite_container "gitea" "/data/gitea/gitea.db" "$LATEST_DIR/gitea.sqlite.dump" "/mnt/user/services/gitea/data/gitea/gitea.db" dump_sqlite_container "vaultwarden" "/data/db.sqlite3" "$LATEST_DIR/vaultwarden.sqlite.dump" "/mnt/user/appdata/vaultwarden/db.sqlite3" diff --git a/ops/h-drive-nearline/pull-critical-backups.ps1 b/ops/h-drive-nearline/pull-critical-backups.ps1 index 2f8af68..e7c9c42 100644 --- a/ops/h-drive-nearline/pull-critical-backups.ps1 +++ b/ops/h-drive-nearline/pull-critical-backups.ps1 @@ -43,6 +43,7 @@ $Jobs = @( ExcludeFiles = @("unraid-flash-config.tar.gz", "unraid-flash-config.tar.gz.sha256", "unraid-flash-config.manifest.txt") Files = @( "borg-ui.sqlite", + "dawarich.dump", "filebrowser.bolt.dump", "gitea.sqlite.dump", "grafana.sqlite", @@ -202,6 +203,7 @@ try { $lines += "Expected critical artifacts after run:" $lines += "" $lines += "- ``borg-dumps/latest/immich.dump``" + $lines += "- ``borg-dumps/latest/dawarich.dump``" $lines += "- ``borg-dumps/latest/komodo-mongo.archive.gz``" $lines += "- ``git-bundles/gitea/latest-report.md``" $lines += "- ``git-bundles/gitea/micha/*.bundle``" diff --git a/ops/hermes-agent/services.yaml b/ops/hermes-agent/services.yaml index a215c9b..b5aa302 100644 --- a/ops/hermes-agent/services.yaml +++ b/ops/hermes-agent/services.yaml @@ -318,6 +318,67 @@ services: first_check: "mealie_internal Netz? Disk-Space?" notes: "interne DB; mealie_internal Netz" + dawarich_app: + description: Standort-Historie / Google-Timeline-Ersatz + tier: 2 + category: app + container_name: dawarich_app + dependencies: + - dawarich_db + - dawarich_redis + - traefik + - authelia + url: https://dawarich.kaleschke.info + dump_file: dawarich.dump + data_paths: + - /mnt/user/appdata/dawarich/public + - /mnt/user/appdata/dawarich/watched + - /mnt/user/appdata/dawarich/storage + first_check: "dawarich_db und dawarich_redis healthy? /api/v1/health ok? Authelia-UI-Router und API-Key-Router getrennt?" + notes: "Standortdaten sind hochsensibel; UI hinter Authelia, API-Key-Ingest-Pfade ohne ForwardAuth; Backup repo-seitig via dawarich.dump + /local/appdata/dawarich verdrahtet" + + dawarich_db: + description: Dawarich PostGIS-Datenbank + tier: 2 + category: infra + container_name: dawarich_db + dependencies: [] + url: null + dump_file: dawarich.dump + data_paths: + - /mnt/user/appdata/dawarich/postgres17 + first_check: "backend_net Konnektivitaet? pg_isready im Container? dawarich.dump frisch?" + notes: "PostGIS 17; raw DB nicht primaerer Restore-Weg" + + dawarich_redis: + description: Dawarich Cache / Queue-Backend + tier: 2 + category: infra + container_name: dawarich_redis + dependencies: [] + url: null + dump_file: null + data_paths: + - /mnt/user/appdata/dawarich/redis + first_check: "backend_net Konnektivitaet? redis-cli auth ping?" + notes: "aus DB/Appdaten rekonstruierbar, aber Appdata-Pfad ist im Borg-Scope" + + dawarich_sidekiq: + description: Dawarich Hintergrundjobs + tier: 2 + category: app + container_name: dawarich_sidekiq + dependencies: + - dawarich_db + - dawarich_redis + - dawarich_app + url: null + dump_file: dawarich.dump + data_paths: + - /mnt/user/appdata/dawarich/storage + first_check: "sidekiq-Prozess laeuft? DB/Redis erreichbar? Metriken auf :9394 erreichbar?" + notes: "nutzt dasselbe Dawarich-Image wie dawarich_app" + mail-archiver: description: Mail-Archivierung (IMAP) tier: 2 diff --git a/ops/restore-tests/check-restore-freshness.ps1 b/ops/restore-tests/check-restore-freshness.ps1 index 957f855..72fa480 100644 --- a/ops/restore-tests/check-restore-freshness.ps1 +++ b/ops/restore-tests/check-restore-freshness.ps1 @@ -12,6 +12,7 @@ $checks = @( @{ Name = "mealie.dump"; Path = Join-Path $DumpRoot "mealie.dump" }, @{ Name = "immich.dump"; Path = Join-Path $DumpRoot "immich.dump" }, @{ Name = "nextcloud.dump"; Path = Join-Path $DumpRoot "nextcloud.dump" }, + @{ Name = "dawarich.dump"; Path = Join-Path $DumpRoot "dawarich.dump" }, @{ Name = "gitea.sqlite.dump"; Path = Join-Path $DumpRoot "gitea.sqlite.dump" }, @{ Name = "vaultwarden.sqlite.dump"; Path = Join-Path $DumpRoot "vaultwarden.sqlite.dump" }, @{ Name = "n8n.sqlite.dump"; Path = Join-Path $DumpRoot "n8n.sqlite.dump" }, diff --git a/ops/restore-tests/check-restore-freshness.sh b/ops/restore-tests/check-restore-freshness.sh index 84813d0..cfdf581 100755 --- a/ops/restore-tests/check-restore-freshness.sh +++ b/ops/restore-tests/check-restore-freshness.sh @@ -28,7 +28,7 @@ check_file_age_days() { # pg_restore --list als billiger Header-Check fuer Custom-Format-Dumps; # erkennt Korruption, die mit reinem "exists+nonempty" durchrutscht. Wir # brauchen kein laufendes Postgres; der Check liest nur die Toc-Section. -PG_DUMPS="postgresql17-paperless.dump postgresql17-mailarchiver.dump postgresql17-authelia.dump mealie.dump immich.dump nextcloud.dump" +PG_DUMPS="postgresql17-paperless.dump postgresql17-mailarchiver.dump postgresql17-authelia.dump mealie.dump immich.dump nextcloud.dump dawarich.dump" is_pg_custom_dump() { case " $PG_DUMPS " in *" $1 "*) return 0;; *) return 1;; esac } @@ -95,6 +95,7 @@ for dump in \ mealie.dump \ immich.dump \ nextcloud.dump \ + dawarich.dump \ gitea.sqlite.dump \ vaultwarden.sqlite.dump \ n8n.sqlite.dump \ diff --git a/services/posture-check/export-prometheus-textfile.sh b/services/posture-check/export-prometheus-textfile.sh index 26038f3..cb8a7c3 100755 --- a/services/posture-check/export-prometheus-textfile.sh +++ b/services/posture-check/export-prometheus-textfile.sh @@ -8,7 +8,7 @@ BORG_EXPECTED_SOURCES_FILE="${BORG_EXPECTED_SOURCES_FILE:-/local/services/homela # Host-Pfad der aktuellen Dump-Artefakte (pre-backup-dumps.sh schreibt hierhin). # Wird host-seitig gestattet; der Exporter laeuft als Unraid User Script. BORG_DUMP_DIR="${BORG_DUMP_DIR:-/mnt/user/backups/borg/dumps/latest}" -CRITICAL_CONTAINERS="${CRITICAL_CONTAINERS:-traefik authelia postgresql17 gitea komodo-core komodo-mongo komodo-periphery vaultwarden borg-ui ntfy adguard unbound monitoring-alertmanager monitoring-alertmanager-ntfy-bridge monitoring-blackbox-exporter monitoring-cadvisor monitoring-grafana monitoring-loki monitoring-node-exporter monitoring-promtail immich_server immich_postgres immich_redis paperless-ngx nextcloud nextcloud-postgres nextcloud-redis mealie mealie-postgres mail-archiver n8n homeassistant smarthome-mosquitto}" +CRITICAL_CONTAINERS="${CRITICAL_CONTAINERS:-traefik authelia postgresql17 gitea komodo-core komodo-mongo komodo-periphery vaultwarden borg-ui ntfy adguard unbound monitoring-alertmanager monitoring-alertmanager-ntfy-bridge monitoring-blackbox-exporter monitoring-cadvisor monitoring-grafana monitoring-loki monitoring-node-exporter monitoring-promtail immich_server immich_postgres immich_redis paperless-ngx nextcloud nextcloud-postgres nextcloud-redis mealie mealie-postgres mail-archiver n8n dawarich_app dawarich_db dawarich_redis dawarich_sidekiq homeassistant smarthome-mosquitto}" # Hinweis: Tailscale laeuft als natives Unraid-Plugin (kein Docker-Container) und # wird daher hier bewusst NICHT als kritischer Container gefuehrt (Stand 2026-06-06). @@ -260,6 +260,7 @@ EOF mealie.dump \ immich.dump \ nextcloud.dump \ + dawarich.dump \ gitea.sqlite.dump \ vaultwarden.sqlite.dump \ n8n.sqlite.dump \