diff --git a/HOMELAB_ARCHITECTURE_MASTER_V2.md b/HOMELAB_ARCHITECTURE_MASTER_V2.md index 6ed5839..3bbcb1b 100644 --- a/HOMELAB_ARCHITECTURE_MASTER_V2.md +++ b/HOMELAB_ARCHITECTURE_MASTER_V2.md @@ -143,7 +143,6 @@ Diese Dienste sind über echte `*.kaleschke.info`-Domains erreichbar: - `ntfy` — ntfy.kaleschke.info - `gitea` (Web) — git.kaleschke.info - `immich_server` — immich.kaleschke.info -- `mail-archiver` — mail.kaleschke.info - `nextcloud` — cloud.kaleschke.info ### 4.2 Nicht öffentlich / nur Tailscale oder Traefik + Middleware @@ -158,6 +157,7 @@ Diese Dienste sind **keine Public Apps**: - `borg-ui` — borg.kaleschke.info (Middleware) - `homepage` — home.kaleschke.info (Middleware) - `paperless-gpt` — paperless-gpt.kaleschke.info (Middleware) +- `mail-archiver` — mail.kaleschke.info (Middleware + App-Auth) - `glances` — glances.kaleschke.info (Middleware) - `speedtest-tracker` — speedtest.kaleschke.info (Middleware) - `bentopdf` — pdf.kaleschke.info (Middleware) @@ -262,12 +262,12 @@ Legende Status: | `nextcloud-postgres` | ✅ | `nextcloud_internal` | intern | app-eigene Nextcloud-Datenbank mit `_FILE`-Secret | — | | `nextcloud-redis` | ✅ | `nextcloud_internal` | intern | app-eigener Cache fuer File Locking / Sessions | — | -### 7.4 Öffentliche Apps +### 7.4 Produktive Apps | Container | Status | Soll-Netz(e) | Finaler Zugang | Finaler Sollzustand | Offene Punkte | |---|---|---|---|---|---| | `paperless-ngx` | ✅ | `frontend_net`, `backend_net` | Traefik | aktiv via `paperless.kaleschke.info` | — | -| `mail-archiver` | ✅ | `frontend_net`, `backend_net` | Traefik | aktiv via `mail.kaleschke.info`; IMAP-Abruf + DB-Zugang | — | +| `mail-archiver` | ✅ | `frontend_net`, `backend_net` | Traefik + Middleware | aktiv via `mail.kaleschke.info`; IMAP-Abruf + DB-Zugang; App-eigene Auth bleibt zusaetzliche Schutzschicht | — | | `mealie` | ✅ | `frontend_net`, `mealie_mealie_internal` | Traefik | sauber getrennte App/DB-Struktur | — | | `ntfy` | ✅ | `frontend_net` | Traefik | aktiv via `ntfy.kaleschke.info`, Git-Stack | — | | `gitea` | ✅ | `frontend_net` | Traefik + SSH-Port 222 | Web via Traefik, SSH direkt gebunden | — | @@ -286,7 +286,7 @@ Legende Status: | `borg-ui` | ✅ | `frontend_net` | Traefik + Middleware | produktiver Borg-/Restore-Dienst; `/local/secrets` ist bewusst Teil des Restore-Scopes | BorgBase-Repo und Key laufend pflegen | | `paperless-gpt` | ✅ | `frontend_net` | Traefik + Middleware | aktiv via `paperless-gpt.kaleschke.info` | — | | `bentopdf` | ✅ vorbereitet | `frontend_net` | Traefik + Middleware | PDF-Tooling via `pdf.kaleschke.info`; browserseitige Verarbeitung, COOP/COEP fuer Office-Konvertierung | Deploy und fachliche Abnahme offen | -| `hermes-dashboard` | ✅ | `frontend_net`, `hermes_net` | Traefik + Middleware | aktiv via `hermes.kaleschke.info`; Dashboard bindet intern mit `--insecure` auf `0.0.0.0`, externe Absicherung ueber Authelia | Restore-Matrix/DR-Einordnung offen | +| `hermes-dashboard` | ✅ | `frontend_net`, `hermes_net` | Traefik + Middleware | aktiv via `hermes.kaleschke.info`; Dashboard bindet intern mit `--insecure` auf `0.0.0.0`, externe Absicherung ueber Authelia | — | ### 7.6 Monitoring / Status @@ -563,7 +563,7 @@ Mutable Tags wie `latest`, `stable`, `release` oder reine Major-Tags wurden auf Bleibt bewusst in `frontend_net` statt `backend_net`, weil `backend_net` `internal: true` ist und ddns-updater die Cloudflare-API erreichen muss. ### mail-archiver — Hybrid-Dienst -Benötigt `backend_net` (PostgreSQL) + `frontend_net` (IMAP-Abruf von GMX/Gmail). Kein reiner Backend-Dienst. Aktuell via Traefik unter `mail.kaleschke.info` geroutet. +Benötigt `backend_net` (PostgreSQL) + `frontend_net` (IMAP-Abruf von GMX/Gmail). Kein reiner Backend-Dienst. Die Web-UI ist via Traefik unter `mail.kaleschke.info` erreichbar und wird durch `authelia@file,secure-headers@file` plus App-eigene Auth geschuetzt. ### Netzwerk-Standard für Apps mit Datenbanken - App → `frontend_net` + internes Netzwerk diff --git a/apps/mail-archiver/docker-compose.yml b/apps/mail-archiver/docker-compose.yml index 65568ad..e442945 100644 --- a/apps/mail-archiver/docker-compose.yml +++ b/apps/mail-archiver/docker-compose.yml @@ -24,6 +24,7 @@ services: - "traefik.http.routers.mail-archiver.entrypoints=websecure" - "traefik.http.routers.mail-archiver.tls=true" - "traefik.http.routers.mail-archiver.tls.certresolver=le" + - "traefik.http.routers.mail-archiver.middlewares=authelia@file,secure-headers@file" - "traefik.http.services.mail-archiver.loadbalancer.server.port=5000" networks: backend_net: diff --git a/docs/AI_CONTEXT.md b/docs/AI_CONTEXT.md index a039d7d..459cf0e 100644 --- a/docs/AI_CONTEXT.md +++ b/docs/AI_CONTEXT.md @@ -50,6 +50,7 @@ Traefik ist der zentrale Web-Einstieg fuer HTTP(S). Admin-/Ops-UIs liegen entwed ### 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. +- Mail Archiver ist ein Hybrid-Dienst mit `frontend_net` fuer IMAP/Traefik und `backend_net` fuer PostgreSQL; die Web-UI liegt hinter Authelia und behaelt zusaetzlich App-eigene Auth. ### Monitoring / Metriken @@ -137,7 +138,7 @@ Disaster Recovery folgt einer Bootstrap-Reihenfolge: 2. PostgreSQL, Authelia, Redis, Gitea 3. Komodo 4. kritische Apps -5. restliche Apps/Ops +5. restliche Apps/Ops inklusive Hermes Agent ## Typische Arbeitsweise im Repo diff --git a/docs/DISASTER_RECOVERY.md b/docs/DISASTER_RECOVERY.md index 4bcc8e8..9a5d6ee 100644 --- a/docs/DISASTER_RECOVERY.md +++ b/docs/DISASTER_RECOVERY.md @@ -139,6 +139,7 @@ Erwartete Basis unter `/mnt/user/appdata/secrets/`: - `postgres_password.txt` - `redis_password.txt` - `vaultwarden_admin_token.txt` +- `hermes_runner_id_ed25519` Weitere relevante Secret-Pfade: @@ -154,6 +155,8 @@ Diese Werte sind vor dem Start der betroffenen Dienste zu pruefen bzw. wieder in - `IMMICH_DB_PASSWORD` - `MAILARCHIVER_DB_CONNECTION` - `MAILARCHIVER_AUTH_PASSWORD` +- `HERMES_DASHBOARD_HOST` +- Hermes Host-`.env` fuer Provider-/API-/Home-Assistant-Tokens - `KOMODO_SECRET_KEY` - `KOMODO_JWT_SECRET` - `KOMODO_MONGO_PASSWORD` @@ -267,7 +270,8 @@ Ziel: 24. `ops/scrutiny/` 25. `ops/speedtest/` 26. `ops/grafana-influxdb/` -27. `infra/ddns-updater/` +27. `ops/hermes-agent/` +28. `infra/ddns-updater/` **Regel:** Nach jeder Stufe kurz pruefen, bevor die naechste beginnt. @@ -303,6 +307,7 @@ Ziel: - Borg UI startet und kennt sein Repo noch - aktuelle Dump-Artefakte sind vorhanden - Uptime Kuma / Homepage / ntfy sind wieder da +- Hermes Gateway und Dashboard starten; `hermes.kaleschke.info` leitet anonym zu Authelia weiter --- @@ -348,6 +353,19 @@ Relevant: - Dump-Ziel: `/mnt/user/backups/borg/dumps/latest` - Skript: `ops/borg-ui/scripts/pre-backup-dumps.sh` +### Hermes Agent + +Hermes nutzt einen lokalen Build und hostseitige Runtime-Daten. + +Vor dem Start muessen vorhanden sein: + +- `/mnt/user/appdata/hermes-agent/data` +- `/mnt/user/appdata/hermes-agent/ssh` +- `/mnt/user/appdata/secrets/hermes_runner_id_ed25519` +- die hostseitige Hermes `.env` mit Provider-/API-/Home-Assistant-Tokens + +Smoke-Test: `hermes-gateway` healthcheck ist gruen, `hermes.kaleschke.info` leitet fuer anonyme Requests zu Authelia weiter. + ### Gitea Wenn weder externer Mirror noch lokaler Clone verfuegbar sind, ist `services/gitea/data` selbst Teil des kritischen Wiederanlaufs. diff --git a/docs/MIGRATION_LOG.md b/docs/MIGRATION_LOG.md index 88897c6..24ec218 100644 --- a/docs/MIGRATION_LOG.md +++ b/docs/MIGRATION_LOG.md @@ -16,6 +16,12 @@ Dieses Dokument ist nur noch ein historischer Verlauf. Der aktuelle operative Ab ## Historische Meilensteine +### 2026-05-06 - Hermes DR und Mail-Archiver Authelia + +- Hermes Agent in `docs/RESTORE_MATRIX.md` und `docs/DISASTER_RECOVERY.md` mit Restore-Pfaden, Secret-/ENV-Hinweisen und Smoke-Test ergaenzt. +- Mail-Archiver Web-UI hinter `authelia@file,secure-headers@file` gelegt; App-eigene Auth bleibt als zweite Schutzschicht bestehen. +- M10/Komodo blieb unveraendert. + ### 2026-05-05 - N-Aufraeum-Sprint - Obsolete Compose-Top-Level-Felder `version: "3.9"` aus Immich, Mail Archiver und Paperless entfernt. diff --git a/docs/REPO_MAP.md b/docs/REPO_MAP.md index 0cde66f..8420b13 100644 --- a/docs/REPO_MAP.md +++ b/docs/REPO_MAP.md @@ -126,7 +126,7 @@ Secret-Werte werden hier nicht dokumentiert. Aufgefuehrt werden nur Variablennam | `home.kaleschke.info` | Homepage | Traefik + Authelia; faellt in Authelia unter die 1FA-Wildcard-Regel | | `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 | +| `mail.kaleschke.info` | Mail Archiver | Traefik + Authelia + App-Auth | | `mealie.kaleschke.info` | Mealie | Traefik | | `ntfy.kaleschke.info` | ntfy | Traefik | | `paperless.kaleschke.info` | Paperless-ngx | Traefik | diff --git a/docs/RESTORE_MATRIX.md b/docs/RESTORE_MATRIX.md index 19aeaff..eeea292 100644 --- a/docs/RESTORE_MATRIX.md +++ b/docs/RESTORE_MATRIX.md @@ -45,7 +45,7 @@ Sie ist die fachliche Ergaenzung zu `docs/DISASTER_RECOVERY.md`. | Paperless-ngx | Borg + Dumps | `/mnt/user/appdata/paperless-ngx/data`, `/mnt/user/documents/paperless`, `/mnt/user/documents/paperless/export`, `/mnt/user/documents/scans_inbox` | `postgresql17-paperless.dump` | `PAPERLESS_DBPASS`, `PAPERLESS_REDIS` | PostgreSQL 17, Redis, Traefik | Web-UI startet, Dokumente vorhanden | | Mealie | Borg + Dump | `/mnt/user/appdata/mealie/data`, optional `/mnt/user/appdata/mealie/postgres` bei lokalem Share-Weiterbetrieb | `mealie.dump` | `mealie_postgres_password.txt` | `mealie-postgres`, Traefik | UI startet, Rezepte vorhanden | | Immich | Borg + Dump | `/mnt/user/photos/immich`, `/mnt/user/photos/family_archive` | `immich.dump` | `IMMICH_DB_PASSWORD`, `immich_postgres_password.txt` | `immich_postgres`, `immich_redis`, Traefik | UI startet, Medienbibliothek sichtbar | -| Mail-Archiver | Borg + Shared Dump | `/mnt/user/appdata/mailarchiver/data-protection-keys` | `postgresql17-mailarchiver.dump` | `MAILARCHIVER_DB_CONNECTION`, `MAILARCHIVER_AUTH_PASSWORD` | PostgreSQL 17, Traefik | Web-UI startet, Archiv laesst sich oeffnen | +| Mail-Archiver | Borg + Shared Dump | `/mnt/user/appdata/mailarchiver/data-protection-keys` | `postgresql17-mailarchiver.dump` | `MAILARCHIVER_DB_CONNECTION`, `MAILARCHIVER_AUTH_PASSWORD` | PostgreSQL 17, Traefik, Authelia | Authelia-Weiterleitung greift; nach Login startet die Web-UI und das Archiv laesst sich oeffnen | | Nextcloud | Borg + Share | `/mnt/user/appdata/nextcloud/html`, `/mnt/user/appdata/nextcloud/postgres`, `/mnt/user/appdata/nextcloud/redis`, `/mnt/user/documents/nextcloud-data` | app-eigene PostgreSQL unter `/mnt/user/appdata/nextcloud/postgres` | `nextcloud_admin_user.txt`, `nextcloud_admin_password.txt`, `nextcloud_postgres_password.txt` | `nextcloud-postgres`, `nextcloud-redis`, Traefik | Web-UI startet, Login funktioniert, Dateien sichtbar | | Homepage | Borg / Share | `/mnt/user/appdata/homepage` | keine | `HOMEPAGE_VAR_*` | Traefik, Authelia | Dashboard startet, Widgets laden | | ntfy | Borg / Share | `/mnt/user/appdata/ntfy` | keine | keine besonderen Secret-Dateien dokumentiert | Traefik | UI und Push-Endpunkt erreichbar | @@ -67,6 +67,7 @@ Sie ist die fachliche Ergaenzung zu `docs/DISASTER_RECOVERY.md`. | BentoPDF | Rebuildbar | keine kritische Persistenz; alte Stirling-PDF-Daten unter `/mnt/user/appdata/stirling-pdf` bis zur Abnahme behalten | keine | keine separaten Secret-Dateien dokumentiert | Traefik, Authelia | UI startet, PDF-Tools verfuegbar, Office-Konvertierung ueber HTTPS funktioniert | | Grafana | Share | `/mnt/user/appdata/grafana`, inklusive `provisioning/datasources/influxdb.yml` | SQLite im App-Pfad | `grafana_admin_password.txt`, `grafana_influxdb_token.txt` | Traefik, Authelia, InfluxDB 3 Core | UI startet, InfluxDB-Datenquelle testet erfolgreich | | InfluxDB 3 Core | Share | `/mnt/user/appdata/influxdb3/data`, `/mnt/user/appdata/influxdb3/plugins` | dateibasierter Object Store | `influxdb3_admin_token.json` | internes `grafana_influx_internal` Netz | `homelab`-Datenbank vorhanden, Grafana kann SQL-Abfrage ausfuehren | +| Hermes Agent | Borg / Share | `/mnt/user/appdata/hermes-agent/data`, `/mnt/user/appdata/hermes-agent/ssh` | keine eigene DB | Host-`.env` fuer Provider-/API-/Home-Assistant-Tokens, `hermes_runner_id_ed25519`, `HERMES_DASHBOARD_HOST` | Traefik, Authelia, `hermes_net` | Gateway-Health ist ok, Dashboard leitet anonym zu Authelia weiter, SSH-Runner-Key ist vorhanden | | ddns-updater | Rebuildbar | geringe Persistenzrelevanz | keine | Provider-Zugang ueber Stack ENV | Internetzugang | Update-Job laeuft | --- diff --git a/docs/SERVICE_CATALOG.md b/docs/SERVICE_CATALOG.md index 54bf3a6..293d6d1 100644 --- a/docs/SERVICE_CATALOG.md +++ b/docs/SERVICE_CATALOG.md @@ -43,7 +43,7 @@ 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` | `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 | +| `mail-archiver` | Mail-Archivierung | `apps/mail-archiver/docker-compose.yml` | `https://mail.kaleschke.info` | PostgreSQL 17, 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 | | `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 | @@ -68,8 +68,8 @@ Secret-Werte sind nicht enthalten. Es werden nur Secret-Namen, Env-Key-Namen und | `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; laeuft aktuell als `user: "0"` wegen Host-Appdata-Permissions | | `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; laeuft aktuell als `user: "0"` wegen Host-Appdata-Permissions | -| `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` | `https://hermes.kaleschke.info` via `${HERMES_DASHBOARD_HOST}` | `hermes-gateway`, Traefik + Authelia | shared read-only data mount | noch nicht in Restore Matrix | ja + Authelia | Compose-Profil `dashboard`; bindet intern mit `--insecure` auf `0.0.0.0`, externe Absicherung bleibt Authelia | +| `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 | Tier 3, Borg/Share | nein | kein Docker socket; terminal backend `ssh`; echte `.env` auf Host-Appdata | +| `hermes-dashboard` | Hermes Dashboard | `ops/hermes-agent/docker-compose.yml` | `https://hermes.kaleschke.info` via `${HERMES_DASHBOARD_HOST}` | `hermes-gateway`, Traefik + Authelia | shared read-only data mount | Tier 3, Borg/Share | ja + Authelia | Compose-Profil `dashboard`; bindet intern mit `--insecure` auf `0.0.0.0`, externe Absicherung bleibt Authelia | ## Backup- und Restore-Hinweise @@ -81,7 +81,6 @@ Secret-Werte sind nicht enthalten. Es werden nur Secret-Namen, Env-Key-Namen und ## Bekannte offene Fragen -- Hermes Agent ist dokumentiert, aber noch nicht vollstaendig in Restore Matrix / DR Bootstrap eingeordnet. - Authelia Repo-Baseline, Host-Config und Compose-Middlewares sollten 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.