diff --git a/CLAUDE.md b/CLAUDE.md new file mode 100644 index 0000000..0b57bdf --- /dev/null +++ b/CLAUDE.md @@ -0,0 +1,127 @@ +# Claude Code Context - Homelab Infra + +Stand: 2026-05-04 + +Dieses Repository ist die GitOps-Quelle fuer das KalliLab CORE Homelab auf einem Unraid-Host. Es verwaltet Docker-Compose-Stacks fuer Core-Dienste, Security, Infrastruktur, Apps, Operations-Tools, Host-nahe Dienste und Traefik. Gitea Online ist die operative Quelle der Wahrheit; Komodo konsumiert den Git-Stand und deployed daraus. + +## Vor jeder Aenderung lesen + +Claude muss vor jeder fachlichen oder technischen Aenderung mindestens diese Dateien lesen: + +1. `HOMELAB_ARCHITECTURE_MASTER_V2.md` +2. `docs/WORKFLOW.md` +3. `docs/REPO_MAP.md` +4. `docs/SERVICE_CATALOG.md` +5. die betroffene `docker-compose.yml` + +Zusaetzlich je nach Thema: + +- Restore / Host-Ausfall: `docs/DISASTER_RECOVERY.md` und `docs/RESTORE_MATRIX.md` +- Rollback: `docs/ROLLBACK.md` +- Secrets: `docs/SECRETS_MAP.md` +- GitOps-/Komodo-/Runtime-Drift: `docs/GITOPS_DRIFT_RUNBOOK.md` +- Gesamtbild fuer KI-Agenten: `docs/AI_CONTEXT.md` +- Home Assistant / Ecowitt / InfluxDB: `docs/HOME_ASSISTANT_INFLUXDB_ECOWITT.md` + +## Projektbeschreibung + +- Host: Unraid, Hostname `Kallilabcore` +- Domain: `kaleschke.info` +- Reverse Proxy: Traefik v3 +- DNS: AdGuard Home + Unbound +- VPN/Remote: Tailscale +- Git: Gitea unter `git.kaleschke.info` +- Deployment: Komodo als primaerer und einziger produktiver Stack-Manager +- Lokale Arbeitskopie: Windows/GitHub Desktop +- Persistenz: ueberwiegend `/mnt/user/appdata`, Nutzdaten in `/mnt/user/documents`, `/mnt/user/photos`, GitOps/Gitea in `/mnt/user/services` + +## Architekturprinzipien + +- Traefik ist der einzige oeffentliche HTTP(S)-Einstiegspunkt. +- Service-Routing erfolgt per Docker-Labels, nicht ueber neue Traefik File-Provider-Service-Routen. +- `frontend_net` ist das Web-/Proxy-Netz. +- `backend_net` ist `internal: true` fuer Datenbanken, Redis und interne Backends. +- App-interne Netze sind erlaubt, wenn sie eine App und ihre Datenbank/Worker sauber isolieren. +- Datenbanken und Caches duerfen nicht im `frontend_net` liegen. +- Direkte Host-Ports sind nur mit dokumentierter Ausnahme erlaubt. +- Komodo bleibt bewusst ohne pauschale zentrale Authelia-ForwardAuth-Middleware. +- Secrets gehoeren niemals ins Git-Repository. +- Produktive Container sollen als Compose/Git-Stack verwaltet werden. + +## GitOps-Regeln + +Quelle der Wahrheit: + +1. Gitea `origin/master` +2. lokaler Clone +3. Komodo Stack Workspace +4. laufende Docker-Container +5. Host-Zustand + +Standard-Workflow: + +1. Lokal synchronisieren (`Fetch`, ggf. `Pull`) +2. Betroffene Docs und Compose-Datei lesen +3. Zielzustand und Rollback klaeren +4. Lokal minimal aendern +5. Validieren +6. Commit und Push durch den Benutzer oder nach expliziter Freigabe +7. Komodo-Deploy/Runtime pruefen +8. Dokumentation nachziehen + +Wenn Drift vermutet wird, nicht raten. Erst die Pflichtmatrix in `docs/GITOPS_DRIFT_RUNBOOK.md` abarbeiten. + +## Sicherheitsregeln + +- Secret-Werte niemals ausgeben. Wenn Werte auftauchen: redakten. +- Nur Secret-Namen, Env-Key-Namen und Pfade dokumentieren. +- Keine produktiven `.env`- oder Stack-Env-Werte zitieren. +- Keine Compose-Aenderung ohne vorherigen Architektur-/Workflow-Abgleich. +- Keine Deployments, Host-Hotfixes oder Docker-Schreibbefehle ohne ausdrueckliche Anweisung. +- Keine direkten Host-Ports fuer Web-UIs, ausser dokumentierte Ausnahmen. +- `privileged: true`, Docker-Socket und Host-Netz nur als dokumentierte Ausnahme. +- Traefik dynamic config unter `traefik/dynamic/` wird nicht automatisch von Komodo deployed und muss bei Aenderungen manuell auf den Host synchronisiert werden. + +## Bekannte dokumentierte Ausnahmen + +- `traefik`: Host-Ports 80/443 +- `gitea`: SSH-Port 222 +- `AdGuard Home`: DNS-Port 53 und LAN-Admin-Port 8082 +- `tailscale`: `network_mode: host` +- `Plex-Media-Server`: historischer Host-Netz-Sonderfall, nicht als Repo-Stack enthalten +- `scrutiny`: `privileged: true` fuer SMART/Laufwerkszugriff +- `Komodo`: Docker-Socket und native Auth ohne pauschale ForwardAuth +- `traefik/dynamic/*`: manuelle Host-Sync-Ausnahme +- `influxdb3-core`: LAN-only Host-Port 8181 fuer Home Assistant Writer, keine Traefik-Route, nicht im `frontend_net` + +## No-Go-Regeln + +- Keine produktiven Aenderungen direkt in Komodo. +- Keine `docker run`-Ad-hoc-Container als Dauerzustand. +- Keine Compose-Dateien, Secrets oder Host-Konfigurationen stillschweigend aendern. +- Keine Deployments ausloesen, wenn der Benutzer nur Analyse oder Dokumentation verlangt. +- Kein `push --force` auf `master` als Standard-Rollback. +- Keine History-Rewrites ohne ausdrueckliche Freigabe. +- Keine Loesch-, Reset- oder Migrationsbefehle ohne klaren Zielzustand und Rollback. +- Keine neuen `latest`-/mutable Image-Tags ohne bewusste Versionsentscheidung. + +## Rollback-Erwartungen + +Jede Aenderung braucht vor dem Deploy eine klare Rueckkehrstrategie: + +- letzter bekannter funktionierender Git-Stand +- betroffener Stack und Persistenzpfade +- ob Datenpfade unveraendert bleiben +- ob Secrets/ENV betroffen sind +- konkrete Smoke-Tests nach Rollback + +Standard-Rollback ist ein Ruecknahme-Commit oder gezielte Rueckaenderung mit Push nach Gitea. Produktive Datenpfade unter `/mnt/user/appdata`, `/mnt/user/documents`, `/mnt/user/photos`, `/mnt/user/services` und `/mnt/user/backups` nicht blind loeschen. + +## Arbeitsweise fuer Claude + +- Erst lesen, dann handeln. +- Bei Unsicherheit Zustand messen, nicht erraten. +- Aenderungen klein halten und nur den betroffenen Bereich anfassen. +- Bestehende Doku und Repo-Konventionen bevorzugen. +- Bei Secret-/Runtime-/Komodo-Fragen besonders konservativ sein. +- Wenn zwei Reparaturversuche nicht funktionieren: stoppen, Pflichtmatrix ausfuellen, eine abweichende Ebene benennen. diff --git a/docs/AI_CONTEXT.md b/docs/AI_CONTEXT.md new file mode 100644 index 0000000..19351db --- /dev/null +++ b/docs/AI_CONTEXT.md @@ -0,0 +1,175 @@ +# AI Context + +Stand: 2026-05-04 + +Diese Datei ist fuer KI-Agenten gedacht, die das Homelab-Repo schnell verstehen muessen. Sie ersetzt nicht die Detaildokumente, sondern fasst Zielbild, Betriebsmodell und Risiken zusammen. + +## Kurzfassung + +Dieses Repository beschreibt ein Unraid-basiertes Homelab namens `Kallilabcore`. Der Betrieb folgt GitOps: Gitea `origin/master` ist die Quelle der Wahrheit, der lokale Clone ist Arbeitskopie, Komodo deployed aus Gitea, Docker Runtime und Host sind Ergebnis, nicht Bearbeitungsort. + +Traefik ist der zentrale Web-Einstieg fuer HTTP(S). Admin-/Ops-UIs liegen entweder hinter Authelia/secure headers oder sind als Ausnahme dokumentiert. Secrets liegen ausserhalb des Repos auf dem Host, meistens unter `/mnt/user/appdata/secrets/`. + +## Zielbild des Homelabs + +- stabile Compose-first Infrastruktur +- keine produktiven Dockerman-/Ad-hoc-Container als Dauerzustand +- Traefik als einziger oeffentlicher Web-Eingang +- GitOps ueber Gitea + Komodo +- klare Trennung von Web-Netz, Backend-Netz und app-internen Netzen +- saubere Backup-/Restore-Faehigkeit ueber Borg, Dumps und dokumentierte Pfade +- keine stillen Host-Hotfixes ohne Repo-/Doku-Abgleich + +## Architekturblocke + +### Ingress / Netzwerk + +- `traefik` nimmt 80/443 entgegen. +- Docker-Labels definieren Service-Routing. +- `traefik/dynamic/*` bleibt nur fuer Middlewares, TLS und Dashboards. +- Neue Service-Routen gehoeren nicht in den File-Provider. + +### DNS / Remote + +- AdGuard Home beantwortet LAN-DNS und nutzt Unbound als Upstream. +- Tailscale stellt Remote-Zugang bereit und nutzt `network_mode: host`. + +### GitOps + +- Gitea hostet das Repo unter `git.kaleschke.info`. +- Komodo ist Stack-Manager und Deploy-Consumer. +- Komodo Periphery braucht Docker-Socket und `/mnt/user/services` Mount, um Stacks reproduzierbar zu deployen. + +### Identity / Security + +- Authelia stellt ForwardAuth fuer viele Admin-UIs bereit. +- Vaultwarden ist ein separater Passwort-Tresor. +- Komodo ist bewusst nicht pauschal hinter Authelia, weil UI, API, Webhooks und Periphery-WebSocket sonst leicht gebrochen werden koennen. + +### Apps + +Wichtige Apps sind Paperless, Immich, Mealie, Mail Archiver, Nextcloud, ntfy, Vaultwarden und Gitea. Admin-/Ops-Tools sind u. a. Homepage, Komodo, Borg UI, Backrest, Uptime Kuma, Filebrowser, code-server, Glances, Scrutiny, Speedtest, Grafana und Hermes Agent. + +### Monitoring / Metriken + +- Grafana laeuft unter `grafana.kaleschke.info` hinter Traefik + Authelia. +- InfluxDB 3 Core ist nicht public und nicht im `frontend_net`. +- Home Assistant schreibt ueber LAN-only Port 8181 nach InfluxDB, gebunden ueber `INFLUXDB_BIND_IP`. +- Ein `401 Unauthorized` von InfluxDB ohne Token ist beim Reachability-Test ein Erfolgssignal. + +## Deployment-Logik + +Normalfall: + +1. lokaler Clone synchronisieren +2. betroffene Dokumente und Compose-Datei lesen +3. minimal aendern +4. lokal validieren +5. committen und pushen +6. Komodo-Webhook / Deploy beobachten +7. Runtime testen +8. Doku aktualisieren + +Wichtig: Komodo-Web-Editor ist nicht der Bearbeitungsort. Wenn Komodo und Git voneinander abweichen, zuerst Git und Komodo Workspace pruefen, nicht live herumprobieren. + +## Netzwerkmodell + +| Netzwerk | Bedeutung | +|---|---| +| `frontend_net` | Web-/Proxy-Netz fuer Traefik-geroutete Dienste und Dienste mit Internetbedarf | +| `backend_net` | internes Netz fuer shared PostgreSQL, Redis und Backends | +| `dns_net` | AdGuard + Unbound | +| app-interne Netze | Isolation von App + DB/Cache, z. B. Immich, Mealie, Nextcloud, Grafana/Influx | +| `host` | nur dokumentierte Sonderfaelle wie Tailscale/Plex | + +Regeln: + +- Datenbanken nie ins `frontend_net`. +- Admin-UIs nur mit Traefik + Middleware oder dokumentierter Ausnahme. +- Direkte Host-Ports sind Ausnahme, nicht Default. +- Runtime-Netznamen koennen Compose-Projektpraefixe bekommen, z. B. `grafana_grafana_influx_lan`. + +## Security-Modell + +- Secrets nie ins Git. +- Werte niemals zitieren, auch nicht aus `.env`, Stack ENV, Logs oder Screenshots. +- Secret-Dateien bevorzugt unter `/mnt/user/appdata/secrets/`. +- `_FILE`-Varianten bevorzugen, falls Image sie unterstuetzt. +- Wenn `_FILE` nicht unterstuetzt wird, Komodo Stack Environment Variables verwenden. +- Docker-Socket, `privileged: true`, Host-Netz und breite Mounts sind nur mit dokumentierter Begruendung akzeptabel. + +Bekannte Ausnahmen: + +- Traefik: 80/443 +- Gitea: SSH 222 +- AdGuard: DNS 53 und Admin 8082 +- Tailscale: Host-Netz +- Scrutiny: privileged +- Komodo: Docker-Socket, native Auth +- InfluxDB: LAN-only 8181 fuer Home Assistant Writer +- Traefik dynamic config: manueller Host-Sync + +## Backup- und Restore-Modell + +Borg sichert kritische Appdaten, Secrets, Traefik-State und Dump-Artefakte. Datenbank-Restore soll bevorzugt ueber Dumps laufen, nicht ueber rohe Live-DB-Verzeichnisse. + +Wichtige Pfade: + +- `/mnt/user/appdata` +- `/mnt/user/appdata/secrets` +- `/mnt/user/services` +- `/mnt/user/documents` +- `/mnt/user/photos` +- `/mnt/user/backups/borg/dumps/latest` + +Dump-Skript: + +- `ops/borg-ui/scripts/pre-backup-dumps.sh` +- soll auf dem Unraid Host laufen +- soll nicht als Borg-UI Inline-Hook behandelt werden, solange die Architektur nicht bewusst geaendert wird + +Disaster Recovery folgt einer Bootstrap-Reihenfolge: + +1. Traefik, AdGuard, Tailscale +2. PostgreSQL, Redis, Authelia, Gitea +3. Komodo +4. kritische Apps +5. restliche Apps/Ops + +## Typische Arbeitsweise im Repo + +- Fuer Fragen zuerst `HOMELAB_ARCHITECTURE_MASTER_V2.md` lesen. +- Fuer operative Aenderungen `docs/WORKFLOW.md` lesen. +- Fuer Service-Details `docs/SERVICE_CATALOG.md` und die Compose-Datei lesen. +- Fuer Drift `docs/GITOPS_DRIFT_RUNBOOK.md` nutzen. +- Fuer Rollback `docs/ROLLBACK.md` nutzen. +- Fuer Restore `docs/DISASTER_RECOVERY.md` und `docs/RESTORE_MATRIX.md` nutzen. + +KI-Agenten sollen konservativ arbeiten: keine indirekten Live-Aenderungen, keine Deployments, keine Commits, keine Host-Schreibbefehle, wenn der Benutzer nur Analyse oder Doku verlangt. + +## Bekannte Risiken und Altlasten + +- Traefik dynamic config muss manuell auf den Host synchronisiert werden; Komodo deployed diese Dateien nicht automatisch. +- `backend_net` und app-interne Netze muessen bei Runtime-Problemen live geprueft werden, weil Compose-Projektpraefixe Netznamen veraendern koennen. +- Authelia Template und Compose-Middlewares koennen auseinanderlaufen; bei Auth-Aenderungen beide Seiten pruefen. +- `paperless-ngx` nutzt fuer DB/Redis bewusst Stack ENV statt `_FILE`. +- `homepage`, `glances` und `komodo-periphery` nutzen Docker-Socket-Mounts; Zugriff bewusst behandeln. +- `backrest`, `borg-ui` und `filebrowser` haben breite Mounts; bei Hardening nicht ad hoc, sondern gezielt vorgehen. +- `scrutiny` ist privilegiert und hat Device-Mounts. +- `Plex-Media-Server` ist im Architekturziel als Host-Sonderfall dokumentiert, aber nicht als Repo-Compose-Stack enthalten. +- `ops/hermes-agent/stack.env` liegt als echte Env-Datei im Repo. Werte wurden fuer dieses Kontextpaket nicht gelesen; pruefen, ob daraus ein Example/Host-Only-Modell werden soll. +- Einige Images nutzen mutable Tag plus Digest. Das friert den aktuellen Digest ein, ist aber kein automatisches Upgrade-Modell. + +## Arbeitsregel bei Unsicherheit + +Nicht raten. Erst diese Reihenfolge: + +1. Repo-Doku lesen +2. Compose-Datei lesen +3. Git-Stand pruefen +4. Komodo Workspace pruefen +5. Docker Runtime pruefen +6. Host-Listener / echten Request pruefen +7. genau eine abweichende Ebene benennen + +Wenn zwei Reparaturversuche scheitern: keine weiteren Schreibbefehle, Pflichtmatrix aus `docs/GITOPS_DRIFT_RUNBOOK.md` ausfuellen. diff --git a/docs/REPO_MAP.md b/docs/REPO_MAP.md new file mode 100644 index 0000000..f30773b --- /dev/null +++ b/docs/REPO_MAP.md @@ -0,0 +1,226 @@ +# Repository Map + +Stand: 2026-05-04 + +Diese Datei ist eine technische Landkarte des Repositories. Sie wurde aus Markdown-Dokumenten, `docker-compose.yml`-Dateien, Env-Beispielen, Traefik-Dynamic-Configs, Komodo/Periphery-Dateien und Skripten abgeleitet. Sie beschreibt den Repo-Sollzustand, nicht zwingend den Live-Zustand auf dem Host. + +Secret-Werte werden hier nicht dokumentiert. Aufgefuehrt werden nur Variablennamen, Secret-Namen und Pfade. + +## Ordnerstruktur + +| Pfad | Zweck | +|---|---| +| `apps/` | Produktive Anwendungen und vorbereitete App-Stacks | +| `core/` | Basisdienste, aktuell Gitea | +| `docs/` | Betriebsdokumentation, Restore, Rollback, GitOps-Regeln | +| `env/` | globale Beispiel-Env-Dateien, aktuell leer | +| `host-services/` | Host-nahe Dienste mit direkten Ports oder Host-Netz | +| `infra/` | technische Infrastruktur wie PostgreSQL, Redis, DDNS | +| `ops/` | Operations-, Backup-, Monitoring- und Admin-Tools | +| `security/` | Identity/Security-Dienste wie Authelia und Vaultwarden | +| `traefik/` | Reverse Proxy Compose und dynamic File-Provider-Konfiguration | + +## Wichtige Dokumente + +| Datei | Bedeutung | +|---|---| +| `README.md` | Einstieg und Kurzueberblick | +| `HOMELAB_ARCHITECTURE_MASTER_V2.md` | operative Architektur-Quelle fuer Netzwerk, Zugriff und Ausnahmen | +| `docs/WORKFLOW.md` | GitOps-/No-Drift-Arbeitsregeln | +| `docs/GITOPS_DRIFT_RUNBOOK.md` | Pflichtmatrix fuer Git/Gitea/Komodo/Docker/Host-Drift | +| `docs/DISASTER_RECOVERY.md` | Wiederanlauf nach Host-/Systemausfall | +| `docs/RESTORE_MATRIX.md` | Restore-Quellen und Smoke-Tests je Dienst | +| `docs/ROLLBACK.md` | Rueckweg im GitOps-Betrieb | +| `docs/SECRETS_MAP.md` | Secret-Namen, Pfade und Einbindungsarten ohne Werte | +| `docs/HOME_ASSISTANT_INFLUXDB_ECOWITT.md` | Home Assistant -> InfluxDB 3 -> Grafana Ablauf | +| `docs/AI_CONTEXT.md` | Gesamtverstaendnis fuer KI-Agenten | +| `docs/SERVICE_CATALOG.md` | produktiver Service-Katalog | + +## Relevante Nicht-Compose-Dateien + +| Datei | Zweck / Hinweis | +|---|---| +| `traefik/dynamic/middlewares.yml` | zentrale `secure-headers` und `authelia` ForwardAuth Middleware; manuelle Host-Sync-Ausnahme | +| `traefik/dynamic/dashboards.yml` | leer; File-Provider-Platzhalter | +| `traefik/dynamic/tls.yml` | leer; File-Provider-Platzhalter | +| `security/authelia/configuration.yml` | Authelia Template; nicht mit echten user-spezifischen Daten committen | +| `ops/grafana-influxdb/provisioning/datasources/influxdb.yml` | Grafana Datasource Provisioning fuer InfluxDB 3 Core | +| `ops/borg-ui/scripts/pre-backup-dumps.sh` | Host-seitiges Dump-Skript fuer PostgreSQL, Mealie, Immich und Komodo Mongo | +| `ops/hermes-agent/config/hermes/config.yaml` | Hermes Agent Konfiguration mit Env-Platzhaltern | +| `ops/hermes-agent/hermes.env.example` | Beispiel fuer Hermes `.env`; echte Datei liegt auf Host-Appdata | +| `ops/hermes-agent/stack.env` | echte Stack-Env-Datei im Repo gefunden; Werte nicht gelesen, nur Keys `TZ`, `HERMES_DASHBOARD_HOST` bekannt | +| `ops/grafana-influxdb/stack.env.example` | `INFLUXDB_BIND_IP` Default `127.0.0.1`; auf Unraid fuer Home Assistant auf LAN-IP setzen | +| `ops/komodo/stack.env.example` | Komodo Stack-ENV-Beispiel, Secret-Werte nicht enthalten | + +## Stack-Inventar + +### Apps + +| Stack | Compose | Services / Images | Traefik Hosts | Networks | Ports | Abhaengigkeiten | +|---|---|---|---|---|---|---| +| BentoPDF | `apps/bentopdf/docker-compose.yml` | `bentopdf` -> `bentopdfteam/bentopdf:2.8.4` | `pdf.kaleschke.info` | `frontend_net` | keine | Traefik + Authelia; COOP/COEP Middleware | +| Homepage | `apps/homepage/docker-compose.yml` | `homepage` -> `ghcr.io/gethomepage/homepage:latest@sha256:...` | `home.kaleschke.info` | `frontend_net` | keine | Docker-Socket read-only fuer Widgets; viele `HOMEPAGE_VAR_*` Env-Keys | +| Immich | `apps/immich/docker-compose.yml` | `immich-server`, `immich-machine-learning`, `database`, `redis` | `immich.kaleschke.info` | `frontend_net`, `immich_default` | keine | `immich-server` depends on `database`, `redis` | +| Mail Archiver | `apps/mail-archiver/docker-compose.yml` | `mail-archiver` -> `s1t5/mailarchiver@sha256:...` | `mail.kaleschke.info` | `frontend_net`, `backend_net` | keine | shared PostgreSQL via env connection string; Internet fuer IMAP | +| Mealie | `apps/mealie/docker-compose.yml` | `mealie`, `mealie-postgres` | `mealie.kaleschke.info` | `frontend_net`, `mealie_internal` | keine | eigene PostgreSQL im internen Netz | +| Nextcloud | `apps/nextcloud/docker-compose.yml` | `nextcloud`, `nextcloud-postgres`, `nextcloud-redis` | `cloud.kaleschke.info` | `frontend_net`, `nextcloud_internal` | keine | native Nextcloud-Auth; eigene DB und Redis | +| ntfy | `apps/ntfy/docker-compose.yml` | `ntfy` -> `binwiederhier/ntfy:latest@sha256:...` | `ntfy.kaleschke.info` | `frontend_net` | keine | mobile Push via upstream `ntfy.sh` | +| Paperless-ngx | `apps/paperless/docker-compose.yml` | `paperless` -> `ghcr.io/paperless-ngx/paperless-ngx:2.20.10` | `paperless.kaleschke.info` | `frontend_net`, `backend_net` | keine | shared PostgreSQL + Redis; DB/Redis via Stack ENV | +| Paperless-GPT | `apps/paperless-gpt/docker-compose.yml` | `paperless-gpt` -> `icereed/paperless-gpt:v0.24.0` | `paperless-gpt.kaleschke.info` | `frontend_net` | keine | Paperless API, Ollama/LLM config | +| Unbound | `apps/unbound/docker-compose.yml` | `unbound` -> `shaanmajid/unbound:latest@sha256:...` | keine | `dns_net` | keine | Upstream Resolver fuer AdGuard | + +### Core / Security / Infra + +| Stack | Compose | Services / Images | Traefik Hosts | Networks | Ports | Abhaengigkeiten | +|---|---|---|---|---|---|---| +| Gitea | `core/gitea/docker-compose.yml` | `gitea` -> `docker.gitea.com/gitea:1.25.4` | `git.kaleschke.info` | `frontend_net` | `222:22/tcp` | SQLite in `/data`; SSH-Port ist dokumentierte Ausnahme | +| Authelia | `security/authelia/docker-compose.yml` | `authelia` -> `authelia/authelia:latest@sha256:...` | `auth.kaleschke.info` | `frontend_net`, `backend_net` | keine | PostgreSQL 17, Redis, Traefik ForwardAuth | +| Vaultwarden | `security/vaultwarden/docker-compose.yml` | `vaultwarden` -> `vaultwarden/server:latest@sha256:...` | `vault.kaleschke.info` | `frontend_net` | keine | Datei-Persistenz, `ADMIN_TOKEN_FILE` | +| ddns-updater | `infra/ddns-updater/docker-compose.yml` | `ddns-updater` -> `ghcr.io/qdm12/ddns-updater:latest@sha256:...` | keine | `frontend_net` | keine | Cloudflare/API-Internetbedarf | +| PostgreSQL 17 | `infra/postgresql17/docker-compose.yml` | `postgresql17` -> `postgres:17` | keine | `backend_net` | keine | shared DB-Cluster | +| Redis | `infra/redis/docker-compose.yml` | `Redis` -> `redis:7-alpine` | keine | `backend_net` | keine | shared Cache, Passwort-Datei | + +### Host Services + +| Stack | Compose | Services / Images | Hosts | Networks | Ports / Mode | Abhaengigkeiten | +|---|---|---|---|---|---|---| +| AdGuard Home | `host-services/Adguard/docker-compose.yml` | `adguard` -> `adguard/adguardhome:v0.107.52` | keine Traefik-Route | `dns_net`, `frontend_net` | `53/tcp`, `53/udp`, `8082:80/tcp` | Unbound in `dns_net`; direkte Ports sind dokumentierte Ausnahme | +| Tailscale | `host-services/tailscale/docker-compose.yml` | `Tailscale-Docker` -> `tailscale/tailscale:stable@sha256:...` | keine | `network_mode: host` | host network | VPN/Remote-Zugang | + +### Operations + +| Stack | Compose | Services / Images | Traefik Hosts | Networks | Ports | Abhaengigkeiten | +|---|---|---|---|---|---|---| +| Backrest | `ops/backrest/docker-compose.yml` | `backrest` -> `ghcr.io/garethgeorge/backrest:latest@sha256:...` | `backrest.kaleschke.info` | `frontend_net`, `backend_net` | keine | breite Backup-Mounts, SSH/Repo-Creds im Appdata | +| Borg UI | `ops/borg-ui/docker-compose.yml` | `borg-ui` -> `ainullcode/borg-ui:latest@sha256:...` | `borg.kaleschke.info` | `frontend_net` | keine | Borg repo, Dump-Scope, Restore-Ziel | +| code-server | `ops/code-server/docker-compose.yml` | `code-server` -> `lscr.io/linuxserver/code-server:latest@sha256:...` | `code.kaleschke.info` | `frontend_net` | keine | Passwort-Datei, Workspace-Mounts | +| Filebrowser | `ops/filebrowser/docker-compose.yml` | `filebrowser` -> `filebrowser/filebrowser:latest@sha256:...` | `files.kaleschke.info` | `frontend_net` | keine | Appdata-Mount, Admin-UI hinter Authelia | +| Glances | `ops/glances/docker-compose.yml` | `glances` -> `nicolargo/glances:latest-full@sha256:...` | `glances.kaleschke.info` | `frontend_net` | keine | Rootfs/Docker-Socket fuer Monitoring | +| Grafana/InfluxDB | `ops/grafana-influxdb/docker-compose.yml` | `grafana`, `influxdb3-core` | `grafana.kaleschke.info` | `frontend_net`, `grafana_influx_internal`, `grafana_influx_lan` | `influxdb3-core`: `${INFLUXDB_BIND_IP:-127.0.0.1}:8181:8181` | InfluxDB LAN-only fuer Home Assistant; Grafana datasource token | +| Hermes Agent | `ops/hermes-agent/docker-compose.yml` | `hermes-gateway`, `hermes-dashboard` -> local build from Dockerfile | `${HERMES_DASHBOARD_HOST}` | `hermes_net`, dashboard zusaetzlich `frontend_net` | `8642` nur expose intern | SSH runner, Home Assistant optional, LLM provider env | +| Komodo | `ops/komodo/docker-compose.yml` | `komodo-core`, `komodo-mongo`, `komodo-periphery` | `komodo.kaleschke.info` | `frontend_net`, `komodo_net` | keine | Mongo, Docker socket, `/mnt/user/services` workspace mount, Gitea DNS override | +| Scrutiny | `ops/scrutiny/docker-compose.yml` | `scrutiny` -> `ghcr.io/starosdev/scrutiny:latest-omnibus@sha256:...` | `scrutiny.kaleschke.info` | `frontend_net` | keine | `privileged: true`, device mounts fuer SMART | +| Speedtest Tracker | `ops/speedtest/docker-compose.yml` | `speedtest-tracker` -> `lscr.io/linuxserver/speedtest-tracker:latest@sha256:...` | `speedtest.kaleschke.info` | `frontend_net` | keine | App key/admin env, SQLite/config path | +| Uptime Kuma | `ops/uptime-kuma/docker-compose.yml` | `UptimeKuma` -> `louislam/uptime-kuma:1@sha256:...` | `uptime.kaleschke.info` | `frontend_net` | keine | Monitor-State in Appdata | + +### Traefik + +| Stack | Compose | Service / Image | Hosts | Networks | Ports | Abhaengigkeiten | +|---|---|---|---|---|---|---| +| Traefik | `traefik/docker-compose.yml` | `traefik` -> `traefik:v3.6` | `traefik.kaleschke.info` | `frontend_net`, `backend_net` | `80:80/tcp`, `443:443/tcp` | Docker provider, Cloudflare DNS token secret, dynamic config | + +## Traefik Hosts + +| Host | Service | Zugriff | +|---|---|---| +| `auth.kaleschke.info` | Authelia | Auth provider / bypass fuer eigene Domain | +| `backrest.kaleschke.info` | Backrest | Traefik + Authelia | +| `borg.kaleschke.info` | Borg UI | Traefik + Authelia | +| `cloud.kaleschke.info` | Nextcloud | Traefik, native App-Auth | +| `code.kaleschke.info` | code-server | Traefik + Authelia | +| `files.kaleschke.info` | Filebrowser | Traefik + Authelia | +| `git.kaleschke.info` | Gitea Web | Traefik | +| `glances.kaleschke.info` | Glances | Traefik + Authelia | +| `grafana.kaleschke.info` | Grafana | Traefik + Authelia | +| `home.kaleschke.info` | Homepage | Traefik + Authelia laut Compose; Authelia Template fuehrt Domain als bypass | +| `immich.kaleschke.info` | Immich | Traefik, native App-Auth | +| `komodo.kaleschke.info` | Komodo | Traefik, native Komodo-Auth; keine pauschale ForwardAuth | +| `mail.kaleschke.info` | Mail Archiver | Traefik | +| `mealie.kaleschke.info` | Mealie | Traefik | +| `ntfy.kaleschke.info` | ntfy | Traefik | +| `paperless.kaleschke.info` | Paperless-ngx | Traefik | +| `paperless-gpt.kaleschke.info` | Paperless-GPT | Traefik + Authelia | +| `pdf.kaleschke.info` | BentoPDF | Traefik + Authelia + COOP/COEP | +| `scrutiny.kaleschke.info` | Scrutiny | Traefik + Authelia | +| `speedtest.kaleschke.info` | Speedtest Tracker | Traefik + Authelia | +| `traefik.kaleschke.info` | Traefik Dashboard | Traefik + Authelia | +| `uptime.kaleschke.info` | Uptime Kuma | Traefik + Authelia | +| `vault.kaleschke.info` | Vaultwarden | Traefik | + +## Networks + +| Network | Typ / Status | Nutzer | +|---|---|---| +| `frontend_net` | external bridge | Web-/Proxy-Netz fuer Traefik und alle gerouteten UIs | +| `backend_net` | external/internal laut Architektur | PostgreSQL 17, Redis, Authelia, Paperless, Mail Archiver, Traefik | +| `dns_net` | App-/Host-Netz | AdGuard Home und Unbound | +| `immich_default` | Compose-intern, `internal: true` | Immich Server, ML, Postgres, Redis | +| `mealie_internal` | Compose-intern | Mealie und Mealie Postgres | +| `nextcloud_internal` | Compose-intern | Nextcloud, Nextcloud Postgres, Nextcloud Redis | +| `grafana_influx_internal` | Compose-intern, `internal: true` | Grafana und InfluxDB | +| `grafana_influx_lan` | Compose-intern bridge | InfluxDB Host-Port-Publishing fuer LAN Writer | +| `komodo_net` | Compose-intern, `internal: true` | Komodo Core, Mongo, Periphery | +| `hermes_net` | Compose-intern bridge | Hermes Gateway/Dashboard | +| `host` | Host-Netz | Tailscale; Plex historisch ausserhalb Repo | + +## Volumes und Datenpfade + +| Bereich | Wichtige Pfade | +|---|---| +| Traefik | `/mnt/user/appdata/traefik/dynamic`, `/mnt/user/appdata/traefik/letsencrypt`, Cloudflare Secret | +| Gitea | `/mnt/user/services/gitea/data` | +| Authelia | `/mnt/user/appdata/authelia/config`, Authelia Secret-Dateien | +| Vaultwarden | `/mnt/user/appdata/vaultwarden`, Admin-Token-Datei | +| PostgreSQL 17 | `/mnt/user/appdata/postgresql17`, `postgres_password.txt` | +| Redis | `/mnt/user/appdata/redis`, `redis_password.txt` | +| Paperless | `/mnt/user/appdata/paperless-ngx/data`, `/mnt/user/documents/paperless`, `/mnt/user/documents/scans_inbox` | +| Immich | `/mnt/user/photos/immich`, `/mnt/user/photos/family_archive`, `/mnt/user/appdata/immich_postgres`, `model-cache` | +| Mealie | `/mnt/user/appdata/mealie/data`, `/mnt/user/appdata/mealie/postgres` | +| Mail Archiver | `/mnt/user/appdata/mailarchiver/data-protection-keys` | +| Nextcloud | `/mnt/user/appdata/nextcloud/html`, `/mnt/user/documents/nextcloud-data`, `/mnt/user/appdata/nextcloud/postgres`, `/mnt/user/appdata/nextcloud/redis` | +| Homepage | `/mnt/user/appdata/homepage`, `/mnt/user/appdata/homepage/images`, Docker socket read-only | +| ntfy | `/mnt/user/appdata/ntfy` | +| Paperless-GPT | `/mnt/user/appdata/paperless-gpt/data`, `/mnt/user/appdata/paperless-gpt/prompts` | +| AdGuard | `/mnt/user/appdata/adguard/work`, `/mnt/user/appdata/adguard/conf` | +| Tailscale | `/mnt/user/appdata/tailscale` | +| Backrest | `/mnt/user/appdata/backrest/*`, broad `/mnt/user/...` source mounts, remote repo mount | +| Borg UI | `/mnt/user/appdata/borg-ui/data`, `/mnt/user/appdata/borg-ui/cache`, `/mnt/user/backups/borg/dumps`, selected restore/source mounts | +| code-server | `/mnt/user/appdata/code-server`, `/mnt/user/services/dev`, Homepage production mount | +| Filebrowser | `/mnt/user/appdata`, Filebrowser database/config paths | +| Glances | `/`, Docker socket, `/etc/os-release` | +| Scrutiny | `/mnt/user/appdata/scrutiny/*`, `/run/udev`, selected `/dev/...` disks | +| Speedtest | `/mnt/user/appdata/speedtest-tracker/config` | +| Uptime Kuma | `/mnt/user/appdata/uptime-kuma` | +| Grafana/InfluxDB | `/mnt/user/appdata/grafana`, Grafana provisioning, `/mnt/user/appdata/influxdb3/data`, `/mnt/user/appdata/influxdb3/plugins` | +| Hermes Agent | `/mnt/user/appdata/hermes-agent/data`, `/mnt/user/appdata/hermes-agent/ssh`, SSH private key path | +| Komodo | `komodo_keys`, `/mnt/user/appdata/komodo/core`, `/mnt/user/appdata/komodo/mongo`, `/mnt/user/appdata/komodo/periphery`, `/mnt/user/services` | + +## Secrets und Env-Hinweise + +| Dienst / Stack | Secret-/Env-Hinweise ohne Werte | +|---|---| +| Traefik | `cloudflare_dns_api_token` als Docker Secret / `CF_DNS_API_TOKEN_FILE` | +| Authelia | JWT, Session, Storage Encryption, Postgres Password via `_FILE` | +| Vaultwarden | `ADMIN_TOKEN_FILE` | +| PostgreSQL 17 | `POSTGRES_PASSWORD_FILE` | +| Redis | Passwort-Datei und Startkommando | +| Paperless | `PAPERLESS_DBPASS`, `PAPERLESS_REDIS` als Komodo Stack ENV | +| Immich | `IMMICH_DB_PASSWORD` Stack ENV; `immich_postgres_password.txt` fuer Postgres | +| Mail Archiver | `MAILARCHIVER_DB_CONNECTION`, `MAILARCHIVER_AUTH_PASSWORD` als Stack ENV | +| Homepage | viele `HOMEPAGE_VAR_*` Stack ENV Keys fuer Tokens/Logins | +| Speedtest | `APP_KEY`, `ADMIN_PASSWORD` als Stack ENV | +| Nextcloud | Admin User, Admin Password, Postgres Password via Secret-Dateien | +| Komodo | `KOMODO_SECRET_KEY`, `KOMODO_JWT_SECRET`, `KOMODO_MONGO_PASSWORD`, `KOMODO_PERIPHERY_PASSKEY`; Mongo Passwort-Datei | +| Borg UI | Borg Credentials, Admin Login, SSH Keys in persistentem Appdata, nicht im Git | +| Hermes Agent | provider keys, API server key, messaging tokens, Home Assistant token in Host `.env`; SSH private key als Host-Secret | +| Grafana/InfluxDB | Grafana Admin Password, InfluxDB Admin Token JSON, Grafana Datasource Token | + +## Skripte + +| Skript | Ausfuehrungsort | Zweck | +|---|---|---| +| `ops/borg-ui/scripts/pre-backup-dumps.sh` | Unraid Host, nicht Borg-UI Inline-Hook | erzeugt aktuelle Dumps unter `/mnt/user/backups/borg/dumps/latest` | + +Das Skript liest Secret-Dateien auf dem Host und schreibt Dump-Artefakte. Bei Analyse niemals Secret-Inhalte ausgeben. + +## Unsicherheiten / TODOs aus Repo-Sicht + +- `ops/hermes-agent/stack.env` ist eine echte Env-Datei im Repo; Werte wurden nicht gelesen. Pruefen, ob das dauerhaft gewollt ist oder ein `stack.env.example` plus Git-Ignore besser waere. +- Authelia `configuration.yml` ist als Template markiert, enthaelt aber konkrete Domains. Pruefen, ob der Host-Stand und die Repo-Template-Datei bewusst getrennt bleiben. +- Authelia Access-Control und Compose-Middlewares wirken nicht ueberall deckungsgleich, z. B. Homepage ist in Compose mit Authelia-Middleware geroutet, in Authelia aber als bypass gelistet. +- `apps/mealie` nutzt in Compose `mealie_internal`; Architektur-Doku nennt teils `mealie_mealie_internal`. Laufzeitnamen koennen durch Compose-Projektpraefixe abweichen. +- `backend_net` ist in der Architektur als `internal: true` beschrieben; einzelne Compose-Dateien referenzieren es external. Live-Netz-Attribute bei Drift-Fragen pruefen. +- Einige Images bleiben trotz Digest-Pin semantisch auf mutable Tags (`latest@sha256`, `release@sha256`). Das ist bewusst dokumentiert, aber bei Updates gesondert pruefen. +- `scrutiny` bleibt `privileged: true`; dokumentierte Ausnahme, aber weiterhin pruefenswert. +- `Plex-Media-Server` ist als historischer Host-Sonderfall dokumentiert, aber nicht als Repo-Compose-Stack enthalten. +- BentoPDF und Hermes Agent koennen je nach Live-Stand vorbereitet statt produktiv sein; vor Deploy-/Rollback-Fragen in Komodo/Runtime pruefen. diff --git a/docs/SERVICE_CATALOG.md b/docs/SERVICE_CATALOG.md new file mode 100644 index 0000000..6533b7d --- /dev/null +++ b/docs/SERVICE_CATALOG.md @@ -0,0 +1,88 @@ +# Service Catalog + +Stand: 2026-05-04 + +Dieser Katalog beschreibt produktive und repo-vorbereitete Dienste aus Sicht von Betrieb, Restore und KI-Kontext. Er basiert auf dem Repo-Sollzustand. Vor produktiven Eingriffen immer den Live-Zustand in Komodo/Docker pruefen. + +Secret-Werte sind nicht enthalten. Es werden nur Secret-Namen, Env-Key-Namen und Pfade genannt. + +## Core / Ingress / DNS + +| Service | Zweck | Autoritativer Pfad | URL / Zugang | Abhaengigkeiten | Datenpfade | Backup / Restore | Traefik | Besonderheiten / TODOs | +|---|---|---|---|---|---|---|---|---| +| `traefik` | zentraler Reverse Proxy, TLS, Docker-Label-Routing | `traefik/docker-compose.yml`, `traefik/dynamic/*` | `https://traefik.kaleschke.info` | Docker socket, Cloudflare DNS API, `frontend_net`, `backend_net` | `/mnt/user/appdata/traefik/dynamic`, `/mnt/user/appdata/traefik/letsencrypt` | Tier 1, Share/Borg | ja, eigene Dashboard-Route mit Authelia | Host-Ports 80/443 sind zentrale Ausnahme; dynamic configs werden nicht automatisch von Komodo deployed | +| `adguard` | DNS-Server / LAN DNS | `host-services/Adguard/docker-compose.yml` | LAN-Port `53`, Admin `8082` | `dns_net`, `frontend_net`, Unbound | `/mnt/user/appdata/adguard/conf`, `/mnt/user/appdata/adguard/work` | Tier 1, config relevant | nein | Direkte Ports 53 und 8082 dokumentierte Ausnahme; Admin-Port spaeter ggf. absichern | +| `unbound` | Upstream DNS Resolver fuer AdGuard | `apps/unbound/docker-compose.yml` | intern | `dns_net` | `/mnt/user/appdata/unbound/config` | rebuildbar / config relevant | nein | intern isoliert | +| `tailscale` | VPN/Remote-Zugang | `host-services/tailscale/docker-compose.yml` | Tailscale | Host-Netz | `/mnt/user/appdata/tailscale` | Tier 1, State relevant | nein | `network_mode: host` ist dokumentierte Ausnahme | +| `gitea` | Git-Server / origin fuer GitOps | `core/gitea/docker-compose.yml` | `https://git.kaleschke.info`, SSH `222` | Traefik, `frontend_net` | `/mnt/user/services/gitea/data` | Tier 1, SQLite in `/data` | ja | SSH-Port 222 direkte Host-Port-Ausnahme; ohne externen Mirror im DR kritisch | + +## Security / Identity + +| Service | Zweck | Autoritativer Pfad | URL / Zugang | Abhaengigkeiten | Datenpfade | Backup / Restore | Traefik | Besonderheiten / TODOs | +|---|---|---|---|---|---|---|---|---| +| `authelia` | ForwardAuth / zentrale Auth fuer Admin-UIs | `security/authelia/docker-compose.yml`, `security/authelia/configuration.yml` | `https://auth.kaleschke.info` | PostgreSQL 17, Redis, Traefik | `/mnt/user/appdata/authelia/config`, Authelia Secret-Dateien | Tier 1, config + DB + secrets | ja | Template im Repo, Host-Datei pruefen; Access-Control und Compose-Middleware bei Aenderungen abgleichen | +| `vaultwarden` | Passwort-Tresor | `security/vaultwarden/docker-compose.yml` | `https://vault.kaleschke.info` | Traefik, `frontend_net` | `/mnt/user/appdata/vaultwarden` | Tier 1 | ja | `ADMIN_TOKEN_FILE`; keine direkten Ports | + +## Shared Infrastructure + +| Service | Zweck | Autoritativer Pfad | URL / Zugang | Abhaengigkeiten | Datenpfade | Backup / Restore | Traefik | Besonderheiten / TODOs | +|---|---|---|---|---|---|---|---|---| +| `postgresql17` | shared PostgreSQL Cluster | `infra/postgresql17/docker-compose.yml` | intern | `backend_net` | `/mnt/user/appdata/postgresql17`, `postgres_password.txt` | Tier 1; Dumps unter `/mnt/user/backups/borg/dumps/latest` | nein | keine Host-Ports; raw DB nicht primaerer Restore-Weg | +| `Redis` | shared Redis Cache | `infra/redis/docker-compose.yml` | intern | `backend_net` | `/mnt/user/appdata/redis`, `redis_password.txt` | transiente Daten, bewusst nicht kritisch | nein | Passwort-Datei; optional named volume offen | +| `ddns-updater` | Cloudflare/DDNS Aktualisierung | `infra/ddns-updater/docker-compose.yml` | intern | Internetzugang, `frontend_net` | `/mnt/user/appdata/ddns-updater` | rebuildbar | nein | bleibt bewusst in `frontend_net`, weil `backend_net` internal ist | + +## Public / User Apps + +| Service | Zweck | Autoritativer Pfad | URL / Zugang | Abhaengigkeiten | Datenpfade | Backup / Restore | Traefik | Besonderheiten / TODOs | +|---|---|---|---|---|---|---|---|---| +| `paperless-ngx` | Dokumentenmanagement | `apps/paperless/docker-compose.yml` | `https://paperless.kaleschke.info` | PostgreSQL 17, Redis, Traefik | `/mnt/user/appdata/paperless-ngx/data`, `/mnt/user/documents/paperless`, `/mnt/user/documents/scans_inbox` | Tier 2, Borg + `postgresql17-paperless.dump` | ja | DB/Redis Secrets bleiben bewusst Stack ENV | +| `paperless-gpt` | KI-Ergaenzung fuer Paperless | `apps/paperless-gpt/docker-compose.yml` | `https://paperless-gpt.kaleschke.info` | Paperless API, LLM/Ollama, Traefik | `/mnt/user/appdata/paperless-gpt/data`, `/mnt/user/appdata/paperless-gpt/prompts` | Tier 2 | ja + Authelia | API Token als Stack ENV; OCR/LLM-Konfig bei Aenderungen pruefen | +| `immich_server` | Foto-/Video-App | `apps/immich/docker-compose.yml` | `https://immich.kaleschke.info` | Immich Postgres, Immich Redis, ML, Traefik | `/mnt/user/photos/immich`, `/mnt/user/photos/family_archive` | Tier 2, Borg + `immich.dump` | ja | native App-Auth; externes Fotoarchiv gemountet | +| `immich_postgres` | Immich-Datenbank | `apps/immich/docker-compose.yml` | intern | `immich_default` | `/mnt/user/appdata/immich_postgres`, `immich_postgres_password.txt` | Dump `immich.dump` | nein | nie ins `frontend_net` | +| `immich_redis` | Immich Cache | `apps/immich/docker-compose.yml` | intern | `immich_default` | kein kritischer Pfad dokumentiert | rebuildbar | nein | Architektur nennt anonymes Volume -> named volume als offenes Thema | +| `immich_machine_learning` | Immich ML | `apps/immich/docker-compose.yml` | intern | `immich_default` | `model-cache` | rebuildbar | nein | intern-only | +| `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/postgres`, `mealie_postgres_password.txt` | Dump `mealie.dump` | nein | interne DB | +| `mail-archiver` | Mail-Archivierung | `apps/mail-archiver/docker-compose.yml` | `https://mail.kaleschke.info` | PostgreSQL 17, Internet/IMAP, Traefik | `/mnt/user/appdata/mailarchiver/data-protection-keys` | Tier 2, `postgresql17-mailarchiver.dump` | ja | Hybrid-Dienst: `frontend_net` fuer Internet, `backend_net` fuer DB | +| `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, Share + app-eigene DB | ja | native App-Auth ohne zentrale ForwardAuth; WebDAV/CardDAV beachten | +| `nextcloud-postgres` | Nextcloud-Datenbank | `apps/nextcloud/docker-compose.yml` | intern | `nextcloud_internal` | `/mnt/user/appdata/nextcloud/postgres`, `nextcloud_postgres_password.txt` | Teil von Nextcloud-Restore | nein | interne DB | +| `nextcloud-redis` | Nextcloud Cache/Locking | `apps/nextcloud/docker-compose.yml` | intern | `nextcloud_internal` | `/mnt/user/appdata/nextcloud/redis` | Teil von Nextcloud-Restore | nein | interne Redis | +| `ntfy` | Push-Benachrichtigungen | `apps/ntfy/docker-compose.yml` | `https://ntfy.kaleschke.info` | Traefik, upstream mobile push | `/mnt/user/appdata/ntfy` | Tier 2 | ja | `NTFY_BEHIND_PROXY=true`; Monitoring/Borg-Benachrichtigungen | +| `bentopdf` | PDF-Tooling / Ersatz fuer Stirling-PDF | `apps/bentopdf/docker-compose.yml` | `https://pdf.kaleschke.info` | Traefik + Authelia | keine kritische Persistenz im Compose | Tier 3, rebuildbar | ja + Authelia | COOP/COEP per Middleware; fachliche Abnahme/Live-Status pruefen | + +## Operations / Monitoring / Admin + +| Service | Zweck | Autoritativer Pfad | URL / Zugang | Abhaengigkeiten | Datenpfade | Backup / Restore | Traefik | Besonderheiten / TODOs | +|---|---|---|---|---|---|---|---|---| +| `homepage` | Start-Dashboard | `apps/homepage/docker-compose.yml` | `https://home.kaleschke.info` | Traefik, Docker socket read-only, viele API Tokens | `/mnt/user/appdata/homepage`, `/mnt/user/appdata/homepage/images` | Tier 2 | ja + Authelia laut Compose | Authelia Template listet `home` als bypass; abgleichen | +| `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 | +| `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 | ja + Authelia | breite Mounts bewusst; `/local/secrets` im DR-Scope | +| `backrest` | Backup-Admin-Dienst / Legacy-Backup-Ebene | `ops/backrest/docker-compose.yml` | `https://backrest.kaleschke.info` | Traefik + Authelia, Repo/SSH-Mounts | `/mnt/user/appdata/backrest/*`, broad source mounts | Tier 3 | ja + Authelia | breite Mounts bewusst dokumentieren | +| `uptime-kuma` | Monitoring / Uptime Checks | `ops/uptime-kuma/docker-compose.yml` | `https://uptime.kaleschke.info` | Traefik + Authelia | `/mnt/user/appdata/uptime-kuma` | Tier 3 | ja + Authelia | Monitore nach Restore pruefen | +| `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 | Rootfs und Docker-Socket Mounts | +| `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 | `privileged: true` dokumentierte Ausnahme | +| `speedtest-tracker` | Speedtest-Monitoring | `ops/speedtest/docker-compose.yml` | `https://speedtest.kaleschke.info` | Traefik + Authelia | `/mnt/user/appdata/speedtest-tracker/config` | Tier 3 | ja + Authelia | `APP_KEY`, `ADMIN_PASSWORD` Stack ENV | +| `filebrowser` | Datei-Browser fuer Appdata | `ops/filebrowser/docker-compose.yml` | `https://files.kaleschke.info` | Traefik + Authelia | `/mnt/user/appdata/filebrowser/*`, breiter `/mnt/user/appdata` Mount | Tier 3 | ja + Authelia | Mounts langfristig einschraenken | +| `code-server` | Web-Editor / Operations Workspace | `ops/code-server/docker-compose.yml` | `https://code.kaleschke.info` | Traefik + Authelia | `/mnt/user/appdata/code-server`, `/mnt/user/services/dev` | Tier 3 | ja + Authelia | `PASSWORD_FILE`; Workspaces beachten | +| `grafana` | Metrik-Dashboard | `ops/grafana-influxdb/docker-compose.yml` | `https://grafana.kaleschke.info` | Traefik + Authelia, InfluxDB 3 Core | `/mnt/user/appdata/grafana`, Grafana provisioning | Tier 3 | ja + Authelia | Datasource wird provisioniert, Token ueber Secret | +| `influxdb3-core` | Zeitreihen-/Metrikdaten fuer Grafana und Home Assistant | `ops/grafana-influxdb/docker-compose.yml` | LAN `8181` je `INFLUXDB_BIND_IP`, keine Public URL | Grafana, Home Assistant Writer | `/mnt/user/appdata/influxdb3/data`, `/mnt/user/appdata/influxdb3/plugins` | Tier 3 | nein | LAN-only Host-Port-Ausnahme; `401 Unauthorized` beim Curl ohne Token ist erwarteter Reachability-Test | +| `hermes-gateway` | Hermes Agent Gateway/API intern | `ops/hermes-agent/docker-compose.yml` | intern `8642` auf `hermes_net` | SSH Runner, LLM Provider, optional Home Assistant | `/mnt/user/appdata/hermes-agent/data`, SSH key path | noch nicht in Restore Matrix | nein | kein Docker socket; terminal backend `ssh`; echte `.env` auf Host-Appdata | +| `hermes-dashboard` | Hermes Dashboard | `ops/hermes-agent/docker-compose.yml` | `${HERMES_DASHBOARD_HOST}` | `hermes-gateway`, Traefik + Authelia | shared read-only data mount | noch nicht in Restore Matrix | ja + Authelia | Compose-Profil `dashboard`; Live-Status pruefen | + +## Backup- und Restore-Hinweise + +- Tier-1-Dienste stehen in `docs/RESTORE_MATRIX.md` und `docs/DISASTER_RECOVERY.md`. +- Dump-Erzeugung erfolgt host-seitig ueber `ops/borg-ui/scripts/pre-backup-dumps.sh`. +- Dump-Ziel: `/mnt/user/backups/borg/dumps/latest`. +- Raw Live-DB-Pfade sind meist nicht der primaere Restore-Weg; bevorzugt werden Dumps plus Appdaten. +- Borg UI nimmt bewusst `/local/secrets` in den DR-Scope auf. + +## Bekannte offene Fragen + +- Hermes Agent ist dokumentiert, aber noch nicht vollstaendig in Restore Matrix / DR Bootstrap eingeordnet. +- Authelia Template vs. Compose-Middleware sollte bei Auth-Aenderungen explizit abgeglichen werden. +- Filebrowser- und Backrest-Mounts sind breit und bewusst, aber bei zukuenftigen Hardening-Sprints Kandidaten. +- Scrutiny bleibt privilegiert; nur mit klarer Begruendung aendern. +- BentoPDF und Hermes Dashboard koennen je nach Live-Stand vorbereitet statt produktiv sein.