Bind AdGuard admin to Tailscale
This commit is contained in:
@@ -47,7 +47,7 @@
|
||||
## 2. Architektur-Prinzipien
|
||||
|
||||
### P1 — Traefik ist der einzige öffentliche HTTP(S)-Einstiegspunkt
|
||||
Kein Webdienst veröffentlicht finale direkte Host-Ports außer `traefik` selbst. Begründete Ausnahmen: `gitea`-SSH (Port 222), `AdGuard Home` (Port 53/DNS + 8082/Admin als bewusste LAN-Operator-Entscheidung), `Tailscale`, `Plex-Media-Server` und `monitoring-influxdb3-core` Port 8181 als LAN-only Writer-Endpunkt fuer Home Assistant.
|
||||
Kein Webdienst veröffentlicht finale direkte Host-Ports außer `traefik` selbst. Begründete Ausnahmen: `gitea`-SSH (Port 222), `AdGuard Home` (Port 53/DNS direkt; Admin 8082 nur auf Tailscale-IP `100.80.98.33`), `Tailscale`, `Plex-Media-Server` und `monitoring-influxdb3-core` Port 8181 als LAN-only Writer-Endpunkt fuer Home Assistant.
|
||||
|
||||
### P2 — Das Setup bleibt bewusst einfach: `frontend_net` + `backend_net` + app-interne Netze
|
||||
- `frontend_net` = Proxy-/Web-Netz
|
||||
@@ -167,7 +167,7 @@ Diese Dienste sind **keine Public Apps**:
|
||||
- `monitoring-grafana` — monitoring.kaleschke.info (Middleware)
|
||||
- `hermes-dashboard` — hermes.kaleschke.info (Middleware)
|
||||
- `Traefik-Dashboard`
|
||||
- `AdGuard Home` — Port 8082 direkt auf die Admin-UI (`80` im Container), kein Traefik, nur LAN-Zugang; 2026-05-25 bewusst keine 2FA-/Traefik-Umstellung
|
||||
- `AdGuard Home` — Admin-UI auf Port 8082 (`80` im Container), kein Traefik, nur Tailscale-IP `100.80.98.33`; 2026-05-26 bewusst keine 2FA-/Traefik-Umstellung
|
||||
|
||||
### 4.3 Regel
|
||||
Wenn ein Dienst im `frontend_net` hängt, heißt das **nicht automatisch öffentlich**. Admin-Dienste dürfen im `frontend_net` liegen, wenn:
|
||||
@@ -239,7 +239,7 @@ Legende Status:
|
||||
| Container | Status | Soll-Netz(e) | Finaler Zugang | Finaler Sollzustand | Offene Punkte |
|
||||
|---|---|---|---|---|---|
|
||||
| `traefik` | ✅ | `frontend_net`, `backend_net` | öffentlich 80/443 | zentraler Ingress, Service-Routing via Docker-Labels | — |
|
||||
| `AdGuard Home` | ✅ | `dns_net` (172.23.0.3), `frontend_net` | Port 53 DNS direkt, Port 8082 Admin (LAN) | DNS-Server + Upstream zu unbound; kein Traefik fuer Admin-UI | Admin-Port bleibt bewusst LAN-direkt; Operator-Entscheidung 2026-05-25 |
|
||||
| `AdGuard Home` | ✅ | `dns_net` (172.23.0.3), `frontend_net` | Port 53 DNS direkt, Port 8082 Admin nur auf Tailscale-IP `100.80.98.33` | DNS-Server + Upstream zu unbound; kein Traefik fuer Admin-UI | Admin-Port bleibt bewusst ohne Traefik/2FA, aber nicht mehr auf allen LAN-Interfaces |
|
||||
| `unbound` | ✅ | `dns_net` | intern | Upstream-Resolver für AdGuard, isoliert | — |
|
||||
| `ddns-updater` | ✅ | `frontend_net` | intern | Cloudflare DNS API; bleibt in `frontend_net` | Dokumentierte Ausnahme |
|
||||
| `tailscale` | ✅ | `host` | VPN-Zugang | Git-Stack (`host-services/tailscale/`) | nutzt `NET_ADMIN`, `NET_RAW` und `/dev/net/tun` als dokumentierte VPN-Ausnahme |
|
||||
@@ -393,7 +393,7 @@ Für den laufenden Betrieb gilt stattdessen:
|
||||
|---|---|---|
|
||||
| `traefik` | Host-Ports 80/443 | zentraler Reverse Proxy |
|
||||
| `tailscale` | `host`, `NET_ADMIN`, `NET_RAW`, `/dev/net/tun` | VPN-Zugang benoetigt Kernel-Netzwerkfunktionen; Umstellung nur kontrolliert moeglich |
|
||||
| `AdGuard Home` | Port 53 (TCP/UDP) direkt + Port 8082 auf Container-Port 80 | DNS benoetigt direkten Port 53; Admin-Port 8082 bleibt bewusst LAN-direkt ohne Traefik/2FA |
|
||||
| `AdGuard Home` | Port 53 (TCP/UDP) direkt + `100.80.98.33:8082` auf Container-Port 80 | DNS benoetigt direkten Port 53; Admin-Port 8082 bleibt bewusst ohne Traefik/2FA, aber nur via Tailscale |
|
||||
| `Plex-Media-Server` | `host` | Discovery / mDNS / Plex GDM |
|
||||
| `scrutiny` | `privileged: true` | SMART-Datenzugriff auf Laufwerke |
|
||||
| `Komodo` | Docker-Socket Zugriff | Stack-Deployments benötigen Socket |
|
||||
@@ -495,7 +495,7 @@ Komodo ist nun der primäre GitOps-Stack-Manager:
|
||||
- AdGuard läuft als Git-Stack (`host-services/Adguard/docker-compose.yml`)
|
||||
- Netzwerke: `dns_net` (feste IP 172.23.0.3) + `frontend_net`
|
||||
- Port 53 (DNS) direkt gebunden — dokumentierte Ausnahme
|
||||
- Admin-UI direkt gebunden via Host-Port 8082 auf Container-Port 80 — 2026-05-25 bewusst als einfache LAN-Operator-Entscheidung beibehalten, keine Traefik-/2FA-Umstellung
|
||||
- Admin-UI direkt gebunden via Tailscale-IP `100.80.98.33:8082` auf Container-Port 80 — 2026-05-26 bewusst als einfache Operator-Entscheidung ohne Traefik-/2FA-Umstellung
|
||||
- `unbound` läuft weiterhin als Upstream-Resolver in `dns_net`
|
||||
|
||||
### diun — Entfernung (2026-03-28)
|
||||
|
||||
@@ -13,6 +13,14 @@ Bei Restore-, Host-Ausfall- oder Wiederanlauf-Fragen zusaetzlich:
|
||||
|
||||
3. `docs/DISASTER_RECOVERY.md`
|
||||
4. `docs/RESTORE_MATRIX.md`
|
||||
5. `docs/SERVICES_RECOVERY.md`
|
||||
|
||||
Bei Hardware-, Netzwerk-, Provider- oder Kapazitaetsfragen zusaetzlich:
|
||||
|
||||
6. `docs/HARDWARE_INVENTORY.md`
|
||||
7. `docs/NETWORK_INVENTORY.md`
|
||||
8. `docs/EXTERNAL_DEPENDENCIES.md`
|
||||
9. `docs/CAPACITY_AND_LIFECYCLE.md`
|
||||
|
||||
## Architektur
|
||||
|
||||
@@ -63,5 +71,7 @@ Bei Restore-, Host-Ausfall- oder Wiederanlauf-Fragen zusaetzlich:
|
||||
- Traefik `dynamic/` bleibt eine dokumentierte manuelle Host-Sync-Ausnahme ausserhalb des normalen Komodo-Deployments.
|
||||
- Mutable Image-Tags sind auf die aktuell laufenden Digests eingefroren; echte Versions-Upgrades erfolgen bewusst separat.
|
||||
- Disaster-Recovery und dienstspezifische Restore-Quellen sind in `docs/DISASTER_RECOVERY.md` und `docs/RESTORE_MATRIX.md` beschrieben.
|
||||
- Recovery-kritische Services-Pfade wie Gitea-Repositories, Komodo-Workspaces und Host-Automation sind in `docs/SERVICES_RECOVERY.md` beschrieben.
|
||||
- Hardware-, Netzwerk-, Provider- und Capacity-Inventare sind als operative Audit-Dokumente unter `docs/HARDWARE_INVENTORY.md`, `docs/NETWORK_INVENTORY.md`, `docs/EXTERNAL_DEPENDENCIES.md` und `docs/CAPACITY_AND_LIFECYCLE.md` vorbereitet.
|
||||
- Der verbindliche Detailablauf steht in `docs/WORKFLOW.md`.
|
||||
- `nextcloud`, `bentopdf` und `monitoring` folgen dem dokumentierten Netz-/Secret-/Traefik-Modell; der zentrale Monitoring-Stack buendelt Prometheus, Loki, Promtail, Grafana und InfluxDB 3 Core.
|
||||
|
||||
+1
-1
@@ -135,7 +135,7 @@ Bekannte Ausnahmen:
|
||||
|
||||
- Traefik: 80/443
|
||||
- Gitea: SSH 222
|
||||
- AdGuard: DNS 53 und Admin 8082; Admin 8082 bleibt bewusst LAN-direkt ohne Traefik/2FA
|
||||
- AdGuard: DNS 53 direkt; Admin 8082 ist bewusst ohne Traefik/2FA, aber auf Tailscale-IP `100.80.98.33` begrenzt
|
||||
- Tailscale: Host-Netz, `NET_ADMIN`, `NET_RAW`, `/dev/net/tun`
|
||||
- Scrutiny: privileged
|
||||
- Komodo: Docker-Socket, native Auth
|
||||
|
||||
@@ -0,0 +1,895 @@
|
||||
# Homelab-Audit KalliLab CORE
|
||||
|
||||
Stand: 2026-05-25
|
||||
Methode: Repo-basierter Audit auf `master` (lokaler Clone). Keine Live-Messung gegen den Host. Querverweise auf Audit-Live-Daten aus `docs/AUDIT_2026-05-23_LIVE.md`, wo verfuegbar.
|
||||
Auftrag: externer, kritischer Audit-Blick zusaetzlich zur internen `docs/STRATEGISCHE_BEWERTUNG_2026-05-23.md`.
|
||||
|
||||
## Wichtige Vorbemerkung
|
||||
|
||||
Es gibt seit dem 23.05. eine fundierte interne Bewertung (`docs/STRATEGISCHE_BEWERTUNG_2026-05-23.md`) und eine konsolidierte Hausaufgabenliste (`docs/CODEX_KONSOLIDIERUNG_2026-05-23.md`). Davon wurden seit dem 25.05. bereits umgesetzt:
|
||||
|
||||
- Jellyfin entfernt (MASTER 7.8)
|
||||
- Homepage entfernt (MASTER 7.8)
|
||||
- Uptime-Kuma entfernt (MASTER 7.8, SECRETS_MAP 29)
|
||||
- Monitoring-Stack produktiv (AUDIT_FINAL 9), Altstaende-Container down
|
||||
- Disk1 NTFS -> XFS Phase 2 abgeschlossen am 2026-05-25 (STORAGE_LAYOUT 3)
|
||||
- Unraid-Flash-Backup live (`unraid-flash-config.tar.gz` im Borg-Lauf)
|
||||
- GitHub-Push-Mirror `michaelkaleschke-spec/homelab-infra` aktiv (DR 10, MASTER 7.1)
|
||||
|
||||
Diese geloesten Punkte werden hier nicht wiederholt. Dieser Audit konzentriert sich auf das, was nach dem 23.05.-Sprint **noch offen ist** und auf das, was die strategische Bewertung **nicht oder nur kurz angerissen** hat.
|
||||
|
||||
---
|
||||
|
||||
# Phase 1: Repo-Inventar
|
||||
|
||||
## Ordnerstruktur (Ist-Zustand)
|
||||
|
||||
```
|
||||
homelab-infra/
|
||||
├── apps/ 9 Stacks (bentopdf, immich, mail-archiver, mealie, nextcloud, ntfy, paperless, paperless-gpt, unbound)
|
||||
├── core/ 1 Stack (gitea)
|
||||
├── docs/ 28 Markdown-Dokumente
|
||||
├── env/ 2 *.example
|
||||
├── host-services/ 3 Stacks (Adguard, plex, tailscale)
|
||||
├── infra/ 3 Stacks (ddns-updater, postgresql17, redis)
|
||||
├── monitoring/ 1 Compose mit 10 Services + Provisioning
|
||||
├── ops/ 17 Verzeichnisse (Semaphore, borg-ui, code-server, filebrowser, glance, glances, grafana-influxdb [Altstand], hermes-agent, komodo, loki [Altstand], policy-checks, restore-tests, scrutiny, speedtest, uptime-kuma [Altrest], windows-reinstall)
|
||||
├── security/ 2 Stacks (authelia, vaultwarden)
|
||||
├── services/ 1 posture-check (Host-Skripte)
|
||||
└── traefik/ 1 Compose + dynamic/ (3 Files)
|
||||
```
|
||||
|
||||
**Inventar-Befund:**
|
||||
|
||||
- ~30 Compose-Dateien, 1 zentraler Compose-Multi-Service (`monitoring/`).
|
||||
- 29 Composes wurden vom Policy-Checker validiert (`ops/policy-checks/last-report.md`): **0 Critical, 4 Warnings, 9 Info**.
|
||||
- Doku-Dichte ist hoch (REPO_MAP, SERVICE_CATALOG, RESTORE_MATRIX, DISASTER_RECOVERY, SECRETS_MAP, WORKFLOW, STORAGE_LAYOUT, GITOPS_DRIFT_RUNBOOK, ALERTING_MAP).
|
||||
- Restore-Tests sind als echte Scripts versioniert (`ops/restore-tests/`). Ueberdurchschnittlich.
|
||||
|
||||
## Gut dokumentierte Bereiche (Belegt)
|
||||
|
||||
| Bereich | Quelle |
|
||||
|---|---|
|
||||
| Architektur, Netze, Ausnahmen | `HOMELAB_ARCHITECTURE_MASTER_V2.md` |
|
||||
| GitOps-Workflow, Drift | `docs/WORKFLOW.md`, `docs/GITOPS_DRIFT_RUNBOOK.md` |
|
||||
| Backup-Scope, Restore-Wege, Tier-Modell | `docs/RESTORE_MATRIX.md`, `docs/DISASTER_RECOVERY.md`, `ops/borg-ui/BACKUP_SCOPE.md` |
|
||||
| Storage / Cache-Policy / FS / Posture | `docs/STORAGE_LAYOUT.draft.md` |
|
||||
| Secret-Inventur | `docs/SECRETS_MAP.md` |
|
||||
| Alert-Pfade | `docs/ALERTING_MAP.md` |
|
||||
|
||||
## Luecken / Unklar (vermutet bzw. Rueckfrage noetig)
|
||||
|
||||
| Luecke | Warum es ein Audit-Loch ist |
|
||||
|---|---|
|
||||
| `docs/STORAGE_LAYOUT.draft.md` ist `Draft 1.3`, nicht `Active` | Mehrere Hard Rules (12 Constitution) gelten formal noch nicht. Hard Rule 11 (kein Stack ohne Restore-Pfad in RESTORE_MATRIX) wird heute schon eingehalten — also nur Formal-Luecke. |
|
||||
| `docs/SERVICES_RECOVERY.md` ist als verbindlich angekuendigt (STORAGE_LAYOUT 4), aber nicht im Repo | Konkrete Mirror-Mechanik fuer `services/gitea/git/repositories/` ≤ 6 h ist nirgends spezifiziert. |
|
||||
| Hardware-Inventar: kein zentrales Dokument | Keine Stelle im Repo nennt CPU-Modell, RAM-Groesse, NIC-Speed, Mainboard, Parity-Disk-Groessen — nur "Samsung 970 EVO Plus 2 TB" steht in STORAGE_LAYOUT 3. |
|
||||
| USV: keine Erwaehnung | Keine Datei nennt eine USV. Unklar, ob vorhanden. |
|
||||
| Familien-/User-Onboarding-Doku | Keine Doku, die deine Frau/Kinder lesen muessten ("So loggst du dich in Nextcloud ein"). Aktuell ist alles Operator-Doku. |
|
||||
|
||||
## Fuer den Audit besonders wichtige Dateien (verwendet)
|
||||
|
||||
- `HOMELAB_ARCHITECTURE_MASTER_V2.md` — komplett
|
||||
- `docs/WORKFLOW.md`, `docs/REPO_MAP.md`, `docs/SERVICE_CATALOG.md` — komplett
|
||||
- `docs/DISASTER_RECOVERY.md`, `docs/RESTORE_MATRIX.md`, `docs/SECRETS_MAP.md` — komplett
|
||||
- `docs/STORAGE_LAYOUT.draft.md`, `docs/STRATEGISCHE_BEWERTUNG_2026-05-23.md` — komplett
|
||||
- `docs/AUDIT_2026-05-23_LIVE.md`, `docs/AUDIT_2026-05-23_FINAL.md`
|
||||
- `ops/policy-checks/last-report.md`
|
||||
- `monitoring/docker-compose.yml`, `monitoring/prometheus/alerts.yml`
|
||||
- `traefik/docker-compose.yml`, `traefik/dynamic/middlewares.yml`
|
||||
- `security/authelia/configuration.yml`, `security/authelia/docker-compose.yml`
|
||||
- `apps/paperless/docker-compose.yml`, `apps/immich/docker-compose.yml`, `apps/nextcloud/docker-compose.yml`
|
||||
- `host-services/Adguard/docker-compose.yml`
|
||||
|
||||
---
|
||||
|
||||
# A. Executive Summary
|
||||
|
||||
**Was schon stark ist:**
|
||||
|
||||
- GitOps-Disziplin: Gitea als Sollzustand, Komodo als Consumer, dokumentierter Drift-Runbook, Stop-Regel ("zwei Fehlversuche -> Pflichtmatrix"). Seltene Reife.
|
||||
- Backup-Architektur: Pre-Backup-Dumps + Borg + Restore-Tests mit echtem Smoke-Test-Kriterium ("Container startet ≠ Erfolg"). 15 frische Dumps < 24 h alt (`AUDIT_LIVE 9.4`).
|
||||
- Architektur-Klarheit: `frontend_net` / `backend_net` / app-interne Netze, keine Sammelnetze, dokumentierte Ausnahmen.
|
||||
- Image-Pinning: Tier-1-Stateful mit `<minor>@sha256:...`. Konsequent durchgezogen.
|
||||
- Secrets-Hygiene: Keine Secret-Werte im Repo, `_FILE`-Mounts + Komodo Stack ENV, explizit dokumentierte Ausnahmen.
|
||||
- Policy-as-Code: `check_repo.ps1` mit 0 Critical und sauber dokumentierten Exceptions.
|
||||
|
||||
**Was kritisch ist:**
|
||||
|
||||
- **AdGuard Admin-Port 8082 ohne Authelia/2FA am LAN gebunden** (`host-services/Adguard/docker-compose.yml:16`) — dokumentierte "Operator-Entscheidung" 2026-05-25. Im Heim-LAN tolerierbar, mit IoT/Gaeste-WLAN potenziell ein Pfad zur DNS-Manipulation. Niedrigster Aufwand: Bind nur auf Tailscale-Interface.
|
||||
- **Authelia ACL: 2FA nur fuer `files.kaleschke.info` und `scrutiny.kaleschke.info`** (`security/authelia/configuration.yml:44-48`). Borg-UI, Code-Server, Filebrowser, Glance — alles nur `one_factor`. Bei Pwd-Kompromittierung des Operator-Accounts ist Borg-UI + Code-Server der direkteste Pfad zur Datenexfiltration.
|
||||
- **Authelia-Repo-Baseline ↔ Host-Config-Drift "by design"** (`docs/REPO_MAP.md:48`, `SERVICE_CATALOG 23`). User-DB, OIDC-Clients und Secrets sind hostseitig, Manual-Merge-Pflicht. Stelle, an der Drift mit Anlauf passiert.
|
||||
- **Komodo Self-Bootstrap-Problem ist nur dokumentiert, nicht geloest** (MASTER 13: Self-Stack Drift-Recovery 2026-05-04). Bei Recovery vom kalten Host musst du Komodo aus `compose.yaml` neu erzeugen — dafuer brauchst du die `.env` mit `KOMODO_*`-Secrets, die nur auf Host und ggf. Vaultwarden liegen.
|
||||
- **Backup-Off-Site-Diversitaet:** BorgBase Hetzner ist Single-Provider; Borg-Passphrase analog gesichert ist als TODO markiert (`docs/DISASTER_RECOVERY.md:64,401`). Wenn Hetzner-Account verloren geht, ist das halbe DR-Versprechen weg.
|
||||
|
||||
**Was unnoetig komplex ist:**
|
||||
|
||||
- Drei dokumentierte Monitoring-/Logging-Pfade gleichzeitig im Repo: `ops/grafana-influxdb` (Altstand), `ops/loki` (Altstand), `monitoring/` (Ziel). Die Altstaende sind als Container down, aber **Verzeichnisse noch im Repo** — Doppelpflege-Risiko. Der versprochene Repo-Cleanup (`git rm`) fehlt.
|
||||
- Hermes-Agent: NAS-Stack bewusst deaktiviert ("VM-seitig offen"), aber Stack-Verzeichnis und Compose mit Dashboard-Domain bleiben im Repo. Mehr "Schwebezustand" als operativer Wert.
|
||||
- BentoPDF: "vorbereitet", noch nie produktiv abgenommen (`SERVICE_CATALOG 52`, `MASTER 7.5`).
|
||||
- `infra/redis` ist als shared Cache deklariert, wird de facto nur von Paperless genutzt (Authelia nicht, Immich/Nextcloud/Mealie haben eigene Redis). Das "shared" stimmt im Repo nicht mit der Realitaet ueberein.
|
||||
|
||||
**Groesster Hebel:**
|
||||
|
||||
**Authelia OIDC-Provider aktivieren** — wenn Nextcloud, Immich, Grafana (und perspektivisch Mealie via OIDC-Bridge) per SSO laufen, gewinnst du gleichzeitig:
|
||||
|
||||
- (a) Familien-Onboarding-Komfort (ein Login),
|
||||
- (b) zentrale Brute-Force-Regulation und Audit,
|
||||
- (c) Voraussetzung fuer sinnvolles CrowdSec/Fail2Ban,
|
||||
- (d) zentrale 2FA-Pflicht statt App-by-App.
|
||||
|
||||
Das ist ein Sprint, nicht ein Quartal, und macht aus deinem "Admin-Authelia" ein echtes Identity-System.
|
||||
|
||||
**Was ein erfahrener Homelabber sofort aendern wuerde:**
|
||||
|
||||
1. AdGuard-Admin-Port nur auf Tailscale-Interface binden (5 Min, Compose-Edit).
|
||||
2. Borg-Passphrase auf Papier in Bankschliessfach (15 Min, off-system).
|
||||
3. `scrutiny` und `ddns-updater` `no-new-privileges` Warning aufraeumen (10 Min) — kosmetisch, aber Policy-Check sollte clean sein.
|
||||
4. Altstaende `ops/grafana-influxdb/` und `ops/loki/` aus Repo entfernen (Backup-Branch dann `git rm`).
|
||||
5. Renovate-Bot gegen Gitea einrichten — beendet manuelle Digest-Pflicht.
|
||||
|
||||
---
|
||||
|
||||
# B. Scorecard (1 = exzellent, 10 = ungenuegend)
|
||||
|
||||
| Bereich | Note | Begruendung |
|
||||
|---|---:|---|
|
||||
| Hardware | **nicht bewertbar** | Keine Inventar-Doku im Repo. Nur Cache-NVMe genannt. Siehe Phase H. |
|
||||
| Ordnerstruktur | **2** | Klare Trennung apps/infra/ops/security/core; konsistente Namenskonvention (mit Migrationsplan in STORAGE_LAYOUT 6). Kleinerer Haenger: `host-services/Adguard/` mit Grossbuchstabe. |
|
||||
| Storage | **3** (Repo-Stand) / **2** (mit STORAGE_LAYOUT Active) | Cache-XFS, Disk1-XFS jetzt erreicht. Pfad-Disziplin via `/mnt/user/...`. Posture-Check etabliert. Note durch Draft-Status und fehlendes `SERVICES_RECOVERY.md` gedrueckt. |
|
||||
| Docker-Architektur | **2** | Netzmodell klar, Healthchecks fehlen grossflaechig, `latest@sha256` als bewusster Kompromiss bei einigen Images dokumentiert. Keine Memory-Limits. |
|
||||
| Reverse Proxy / Zugriff | **2** | DNS-Challenge, Wildcard-faehig, Authelia ForwardAuth, dynamic config sauber getrennt. Manuelle Host-Sync-Ausnahme ist pragmatisch. |
|
||||
| Security | **3** | Solides Fundament (Authelia Argon2id, no-new-privileges-Standard, Webhook-Allowlist, `cloudflare_dns_api_token` als Docker Secret), aber: nur 2 Domains mit 2FA, AdGuard-Admin direkt am LAN, kein WAF/Bouncer, Authelia Regulation 5-Min-Ban ist gentil. |
|
||||
| Netzwerk / DNS | **2** | AdGuard + Unbound + Tailscale-Trias ist Best-of-Class-Homelab. FritzBox als Router nicht im Repo dokumentiert, daher Note nicht 1. |
|
||||
| Backup | **2** | Borg, Pre-Dumps, Tier-Modell, dokumentierter Scope. Punkt-Abzug: Single-Provider Off-Site, Passphrase nicht analog, Komodo-Mongo-Dump-Verifikation nicht im Auto-Cron. |
|
||||
| Restore-Faehigkeit | **2** | RESTORE_MATRIX mit Smoke-Test je Dienst, Restore-Test-Schedule + Validierungen fuer Vaultwarden/Gitea/Paperless dokumentiert. Punkt-Abzug: Immich-Restore noch nie geuebt — groesster Datentopf. |
|
||||
| GitOps | **1-2** | Webhook-Pflicht fuer neue Stacks, Source-of-Truth-Hierarchie, Drift-Runbook. Self-Bootstrap-Problem von Komodo zieht von 1 auf 2. |
|
||||
| Monitoring | **3** | Stack produktiv, aber Altstaende noch im Repo, Family-View-Dashboard fehlt, Alerts (`alerts.yml`) sehr knapp (5 Regeln), keine Cert-Expiry-Alert auf Prometheus-Ebene (Cert-Token-Check laeuft separat). |
|
||||
| Dokumentation | **1** | Aussergewoehnlich. SERVICE_CATALOG ist Gold. Einziger Punkt: kein End-User-/Familien-Onboarding. |
|
||||
| Automatisierung | **3** | Borg-Dumps automatisiert, posture-check Host-Cron, Alert->ntfy-Pipe. Aber: keine CI gegen Repo, kein Renovate, kein automatisches Image-Update-Tracking. |
|
||||
| Wartbarkeit | **2** | Doku traegt; Sprintpflege-Disziplin sichtbar (MIGRATION_LOG, AUDIT_FINAL). Risiko: Authelia-Drift, Hermes-Schwebezustand. |
|
||||
| Nerd-Faktor | **2-** | Komodo + Borg-UI + ntfy-Bridge + Posture-Check + Restore-Lab + Hermes-Experiment + Push-Mirror + Digest-Pinning. Liegt zwischen "Solider Senior" und "Spielwiese halten lernen". |
|
||||
|
||||
**Gesamteindruck: 2 (gut).** Strukturell weit ueber durchschnittlichem Homelab; konkrete Luecken sind klar benennbar und nicht systemisch.
|
||||
|
||||
---
|
||||
|
||||
# C. Top-20 Findings
|
||||
|
||||
> Format: priorisiert nach Risiko-zu-Aufwand-Hebel. Jeder Eintrag hat Fundstelle, Empfehlung und Prio.
|
||||
|
||||
### F-01 · AdGuard-Admin am LAN ohne Auth
|
||||
|
||||
- **Kategorie:** Security / Zugriff
|
||||
- **Fundstelle:** `host-services/Adguard/docker-compose.yml:16`, `MASTER 10`, `docs/SERVICE_CATALOG.md:14`
|
||||
- **Beobachtung:** Port `8082:80` direkt auf alle Interfaces. Bewusste Operator-Entscheidung 2026-05-25.
|
||||
- **Risiko:** Jedes Geraet im LAN kann DNS-Filterregeln, Upstream und Logging manipulieren. IoT-Kompromittierung oder Gast-WLAN -> DNS-Hijack moeglich.
|
||||
- **Best Practice:** Admin-UIs nicht im LAN ohne Auth. Entweder hinter Traefik+Authelia mit `two_factor` oder Bind auf Tailscale-Interface (z. B. `100.x.y.z:8082:80`).
|
||||
- **Empfehlung:** Schritt 1 — Bind auf Tailscale-IP (S, 5 Min). Schritt 2 — optional spaeter Traefik-Route hinter Authelia.
|
||||
- **Prioritaet:** Sollte zeitnah
|
||||
- **Aufwand:** S
|
||||
- **Validierung:** `ss -ltnp | grep :8082` zeigt nur Tailscale-IP; LAN-Browser-Zugriff schlaegt fehl.
|
||||
- **Rollback:** Compose-Diff zurueck, Komodo redeploy.
|
||||
|
||||
### F-02 · Borg-Passphrase nicht analog gesichert
|
||||
|
||||
- **Kategorie:** Backup / DR
|
||||
- **Fundstelle:** `docs/DISASTER_RECOVERY.md:64,401`, `docs/SECRETS_MAP.md:48`
|
||||
- **Beobachtung:** `borg_repo_passphrase.txt` liegt im Host-Filesystem unter `/mnt/user/appdata/secrets/`. Doku weist explizit darauf hin, dass eine externe analoge Sicherung Operator-Aufgabe ist.
|
||||
- **Risiko:** Wenn Unraid-Host und ggf. Vaultwarden gleichzeitig defekt sind, ist das verschluesselte Borg-Repo bei Hetzner nutzlos.
|
||||
- **Empfehlung:** Auf Papier ausdrucken, in Bankschliessfach oder bei vertrauter Person versiegelt. Zusaetzlich in Vaultwarden hinterlegen (aber Vaultwarden hilft nicht, wenn es selbst restauriert werden muss).
|
||||
- **Prioritaet:** Muss sofort
|
||||
- **Aufwand:** S
|
||||
- **Validierung:** Du kannst den Wert ohne Host wiederherstellen.
|
||||
|
||||
### F-03 · Single-Provider Off-Site Backup
|
||||
|
||||
- **Kategorie:** Backup
|
||||
- **Fundstelle:** `ops/borg-ui/BACKUP_SCOPE.md`, `docs/RESTORE_MATRIX.md:77-96`, `STORAGE_LAYOUT 8.1`
|
||||
- **Beobachtung:** Hetzner Storage Box als alleiniges Off-Site-Borg-Ziel. STORAGE_LAYOUT 8.1 sieht zusaetzlich lokales Borg-Repo auf `/mnt/user/backups/borg/` vor (gleicher Host) und eine externe Wechselplatte (manuell rotiert).
|
||||
- **Risiko:** Hetzner-Account-Verlust (Payment-Issue, Account-Hack, Provider-Outage) = halbes 3-2-1.
|
||||
- **Best Practice:** Zweites Off-Site-Ziel mit unterschiedlichem Provider oder Cold-Wechselplatte mit fester Rotationskadenz.
|
||||
- **Empfehlung:** (a) Wechselplatten-Rotation in fester Kadenz dokumentieren (zwei Platten, monatlicher Tausch). Oder (b) zweites Borg-Repo bei rsync.net / BorgBase EU2 / privatem 2. Standort.
|
||||
- **Prioritaet:** Sollte zeitnah
|
||||
- **Aufwand:** M
|
||||
- **Validierung:** `borg list` gegen beide Repos, beide < 7 Tage alt.
|
||||
|
||||
### F-04 · Authelia 2FA-Pflicht zu schmal
|
||||
|
||||
- **Kategorie:** Security
|
||||
- **Fundstelle:** `security/authelia/configuration.yml:44-53`
|
||||
- **Beobachtung:** Nur `files.kaleschke.info` und `scrutiny.kaleschke.info` sind `two_factor`. Tier-1-Operator-UIs wie Borg-UI, Code-Server, Filebrowser (zweite Route?), Komodo (eigene Auth), Glance, Grafana laufen mit `one_factor`.
|
||||
- **Risiko:** Operator-Passwort-Kompromittierung (Phishing, Keylogger, Browser-Save-Leak) gibt ohne 2FA Vollzugriff auf Code-Server (Repo + Workspace), Borg-UI (Restore-Pfade), Filebrowser (Documents/Photos).
|
||||
- **Empfehlung:** ACL erweitern: `two_factor` fuer `borg.kaleschke.info`, `code.kaleschke.info`, `files.kaleschke.info` (schon), `glance.kaleschke.info` (debattierbar), `traefik.kaleschke.info`. Komodo bleibt Ausnahme.
|
||||
- **Prioritaet:** Muss sofort
|
||||
- **Aufwand:** S
|
||||
- **Validierung:** Nach Login auf `borg.kaleschke.info` wird 2FA-Prompt erzwungen.
|
||||
- **Rollback:** ACL-Block zurueck.
|
||||
|
||||
### F-05 · Repo-Altstaende `ops/grafana-influxdb/` und `ops/loki/` nicht entfernt
|
||||
|
||||
- **Kategorie:** Wartbarkeit / GitOps
|
||||
- **Fundstelle:** Repo-Wurzeln `ops/grafana-influxdb/`, `ops/loki/`; `MASTER 7.6`, `SERVICE_CATALOG 68-70,80-81`, `AUDIT_FINAL 9`
|
||||
- **Beobachtung:** Container down, aber Compose-Dateien + Provisioning bleiben im Repo. Doku referenziert beide gleichzeitig. Risiko: jemand (zukuenftiges Ich, KI) deployt versehentlich den Altstand.
|
||||
- **Empfehlung:** `git rm` der beiden Verzeichnisse, Tag `pre-monitoring-cleanup` fuer Rollback, MIGRATION_LOG-Eintrag.
|
||||
- **Prioritaet:** Sollte zeitnah
|
||||
- **Aufwand:** S
|
||||
- **Validierung:** `policy-checks` laeuft clean, Repo enthaelt nur noch `monitoring/`.
|
||||
|
||||
### F-06 · Hermes-Agent im Schwebezustand
|
||||
|
||||
- **Kategorie:** App-Landschaft / Wartbarkeit
|
||||
- **Fundstelle:** `ops/hermes-agent/docker-compose.yml`, `MASTER 7.5`, `SERVICE_CATALOG 82-83`
|
||||
- **Beobachtung:** "NAS-Stack bewusst deaktiviert" wegen offener VM-Seite. Dashboard-Domain (`hermes.kaleschke.info`) + Authelia-ACL + Secret-Pfade dokumentiert.
|
||||
- **Risiko:** Schleichender Verfall — in 6 Monaten verstehst du Model-C nicht mehr ohne `ops/hermes-agent/README.md`. Bei jeder Authelia-/Compose-Aenderung musst du Hermes mitpruefen, obwohl es nichts tut.
|
||||
- **Empfehlung:** Operator-Entscheidung mit 60-Tage-Deadline ehrlich treffen. Wenn nicht produktiv bis 2026-07-25: `git rm ops/hermes-agent/`, Domain aus DNS, ACL-Eintrag raus.
|
||||
- **Prioritaet:** Sollte zeitnah (Entscheidung)
|
||||
- **Aufwand:** S (Entfernen) / L (echte Produktiv-Aktivierung)
|
||||
- **Validierung:** Entweder Smoke-Test auf `hermes.kaleschke.info` mit funktionalem Use-Case-Beleg, oder Repo-clean.
|
||||
|
||||
### F-07 · Monitoring-Stack ohne Digest-Pin
|
||||
|
||||
- **Kategorie:** Reproduzierbarkeit / GitOps
|
||||
- **Fundstelle:** `monitoring/docker-compose.yml:3,28,66,84,100,118,276,296`
|
||||
- **Beobachtung:** Prometheus, Alertmanager, Blackbox, Loki, Promtail, Grafana, node-exporter, cAdvisor sind alle nur per Tag gepinnt (`prom/prometheus:v3.7.3`, `grafana/grafana:12.4.3`, ...). Nur `influxdb3-core` hat `@sha256:`. Das widerspricht der Image-Versionierungs-Disziplin der Tier-1-Stateful-Dienste.
|
||||
- **Risiko:** Wenn upstream einen Tag erneut pushed (Versionsdrift, Supply Chain), wird beim Rebuild ein anderer Container deployed — gerade Monitoring sollte stabil sein.
|
||||
- **Empfehlung:** Beim naechsten Komodo-Redeploy aktuellen Digest auslesen und einpinnen. Vorbereitung fuer Renovate (F-12).
|
||||
- **Prioritaet:** Nice to have
|
||||
- **Aufwand:** S
|
||||
- **Validierung:** `grep '@sha256' monitoring/docker-compose.yml` listet alle 10 Services.
|
||||
|
||||
### F-08 · Alert-Regeln zu duenn
|
||||
|
||||
- **Kategorie:** Monitoring
|
||||
- **Fundstelle:** `monitoring/prometheus/alerts.yml`
|
||||
- **Beobachtung:** Exakt 5 Regeln: ExternalConnectivityDown, EndpointDown, EndpointSlow, DiskAlmostFull, MemoryHighUsage, Traefik5xx. Es fehlen:
|
||||
- Borg-Lauf-Frische (ueber `node_exporter` textfile collector oder Pushgateway).
|
||||
- Zertifikatslaufzeit (Blackbox kann `probe_ssl_earliest_cert_expiry`, aber keine Alert-Regel dafuer).
|
||||
- Container-down-Alert (cAdvisor liefert `container_last_seen`).
|
||||
- PostgreSQL-Connection-Saturation.
|
||||
- Loki ingestion-rate / log-volume spike.
|
||||
- InfluxDB-Disk-Pressure.
|
||||
- Backup-Job-Failure.
|
||||
- **Risiko:** Du siehst Probleme nicht, bevor sie weh tun. Cert-Expiry und Borg-Stale sind die schmerzhaftesten Blind-Spots.
|
||||
- **Empfehlung:** Mindestens zwei Regeln nachziehen: `BorgArchiveStale` (>30 h, Pushgateway oder textfile) und `TLSCertExpiryNear` (<14 Tage). Rest als Folge-Sprint.
|
||||
- **Prioritaet:** Sollte zeitnah
|
||||
- **Aufwand:** M
|
||||
- **Validierung:** Alerts feuern in Test-Bedingung (Borg-Dump-File touch -d backwards).
|
||||
|
||||
### F-09 · Komodo-Self-Bootstrap-Problem
|
||||
|
||||
- **Kategorie:** GitOps / DR
|
||||
- **Fundstelle:** `MASTER 13: Komodo Self-Stack Drift-Recovery 2026-05-04`
|
||||
- **Beobachtung:** Du hattest schon einen Drift-Vorfall (Komodo-Core ran aus `/tmp/*repair.yml`, Mongo-Pfad fehlte). Recovery-ENV liegt als "temporaeres Tier-1-Secret-Material" unter `/mnt/user/appdata/secrets/_komodo_stack_env_recovery_2026-05-04.env` (Doku-Stand).
|
||||
- **Risiko:** Bei Totalausfall musst du Komodo aus Compose-Datei wiederbeleben, dafuer brauchst du die Stack-ENV mit `KOMODO_SECRET_KEY`, `KOMODO_MONGO_PASSWORD`, `KOMODO_PERIPHERY_PASSKEY` etc., die nur als Komodo Stack ENV existieren. Klassisches Henne-Ei.
|
||||
- **Empfehlung:** Komodo-Self-Stack aus Komodos eigener Verwaltung herausnehmen und als handgepflegten `docker compose`-Service in `services/komodo-bootstrap/` halten. Stack-ENV als versiegelte Datei unter `/mnt/user/appdata/secrets/` mit deterministischem Restore-Pfad in RESTORE_MATRIX.
|
||||
- **Prioritaet:** Sollte zeitnah
|
||||
- **Aufwand:** M
|
||||
- **Validierung:** Komodo-Stack-Datei lebt im Repo unter `services/`, nicht in Komodos eigener Workspace-Sicht.
|
||||
|
||||
### F-10 · Authelia Repo↔Host Drift "by design"
|
||||
|
||||
- **Kategorie:** GitOps / Security
|
||||
- **Fundstelle:** `docs/REPO_MAP.md:48`, `security/authelia/configuration.yml`, `SERVICE_CATALOG 23`
|
||||
- **Beobachtung:** Repo enthaelt Baseline ohne Secrets, OIDC, Users-DB. Manuelles Merge auf den Host noetig. Es gibt keine automatische Konsistenz-Pruefung.
|
||||
- **Risiko:** Repo-Aenderung (z. B. neue ACL-Regel) wird gepusht, aber nie auf den Host gemerged -> Drift, Authelia hinkt der Wahrheit hinterher.
|
||||
- **Empfehlung:** Symmetrisch zum Traefik-Dynamic-Workflow (manueller Sync explizit als Pflicht in WORKFLOW.md). Zusaetzlich ein einfaches Diff-Script `services/authelia-diff.sh`, das `diff` zwischen Repo-Baseline und Host-Datei zeigt, und das im posture-check als Warning auftaucht, wenn die ACL-Sektion differiert.
|
||||
- **Prioritaet:** Sollte zeitnah
|
||||
- **Aufwand:** S
|
||||
- **Validierung:** Script laeuft, posture-check kennt einen neuen Check `authelia_config_drift`.
|
||||
|
||||
### F-11 · Immich-Restore noch nie geuebt
|
||||
|
||||
- **Kategorie:** Backup / Restore
|
||||
- **Fundstelle:** `docs/RESTORE_MATRIX.md:49`, Restore-Test-Schedule
|
||||
- **Beobachtung:** Vaultwarden / Gitea / Paperless haben Mini-Restore-Tests (2026-05-07). Immich nicht. Immich ist der groesste Datentopf (Familien-Fotos).
|
||||
- **Risiko:** Silent Corruption in Postgres-pgvecto-rs-Daten bemerkst du erst beim Restore-Versuch.
|
||||
- **Empfehlung:** Eigener Sprint: Immich-Restore-Test gegen `/mnt/user/backups/restore-lab/immich/` mit Sub-Set der `immich.dump` und einem Foto-Sample. Smoke-Test = "10 Fotos im Browser sichtbar nach Restore".
|
||||
- **Prioritaet:** Sollte zeitnah
|
||||
- **Aufwand:** M
|
||||
- **Validierung:** Report unter `/mnt/user/backups/restore-reports/immich-<datum>.json`.
|
||||
|
||||
### F-12 · Keine Image-Update-Automatik (Renovate o. ae.)
|
||||
|
||||
- **Kategorie:** Wartbarkeit
|
||||
- **Fundstelle:** Repo-weit; `docs/WORKFLOW.md:282-288` (Image-Versionierung)
|
||||
- **Beobachtung:** Digest-Pinning ist konsequent, aber rein manuell. Bei ~30 Images bedeutet das, du musst monatlich fuer Patch-Updates manuell Digests auslesen — oder es bleibt liegen.
|
||||
- **Risiko:** CVE-Patches werden nicht eingespielt, weil "der laufende Stand ist stabil".
|
||||
- **Empfehlung:** Renovate Bot (self-hosted, gegen Gitea), Gitea-Actions-Runner. Renovate oeffnet PRs fuer Patch-/Minor-Updates; Major-Updates werden mit Labels separiert.
|
||||
- **Prioritaet:** Sollte zeitnah (oder Nice to have, je nach Schmerz)
|
||||
- **Aufwand:** M (Initial-Setup ist substantiell)
|
||||
- **Validierung:** Renovate hat erste PRs in Gitea geoeffnet, du mergst eines davon kontrolliert.
|
||||
|
||||
### F-13 · Keine OIDC-SSO fuer User-Apps
|
||||
|
||||
- **Kategorie:** Security / UX
|
||||
- **Fundstelle:** `security/authelia/configuration.yml`, `docs/SECRETS_MAP.md`
|
||||
- **Beobachtung:** Authelia kann OIDC, ist aber nur als ForwardAuth konfiguriert. Nextcloud, Immich, Grafana, Mealie laufen mit eigenen User-DBs.
|
||||
- **Risiko:** N getrennte Passwortspeicher, N getrennte 2FA-Setups, keine zentrale Sperrung bei Account-Kompromittierung. Familie hat keinen einfachen Onboarding-Pfad.
|
||||
- **Empfehlung:** OIDC-Provider in Authelia aktivieren, Nextcloud (via Plugin), Immich (nativer OIDC-Support), Grafana (nativer OIDC-Support) als Clients konfigurieren. Vaultwarden via OIDC-Bridge nur, wenn der Aufwand klar mehrwertig ist — sonst bewusst auslassen.
|
||||
- **Prioritaet:** Sollte zeitnah (groesster Hebel laut Executive)
|
||||
- **Aufwand:** L
|
||||
- **Validierung:** Familienkonto kann sich mit einem Login bei Nextcloud + Immich + Grafana anmelden.
|
||||
|
||||
### F-14 · Kein WAF / Bouncer vor oeffentlichen Apps
|
||||
|
||||
- **Kategorie:** Security
|
||||
- **Fundstelle:** `traefik/docker-compose.yml`, oeffentliche Hosts in `docs/REPO_MAP.md:127-152`
|
||||
- **Beobachtung:** Sechs oeffentliche Apps mit nativer Auth (vault, paperless, mealie, ntfy, git, immich, cloud) ohne IP-Bouncer. Authelia-Regulation greift nur fuer die ForwardAuth-Pfade; Apps mit eigener Auth bekommen den vollen Traffic.
|
||||
- **Risiko:** Credential-Stuffing-Bot-Wellen treffen die App selbst (Nextcloud, Immich) — Logs sind im Loki, aber kein Sperr-Mechanismus.
|
||||
- **Empfehlung:** CrowdSec als Bouncer fuer Traefik (`crowdsecurity/traefik-bouncer`). Nutzt Loki/Logs fuer Erkennung, sperrt IPs auf Traefik-Ebene, bevor sie die Apps treffen.
|
||||
- **Prioritaet:** Sollte zeitnah
|
||||
- **Aufwand:** M
|
||||
- **Validierung:** CrowdSec-Dashboard zeigt erste Sperren; Test-Brute-Force gegen `nextcloud.kaleschke.info` wird bei N Versuchen geblockt.
|
||||
|
||||
### F-15 · Healthchecks fehlen grossflaechig
|
||||
|
||||
- **Kategorie:** Docker / Operations
|
||||
- **Fundstelle:** Spot-checks: `apps/paperless/docker-compose.yml`, `apps/immich/docker-compose.yml`, `security/authelia/docker-compose.yml`, `traefik/docker-compose.yml` — keiner hat `healthcheck:`-Block.
|
||||
- **Beobachtung:** Restart-Policy ist ueberall `unless-stopped`, aber ohne Healthcheck kann Docker keinen Crash-Loop bei "Container laeuft, aber App tot" erkennen.
|
||||
- **Risiko:** Bei Soft-Failure (Postgres-Connection-Pool tot, Authelia haengt im Storage-Connect) merkst du nichts, weil Container "running" bleibt.
|
||||
- **Empfehlung:** Fuer Tier-1 (Traefik `wget /ping`, Authelia `/api/health`, PostgreSQL `pg_isready`, Komodo `wget /api/healthcheck`) Healthchecks ergaenzen. Fuer Tier-2 schrittweise.
|
||||
- **Prioritaet:** Sollte zeitnah
|
||||
- **Aufwand:** M (pro Stack 5–15 Min)
|
||||
- **Validierung:** `docker ps` zeigt `(healthy)` neben den Tier-1-Containern.
|
||||
|
||||
### F-16 · `infra/redis` als "shared" deklariert, faktisch nur Paperless
|
||||
|
||||
- **Kategorie:** Architektur-Konsistenz
|
||||
- **Fundstelle:** `infra/redis/docker-compose.yml`, `docs/SERVICE_CATALOG.md:31` ("shared Redis Cache")
|
||||
- **Beobachtung:** Immich, Nextcloud, Mealie haben jeweils eigene Redis-Instanzen. Authelia nutzt bewusst kein Redis (MASTER 13). Paperless nutzt es laut Compose. Effektiv "Paperless-Redis im Frack des shared-Caches".
|
||||
- **Risiko:** Niedrig. Aber: Wenn du `infra/redis` fuer etwas anderes wegnimmst, denkst du, es kostet Paperless was — und das waere der Fall.
|
||||
- **Empfehlung:** Doku-Update: SERVICE_CATALOG 31 praezisieren ("dediziertes Redis fuer Paperless; andere Stacks haben eigene Redis-Instanzen"). Architektur bleibt, nur Etikett ehrlich machen. Alternativ: in `apps/paperless/` als App-internes Netz konsolidieren wie Mealie.
|
||||
- **Prioritaet:** Nice to have
|
||||
- **Aufwand:** S (Doku) / M (Architektur)
|
||||
|
||||
### F-17 · Plex bleibt als Host-Net-Stack
|
||||
|
||||
- **Kategorie:** Security / Architektur
|
||||
- **Fundstelle:** `host-services/plex/docker-compose.yml`, `MASTER 7.4`
|
||||
- **Beobachtung:** Plex laeuft als Host-Net wegen Discovery/GDM. Dokumentierte Ausnahme.
|
||||
- **Risiko:** Plex hat hoehere Angriffsoberflaeche als Apps mit Traefik. Plex-Login wurde mehrfach Ziel von Account-Uebernahmen (Plex.tv-Auth-Issues 2024/25). Bei Plex.tv-Kompromittierung greift Authelia nicht — Plex authentifiziert gegen Plex.tv.
|
||||
- **Empfehlung:** Plex bewusst beibehalten (Doku stuetzt), aber: (a) "Remote Access" in Plex-UI deaktivieren, wenn nur lokal/Tailscale genutzt. (b) Plex-Server nicht in `frontend_net` (waere schaedlich) — bleibt Host-Net, korrekt.
|
||||
- **Prioritaet:** Nice to have
|
||||
- **Aufwand:** S
|
||||
- **Validierung:** Plex `Remote Access` UI zeigt "disabled".
|
||||
|
||||
### F-18 · Nextcloud ohne ForwardAuth, ohne dedizierte Brute-Force-Doku
|
||||
|
||||
- **Kategorie:** Security
|
||||
- **Fundstelle:** `apps/nextcloud/docker-compose.yml`, `MASTER 13: Nextcloud-Entscheidung`
|
||||
- **Beobachtung:** Bewusste Ausnahme (WebDAV/CardDAV). In Nextcloud selbst sind Brute-Force-Schutz, 2FA-Pflicht und App-Passwords konfigurierbar, aber nicht im Repo dokumentiert.
|
||||
- **Risiko:** Familien-Konto mit schwachem Passwort + Nextcloud oeffentlich = direkter Pfad zu Dokumenten/Fotos.
|
||||
- **Empfehlung:** `apps/nextcloud/POST_INSTALL.md` mit Pflicht-Checkliste: Brute-Force-Plugin aktiv, 2FA-Provider TOTP installiert, Admin-Account hat 2FA, "Enforce 2FA for admin group" gesetzt. Optional: `OCC`-Befehle als Skript in `services/nextcloud-policy/`.
|
||||
- **Prioritaet:** Sollte zeitnah
|
||||
- **Aufwand:** S
|
||||
- **Validierung:** Test-Login ohne 2FA als Admin schlaegt fehl.
|
||||
|
||||
### F-19 · Keine Container-Memory-Limits
|
||||
|
||||
- **Kategorie:** Docker / Hardware-Schutz
|
||||
- **Fundstelle:** Spot-checks aller Composes
|
||||
- **Beobachtung:** Keine `mem_limit:` oder `deploy.resources.limits` Sektion in Tier-1- oder Tier-2-Stacks.
|
||||
- **Risiko:** Bei Image-Bug oder Memory-Leak (z. B. Immich-ML, Paperless-OCR-Loop) kann ein Container den Host in OOM treiben. Posture-Check + Docker-Critical-Events sehen das nachher, aber praeventiver waere Container-Limit + Docker-OOM-Kill fuer den richtigen Prozess.
|
||||
- **Empfehlung:** Fuer Tier-1 (Postgres, Authelia, Traefik, Komodo) sanfte Limits setzen (z. B. Postgres 2 GB, Authelia 256 MB, Traefik 256 MB). Fuer Immich-ML-Container ein hartes Limit, das Verhungern verhindert.
|
||||
- **Prioritaet:** Nice to have
|
||||
- **Aufwand:** M
|
||||
- **Validierung:** `docker stats` zeigt `MEM USAGE / LIMIT` ungleich `unlimited`.
|
||||
|
||||
### F-20 · Paperless-DBPass weiter als Stack-ENV (dokumentierte Ausnahme)
|
||||
|
||||
- **Kategorie:** Secrets
|
||||
- **Fundstelle:** `MASTER 13: Secrets in Komodo Stacks`, `docs/SECRETS_MAP.md:25`
|
||||
- **Beobachtung:** Paperless unterstuetzt `_FILE` nicht fuer DB-Pass. Bewusste Ausnahme.
|
||||
- **Risiko:** Stack-ENV liegt in Komodo-DB (Mongo), nicht im Repo. Bei Komodo-Mongo-Backup-Luecke fehlt das Passwort beim Restore.
|
||||
- **Empfehlung:** Erweiterung der Disaster-Recovery-Doku: explizite Liste aller "Stack-ENV-only"-Secrets mit Zeiger, dass `komodo-mongo.archive.gz` fuer Restore zwingend ist, oder die ENV manuell vorgehalten werden muss (in Vaultwarden + externer Notiz).
|
||||
- **Prioritaet:** Nice to have
|
||||
- **Aufwand:** S
|
||||
- **Validierung:** DR-Doc Abschnitt "Stack-ENV-Werte" referenziert konkrete Restore-Pfade.
|
||||
|
||||
---
|
||||
|
||||
# D. Risiko-Matrix
|
||||
|
||||
| Risiko | Bereich | Wahrscheinlichkeit | Auswirkung | Prioritaet | Massnahme |
|
||||
|---|---|---|---|---|---|
|
||||
| Borg-Passphrase weg -> Restore unmoeglich | Backup | niedrig | katastrophal | P0 | F-02 analoge Sicherung |
|
||||
| Hetzner-Account-Verlust -> halbes 3-2-1 | Backup | niedrig-mittel | hoch | P0/P1 | F-03 Zweitziel |
|
||||
| AdGuard-Admin-Manipulation aus LAN | Security | niedrig | hoch (DNS-Hijack) | P0 | F-01 Bind auf Tailscale |
|
||||
| Operator-Pwd-Leak -> 2FA fehlt fuer Borg-UI/Code-Server | Security | mittel | hoch | P0 | F-04 2FA-ACL erweitern |
|
||||
| Komodo-Self-Bootstrap-Failure nach Totalausfall | DR | niedrig | hoch | P1 | F-09 Bootstrap-Datei in `services/` |
|
||||
| Authelia Repo↔Host Drift unbemerkt | GitOps/Security | mittel | mittel | P1 | F-10 Diff-Check |
|
||||
| Immich Silent Corruption -> kein Restore-Test belegt | Backup | niedrig | sehr hoch (Familien-Fotos) | P1 | F-11 Restore-Test |
|
||||
| Cert-Expiry unbemerkt -> Public Apps down | Operations | niedrig | mittel | P1 | F-08 Alert-Regel |
|
||||
| Nextcloud Brute-Force ohne Bouncer | Security | mittel | mittel-hoch | P1 | F-14 CrowdSec / F-18 Nextcloud-Haerten |
|
||||
| Image-Update-Stillstand -> CVE bleibt | Security | mittel | mittel | P1 | F-12 Renovate |
|
||||
| Hermes-Wartungsschuld | Wartbarkeit | hoch | niedrig | P1 | F-06 Entscheidung |
|
||||
| Repo-Altstaende ueberleben -> Doppel-Deploy | GitOps | mittel | niedrig | P1 | F-05 Cleanup |
|
||||
| OOM durch unlimitierte Container | Hardware | niedrig | mittel | P2 | F-19 mem_limit |
|
||||
| Healthcheck-Luecke -> Soft-Failure stumm | Operations | mittel | niedrig | P2 | F-15 Healthchecks |
|
||||
| Monitoring-Stack ohne Digest-Pin | Reproduzierbarkeit | niedrig | niedrig | P2 | F-07 Digests + Renovate |
|
||||
| Hardware-SPOF (kein zweiter Host) | Hardware | niedrig | sehr hoch | P3 | Cold-Standby / 2. Host |
|
||||
|
||||
---
|
||||
|
||||
# E. Zielarchitektur (realistisch fuer privates Homelab)
|
||||
|
||||
**Hardware**
|
||||
|
||||
- 1× Unraid-Host (bestehend) als Production. CPU mit AVX2/AVX-512 fuer Immich-ML. ≥ 32 GB RAM (fuer 2× Postgres + Immich-ML + Loki/Prometheus + 2 VMs).
|
||||
- 2× NVMe als BTRFS-RAID1-Cache, sobald Cache-Auslastung > 70 % (STORAGE_LAYOUT 15.3).
|
||||
- Parity-Disk ≥ groesste Daten-Disk.
|
||||
- USV mit USB-Steuerung (NUT-faehig: APC Back-UPS RS 700+, Eaton 3S, CyberPower CP1500EPFCLCD). Direkter Shutdown bei Power-Loss.
|
||||
- Optional: zweiter alter Mini-PC oder NUC als Cold-Standby mit Tailscale, der den letzten Komodo-Bootstrap + Gitea-Mirror tragen kann.
|
||||
|
||||
**Netzwerk**
|
||||
|
||||
- FritzBox (bestehend) als Router + NAT.
|
||||
- VLANs nur wenn IoT-WLAN dazukommt (FritzBox-Gast-WLAN reicht fuer Anfang).
|
||||
- DNS: AdGuard -> Unbound (bestehend). Admin-UI nur Tailscale.
|
||||
- Tailscale (bestehend): Operator-Pfad. Subnet-Router optional fuer LAN-Devices ueber Tailscale.
|
||||
|
||||
**Storage**
|
||||
|
||||
- Cache `only` fuer `appdata`, `system`, `domains` (bestehend STORAGE_LAYOUT 4).
|
||||
- Disk1 (XFS) fuer `services`, `documents`, `photos`, `backups`, `media`, `finance`, `projekte`.
|
||||
- Externe Wechselplatte (XFS) fuer Cold-Off-Site mit fester monatlicher Rotation.
|
||||
|
||||
**Ordnerstruktur (Repo)**
|
||||
|
||||
- Beibehalten. Nur Cleanup von Altstaenden (F-05). Naming `kebab-case`-Migration aus STORAGE_LAYOUT 6 schrittweise.
|
||||
|
||||
**Docker**
|
||||
|
||||
- Compose-only via Komodo (bestehend).
|
||||
- Digest-Pin fuer alle Images (F-07).
|
||||
- Healthchecks fuer Tier-1 (F-15).
|
||||
- Mem-Limits fuer Tier-1 + Immich-ML (F-19).
|
||||
- App-interne Netze fuer Stack-Isolation (bestehend).
|
||||
|
||||
**Reverse Proxy**
|
||||
|
||||
- Traefik v3 (bestehend), DNS-Challenge, Wildcard.
|
||||
- Dynamic Config nur fuer Middlewares, TLS, Dashboard (bestehend).
|
||||
- CrowdSec-Bouncer (F-14) fuer oeffentliche Apps.
|
||||
|
||||
**Auth**
|
||||
|
||||
- Authelia als ForwardAuth **und** OIDC-Provider (F-13).
|
||||
- Nextcloud, Immich, Grafana via OIDC.
|
||||
- 2FA-Pflicht fuer alle Operator-Dienste (F-04).
|
||||
- Komodo bewusste Ausnahme (bestehend).
|
||||
|
||||
**Backup**
|
||||
|
||||
- Borg lokal (`/mnt/user/backups/borg/`) + Borg Hetzner + Wechselplatte.
|
||||
- Pre-Dump-Hooks (bestehend).
|
||||
- Borg-Passphrase off-system analog (F-02).
|
||||
- Restore-Tests automatisiert (F-11 Immich, dann andere via CI).
|
||||
|
||||
**Monitoring**
|
||||
|
||||
- `monitoring/`-Stack als alleinige Quelle. Altstaende raus (F-05).
|
||||
- Family-View-Dashboard in Grafana (alles gruen, Backup-Frische, Cert-Tage).
|
||||
- Alerts ausgebaut (F-08).
|
||||
- Posture-Check + Docker-Critical-Events -> ntfy `homelab-alerts` (bestehend).
|
||||
|
||||
**Dokumentation**
|
||||
|
||||
- Aktuelle Doku-Tiefe halten.
|
||||
- `SERVICES_RECOVERY.md` und `STORAGE_LAYOUT.md` (Active) finalisieren.
|
||||
- Familien-/User-Onboarding-Doku als eigenes kleines Dokument.
|
||||
|
||||
**GitOps**
|
||||
|
||||
- Gitea + Komodo (bestehend).
|
||||
- GitHub-Push-Mirror (umgesetzt, bestaetigt durch MASTER 7.1).
|
||||
- Renovate-Bot gegen Gitea (F-12).
|
||||
- Optional: Staging-Branch + zweites Komodo-Ziel in Tailscale-VM (Phase 3).
|
||||
|
||||
**Restore**
|
||||
|
||||
- RESTORE_MATRIX bleibt fuehrend.
|
||||
- Restore-Lab unter `/mnt/user/backups/restore-lab/` (bestehend).
|
||||
- Immich-Restore als Luecke schliessen (F-11).
|
||||
- Komodo-Self-Bootstrap raus aus Komodo (F-09).
|
||||
|
||||
---
|
||||
|
||||
# F. Priorisierte Massnahmenliste
|
||||
|
||||
| # | Aufgabe | Warum | Kategorie | Prio | Aufwand | Risiko (bei Nicht-Tun) | Mehrwert | Abhaengigkeiten | Validierung |
|
||||
|---|---|---|---|---|---|---|---|---|---|
|
||||
| 1 | Borg-Passphrase analog sichern | DR-SPOF schliessen | Backup | P0 | S | katastrophal | DR-Sicherheit | — | Wert ohne Host abrufbar |
|
||||
| 2 | AdGuard-Admin auf Tailscale-IP binden | LAN-Angriffsflaeche | Security | P0 | S | hoch | LAN-IoT-Haertung | — | `ss -ltnp` zeigt nur Tailscale |
|
||||
| 3 | 2FA-ACL erweitern (borg, code, files, traefik) | Operator-Pwd-Leak | Security | P0 | S | hoch | 2FA-Coverage | Authelia-TOTP-Setup | Login erzwingt 2FA |
|
||||
| 4 | Altstaende `ops/grafana-influxdb`+`ops/loki` `git rm` | Repo-Hygiene, kein Re-Deploy | GitOps | P0 | S | niedrig | Klarheit | Tag setzen | Policy-Check clean |
|
||||
| 5 | Hermes 60-Tage-Deadline | Wartungsschuld | App | P1 | S/L | mittel | Komplexitaet raus | Operator-Entscheidung | Entweder produktiv oder weg |
|
||||
| 6 | Immich-Restore-Test einrichten | Groesster Datentopf ungeprueft | Backup | P1 | M | hoch | Restore-Vertrauen | Restore-Lab-Pfad | Smoke-Test-Report |
|
||||
| 7 | Renovate-Bot in Gitea | manuelle Digest-Pflege | Wartung | P1 | M | mittel | Update-Hygiene | Gitea-Runner | erste PR offen |
|
||||
| 8 | Alert-Regeln (Borg-Frische, Cert-Expiry) | Blind-Spot Operations | Monitoring | P1 | M | mittel | echte Alerts | Pushgateway o. textfile | Alert in Test |
|
||||
| 9 | Family-View-Dashboard Grafana | Morgens 30 s Check | Monitoring | P1 | M | niedrig | Uebersicht | Datasources stehen | Dashboard funktioniert |
|
||||
| 10 | Komodo-Self-Bootstrap als `services/komodo-bootstrap/` | Henne-Ei-Problem | GitOps/DR | P1 | M | mittel | sauberer Recovery-Pfad | Komodo-Stack-Doku | Bootstrap aus Repo allein moeglich |
|
||||
| 11 | Authelia-Drift-Diff-Check in posture-check | Repo↔Host Drift | GitOps | P1 | S | mittel | Drift-Detektion | posture-check-Erweiterung | neuer Check sichtbar |
|
||||
| 12 | Healthchecks Tier-1 | Soft-Failure-Erkennung | Docker | P1 | M | niedrig | Self-Healing-Trigger | — | `docker ps` zeigt `healthy` |
|
||||
| 13 | CrowdSec-Bouncer vor Traefik | oeffentliche Apps schuetzen | Security | P1 | M | mittel | Brute-Force-Stop | Traefik-Middleware | Test-IP wird geblockt |
|
||||
| 14 | Nextcloud-Haertung dokumentieren | Public App + native Auth | Security | P1 | S | mittel | App-Haertung | Plugin-Install | 2FA-erzwingt |
|
||||
| 15 | Authelia OIDC-Provider + Nextcloud/Immich/Grafana | SSO, Familien-Onboarding | Security/UX | P2 | L | niedrig | hoher Mehrwert | Authelia-OIDC-Setup | SSO-Login funktioniert |
|
||||
| 16 | Immich-Smartphone-Auto-Backup fuer Familie | Killer-App fuer Familie | App | P2 | S | niedrig | hoher Mehrwert | — | Familien-Foto in Immich |
|
||||
| 17 | Monitoring-Stack Digests + Renovate-Pin | Reproduzierbarkeit | GitOps | P2 | S | niedrig | konsistent | Renovate optional | `@sha256` an allen Images |
|
||||
| 18 | Mem-Limits Tier-1 + Immich-ML | OOM-Schutz | Hardware/Docker | P2 | M | niedrig | Schutz | — | `docker stats` zeigt Limits |
|
||||
| 19 | Off-Site-Zweitziel (rsync.net o. Wechselplatte) | Single-Provider | Backup | P2 | M | mittel | 3-2-1 echt | Borg-Config | beide Repos < 7d |
|
||||
| 20 | Staging-Branch + 2. Komodo-Ziel | Risiko-Aenderung testbar | GitOps | P3 | L | niedrig | Reife | 2. VM/Host | Deploy auf staging klappt |
|
||||
|
||||
---
|
||||
|
||||
# G. Refactoring-Plan (Sprints)
|
||||
|
||||
## Sprint 0 — Sicherheitsnetz und Ist-Zustand sichern (1 Tag)
|
||||
|
||||
- **Ziel:** Du kannst danach im schlimmsten Fall alles, was du jetzt aenderst, sicher zurueckrollen.
|
||||
- **Aufgaben:**
|
||||
- Git-Tag `audit-2026-05-25-baseline` auf `master` setzen und nach Gitea + GitHub-Mirror pushen.
|
||||
- Borg-Lauf manuell ausloesen ("freshen up"), Erfolg im Log dokumentieren.
|
||||
- Aktuellen Komodo-Mongo-Dump verifizieren (`mongorestore --dry-run`).
|
||||
- `docs/MIGRATION_LOG.md` Eintrag "Audit-Sprint-Start".
|
||||
- **Erfolgskriterium:** Tag pushed, Borg-Lauf gruen, Mongo-Dump verifiziert.
|
||||
- **Validierung:** `git fetch && git tag | grep audit-2026-05-25-baseline` und `ls /mnt/user/backups/borg/dumps/latest/` zeigt fresh.
|
||||
- **Rollback:** N/A (rein additiv).
|
||||
- **Risiko bei Nichtumsetzung:** Keine Notbremse fuer Sprint 1.
|
||||
|
||||
## Sprint 1 — Offensichtliche Risiken entschaerfen (1 Woche)
|
||||
|
||||
- **Ziel:** P0-Risiken weg, Repo-Hygiene wieder gruen.
|
||||
- **Aufgaben (in dieser Reihenfolge):**
|
||||
1. F-02 Borg-Passphrase analog sichern (off-system, kein Code-Change).
|
||||
2. F-01 AdGuard-Admin-Port auf Tailscale-IP — Edit `host-services/Adguard/docker-compose.yml:16`.
|
||||
3. F-04 Authelia ACL erweitern (`two_factor` fuer borg, code, files, traefik) — Edit `security/authelia/configuration.yml` + Host-Sync.
|
||||
4. F-05 Altstaende `ops/grafana-influxdb/`, `ops/loki/` entfernen — `git rm`, MIGRATION_LOG.
|
||||
5. Policy-Check-Warnings `SEC001` (ddns-updater, scrutiny) aufraeumen.
|
||||
- **Erfolgskriterium:** Policy-Check 0 Warnings fuer SEC001, AdGuard-Admin nur via Tailscale, 2FA-Login auf borg.kaleschke.info.
|
||||
- **Validierung:** Policy-Check-Report; Browser-Test mit/ohne 2FA-Cookie.
|
||||
- **Rollback:** Commit-Revert pro Block.
|
||||
|
||||
## Sprint 2 — GitOps-Robustheit (1–2 Wochen)
|
||||
|
||||
- **Ziel:** Self-Bootstrap-Problem entschaerft, Drift-Detektion automatisiert.
|
||||
- **Aufgaben:**
|
||||
1. F-09 Komodo-Bootstrap-Compose nach `services/komodo-bootstrap/` extrahieren + dokumentierter Standalone-Restore-Pfad.
|
||||
2. F-10 Authelia-Drift-Diff in posture-check ergaenzen.
|
||||
3. F-11 Immich-Restore-Test einrichten (analog zu vaultwarden/gitea/paperless).
|
||||
4. F-06 Hermes-Entscheidung mit 60-Tage-Deadline schriftlich.
|
||||
- **Erfolgskriterium:** Komodo laesst sich aus Repo allein wiederherstellen. Posture-Check zeigt `authelia_config_drift: false`. Immich-Restore-Report unter `/mnt/user/backups/restore-reports/`.
|
||||
- **Validierung:** Trockenversuch (Komodo-Container stoppen, `docker compose up -d` aus `services/komodo-bootstrap/`).
|
||||
- **Rollback:** Bootstrap-Verzeichnis loeschen, Komodo-Self-Stack wie vorher.
|
||||
|
||||
## Sprint 3 — Backup & Restore belastbar machen (2–3 Wochen)
|
||||
|
||||
- **Ziel:** 3-2-1 echt, Restore-Tests breiter, Stack-ENV im DR-Pfad.
|
||||
- **Aufgaben:**
|
||||
1. F-03 Zweitziel: Wechselplatten-Rotation dokumentieren ODER zweites Borg-Repo (rsync.net / BorgBase EU2).
|
||||
2. F-20 Stack-ENV-Liste in DR-Doc explizit machen (Restore-Reihenfolge).
|
||||
3. Borg-Verifikation Cron fuer `borg check --repository-only` weekly (STORAGE_LAYOUT 8.4).
|
||||
4. Quartalsweise End-to-End-Restore-Drill in Schedule aufnehmen.
|
||||
- **Erfolgskriterium:** Beide Off-Site-Ziele < 7 Tage alt; DR-Doc enthaelt "ENV-Restore-Reihenfolge".
|
||||
- **Validierung:** `borg list` gegen beide Repos.
|
||||
|
||||
## Sprint 4 — Monitoring & Alerting ausbauen (2 Wochen)
|
||||
|
||||
- **Ziel:** Sichtbarkeit auf das, was wirklich weh tut.
|
||||
- **Aufgaben:**
|
||||
1. F-08 Alert-Regeln: `BorgArchiveStale`, `TLSCertExpiryNear`, `ContainerDown`, `PostgresConnSaturation`.
|
||||
2. F-15 Healthchecks fuer Traefik, Authelia, Postgres, Komodo, Gitea.
|
||||
3. F-07 Digest-Pin in `monitoring/docker-compose.yml`.
|
||||
4. Family-View-Dashboard in Grafana (1 Panel: Service-Up, 1 Panel: Backup-Frische, 1 Panel: Cert-Tage, 1 Panel: Disk-Fuellung).
|
||||
- **Erfolgskriterium:** Family-View zeigt alles gruen; Cert-Alert feuert in Test (Datum vorgespult).
|
||||
- **Validierung:** Dashboard sichtbar unter `monitoring.kaleschke.info/d/family-view`.
|
||||
|
||||
## Sprint 5 — Auth-Konsolidierung & Frontdoor-Haertung (3–4 Wochen)
|
||||
|
||||
- **Ziel:** SSO fuer die Familie, Brute-Force-Bouncer vor oeffentlichen Apps.
|
||||
- **Aufgaben:**
|
||||
1. F-13 Authelia OIDC-Provider aktivieren.
|
||||
2. Nextcloud OIDC-Plugin + Test-Login.
|
||||
3. Immich OIDC + Test-Login.
|
||||
4. Grafana OIDC + Test-Login.
|
||||
5. F-14 CrowdSec-Bouncer vor Traefik.
|
||||
6. F-18 Nextcloud-Haertung-Dokument + 2FA-Pflicht.
|
||||
- **Erfolgskriterium:** Familien-Konto loggt sich mit einem Login bei drei Apps ein; CrowdSec sperrt Test-IP nach N fehlerhaften Versuchen.
|
||||
- **Validierung:** OIDC-Sequenz im Browser ohne Eingabe-Wiederholung; CrowdSec-Dashboard zeigt Sperre.
|
||||
|
||||
## Sprint 6 — Automatisierung und Nerd-Level (laufend)
|
||||
|
||||
- **Ziel:** Image-Update-Pipeline, optional Staging.
|
||||
- **Aufgaben:**
|
||||
1. F-12 Renovate-Bot gegen Gitea.
|
||||
2. F-19 Mem-Limits Tier-1.
|
||||
3. Restore-Test-CI via Gitea Actions (P3).
|
||||
4. Optional: Staging-Branch + zweites Komodo-Ziel in Tailscale-VM (P3).
|
||||
5. Optional: Firefly III / Actual Budget fuer `/mnt/user/finance`.
|
||||
- **Erfolgskriterium:** Renovate-PRs erscheinen woechentlich; mindestens ein automatisches Patch-Update gemerged.
|
||||
|
||||
---
|
||||
|
||||
# H. Fehlende Informationen
|
||||
|
||||
> Nur, was den Audit konkret schaerfer machen wuerde.
|
||||
|
||||
| Frage | Warum | Bereich | Kommando / Datei |
|
||||
|---|---|---|---|
|
||||
| CPU-Modell, RAM-Groesse, Mainboard | Hardware-Bewertung, OOM-Risiko, Immich-ML-Eignung, AVX-Verfuegbarkeit | Hardware | `cat /proc/cpuinfo \| grep -E 'model name\|flags'`, `free -h`, `dmidecode -t baseboard \| head -20` |
|
||||
| USV vorhanden? Modell? | DR-Beurteilung Power-Loss, Shutdown-Pfad | Hardware/DR | physische Sichtpruefung; `apcaccess` falls APC mit NUT |
|
||||
| Stromverbrauch idle / Last | Betriebskosten, Sizing | Hardware | Smartmeter / Tibber-API |
|
||||
| NIC-Speed (1 GbE? 2.5 GbE?) | Backup-Durchsatz, Plex-Streaming | Netzwerk | `ip -br link`, `ethtool eth0` |
|
||||
| Disk-Inventar (Anzahl, Modelle, Alter) | Storage-Health, Replacement-Plan | Storage | `lsblk -o NAME,SIZE,MODEL,SERIAL`, Scrutiny-UI |
|
||||
| Aktueller Cache-Fuellstand | Wann zweite NVMe? | Storage | `df -h /mnt/cache` |
|
||||
| FritzBox-Modell + Firmware | Net-Sicherheit, VLAN-Faehigkeit | Netzwerk | FritzBox-UI / `fritzconnection` |
|
||||
| Tatsaechlich genutzte Plex- vs. ungenutzte App | Konsolidierungs-Belege | App-Landschaft | Plex-Server-Logs, ggf. Glances-Container-CPU pro Stack |
|
||||
| Existiert `/mnt/user/finance/`-Share schon? | Ist Firefly-Vorbereitung trivial? | Storage | `ls /mnt/user/finance/` |
|
||||
| Authelia Live-User-DB-Tiefe (Anzahl User, 2FA-Status) | 2FA-Coverage-Bewertung | Security | `cat /mnt/user/appdata/authelia/config/users_database.yml` (nur Strukturansicht, keine Hashes hier zitieren) |
|
||||
| Komodo-Mongo-Dump letzter Integrity-Check | F-09-Vorbereitung | Backup | `mongorestore --dry-run --archive=komodo-mongo.archive.gz --gzip` |
|
||||
| Aktuelle Cert-Restlaufzeit | F-08-Test-Vorbereitung | Operations | `openssl s_client -connect git.kaleschke.info:443 -servername git.kaleschke.info < /dev/null \| openssl x509 -noout -dates` |
|
||||
|
||||
---
|
||||
|
||||
# I. Pruefkommandos (Linux / Unraid / Docker / Windows)
|
||||
|
||||
> Strukturiert nach Bereich. Sicher zum Ausfuehren am Host.
|
||||
|
||||
### Hardware
|
||||
|
||||
```bash
|
||||
# CPU + Flags (AVX fuer Immich-ML)
|
||||
cat /proc/cpuinfo | awk '/model name|flags/ {print; if(/flags/) exit}'
|
||||
|
||||
# RAM
|
||||
free -h
|
||||
dmidecode -t memory | grep -E "Size|Speed" | head -20
|
||||
|
||||
# Mainboard
|
||||
dmidecode -t baseboard | head -20
|
||||
|
||||
# PCI / SATA / NVMe
|
||||
lspci
|
||||
nvme list
|
||||
lsblk -o NAME,SIZE,MODEL,SERIAL,FSTYPE,MOUNTPOINT,VENDOR
|
||||
|
||||
# SMART
|
||||
smartctl -a /dev/nvme0n1 | head -40
|
||||
smartctl -a /dev/sdb | head -40
|
||||
|
||||
# Stromverbrauch (Unraid Plugin oder ipmitool falls IPMI)
|
||||
sensors | head -30
|
||||
```
|
||||
|
||||
### Filesystem / Storage / Mounts
|
||||
|
||||
```bash
|
||||
# Filesystem-Typen (Hard Rule 12.1)
|
||||
findmnt -no FSTYPE /mnt/cache /mnt/disk1 /boot
|
||||
mount | grep -E "ntfs3|fuseblk" # darf leer sein
|
||||
|
||||
# Share-Settings
|
||||
ls -la /boot/config/shares/
|
||||
|
||||
# Cache-Fuellstand
|
||||
df -h /mnt/cache /mnt/disk1 /mnt/user
|
||||
du -sh /mnt/user/appdata/* | sort -hr | head -20
|
||||
```
|
||||
|
||||
### Docker
|
||||
|
||||
```bash
|
||||
# Container-Inventur
|
||||
docker ps --format "table {{.Names}}\t{{.Status}}\t{{.Image}}" | sort
|
||||
docker ps -a --filter "status=exited" --format "table {{.Names}}\t{{.Image}}\t{{.Status}}"
|
||||
|
||||
# Netzwerke
|
||||
docker network ls
|
||||
docker network inspect frontend_net | jq '.[0].Containers | keys'
|
||||
docker network inspect backend_net | jq '.[0].Internal'
|
||||
|
||||
# Volumes ohne Container (Waisen)
|
||||
docker volume ls -qf dangling=true
|
||||
|
||||
# Effektive Ports
|
||||
ss -ltnp | sort -k4
|
||||
|
||||
# Healthchecks
|
||||
docker ps --format "{{.Names}}\t{{.Status}}" | grep -E "healthy|unhealthy|starting"
|
||||
```
|
||||
|
||||
### Security
|
||||
|
||||
```bash
|
||||
# Privileged-Container und Docker-Socket-Mounts
|
||||
for c in $(docker ps -q); do
|
||||
docker inspect "$c" --format '{{.Name}}: priv={{.HostConfig.Privileged}}; sock={{range .HostConfig.Binds}}{{println .}}{{end}}'
|
||||
done | grep -E "priv=true|docker.sock"
|
||||
|
||||
# Direkte Host-Ports
|
||||
docker ps --format "{{.Names}}: {{.Ports}}" | grep -v "^[^:]*: $"
|
||||
|
||||
# Secret-Datei-Rechte
|
||||
ls -la /mnt/user/appdata/secrets/
|
||||
stat -c "%a %n" /mnt/user/appdata/secrets/*.txt
|
||||
```
|
||||
|
||||
### Backup / Restore
|
||||
|
||||
```bash
|
||||
# Borg-Frische
|
||||
ls -lat /mnt/user/backups/borg/dumps/latest/ | head
|
||||
find /mnt/user/backups/borg/dumps/latest -mmin +1440 -type f # aelter 24h
|
||||
|
||||
# Borg-Repo (Passphrase per File)
|
||||
export BORG_PASSPHRASE=$(cat /mnt/user/appdata/secrets/borg_repo_passphrase.txt)
|
||||
borg list ssh://... --short | tail -5
|
||||
borg info ssh://... ::Taegliche-Sicherung-2026-05-25T05:52:44.157
|
||||
|
||||
# Posture-Check
|
||||
cat /mnt/user/services/posture-check/last.json | jq '.warning_count, .critical_count'
|
||||
```
|
||||
|
||||
### Netzwerk / DNS
|
||||
|
||||
```bash
|
||||
# Tailscale
|
||||
tailscale status
|
||||
|
||||
# DNS auf AdGuard testen
|
||||
dig @127.0.0.1 git.kaleschke.info
|
||||
dig @127.0.0.1 example.com # Unbound-Recursion
|
||||
|
||||
# Cert-Restlaufzeit
|
||||
for h in vault git immich cloud paperless mealie ntfy; do
|
||||
echo -n "$h.kaleschke.info: "
|
||||
openssl s_client -connect ${h}.kaleschke.info:443 -servername ${h}.kaleschke.info </dev/null 2>/dev/null \
|
||||
| openssl x509 -noout -dates 2>/dev/null
|
||||
done
|
||||
```
|
||||
|
||||
### GitOps-Konsistenz
|
||||
|
||||
```bash
|
||||
# Komodo Stack-Workspace vs. Repo
|
||||
cd /mnt/user/services/stacks/<stackname>
|
||||
git rev-parse HEAD
|
||||
git status --short
|
||||
|
||||
# Webhook-Liveness
|
||||
docker logs komodo-core 2>&1 | grep -i "webhook\|deploy" | tail -20
|
||||
```
|
||||
|
||||
### Windows (lokal)
|
||||
|
||||
```powershell
|
||||
# Repo-Status
|
||||
git status --short
|
||||
git fetch origin
|
||||
git log origin/master..HEAD --oneline # ungepushte Commits
|
||||
git log HEAD..origin/master --oneline # ungepullte Commits
|
||||
|
||||
# Policy-Check
|
||||
.\ops\policy-checks\check_repo.ps1
|
||||
|
||||
# Restore-Freshness
|
||||
.\ops\restore-tests\check-restore-freshness.ps1
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
# J. Community- / Best-Practice-Abgleich
|
||||
|
||||
> Nur fuer die Architekturentscheidungen, bei denen der Markt eindeutig ist oder Gegenpositionen relevant sind.
|
||||
|
||||
| Entscheidung | Markt-Best-Practice | Stuetzende Quellen | Bewertung |
|
||||
|---|---|---|---|
|
||||
| Traefik mit Docker-Labels statt File-Provider | Standard in Selfhosted (siehe `awesome-selfhosted-docker`, Smarthome-Beginner Templates) | Traefik-Doc v3 docs.traefik.io/providers/docker | passt zu MASTER 13 (Wechsel 2026-03-28) |
|
||||
| DNS-Challenge mit Cloudflare statt HTTP-01 | Standard fuer Wildcard und reduzierte Angriffsflaeche | acme.sh / lego docs | passt, korrekt |
|
||||
| Authelia ForwardAuth statt Authentik | Authelia ist leichtgewichtiger, Authentik maechtiger; beide valide | r/selfhosted-Konsens 2024-25 | Authelia richtig fuer Single-Family-Setup |
|
||||
| Authelia ohne Redis-Session-Backend | Markt-Standard ist mit Redis; deine Vereinfachung ist begruendet (MASTER 13 2026-05-04) | Authelia-Doc | Trade-off klar; Bewertung: vertretbar fuer Homelab |
|
||||
| Komodo statt Portainer/Dockge | Komodo ist neuer (2024), Dockge etabliert, Portainer kommerziell | Selfh.st 2025 Comparison | Komodo legitim, mehr GitOps-nativ als Dockge |
|
||||
| Borg statt Restic/Kopia | Borg ist klassische Wahl fuer Linux-Backup mit Deduplikation; Kopia/Restic gewinnen mit Multi-Backend | r/datahoarder, ServeTheHome 2024 | Borg passt zu Unraid-Stack; bewusste Vereinfachung |
|
||||
| Glance statt Homepage als Single-Dashboard | beide auf Augenhoehe; Homepage etablierter, Glance moderner, schneller, mit Live-Widgets | github.com/glanceapp/glance vs. github.com/gethomepage/homepage | Glance legitim; Bewertung: deine Wahl ist verteidigbar |
|
||||
| Immich nicht hinter Authelia ForwardAuth | offizielle Immich-Doku raet bei nativer App-Auth davon ab, weil Sync-Clients OIDC oder direkte Auth brauchen | immich.app/docs/administration/reverse-proxy | korrekt; OIDC spaeter (F-13) ist der Weg |
|
||||
| Nextcloud klassisch statt AIO | NC-AIO ist offizielle Empfehlung fuer Neuaufbau, klassisch hat mehr Flexibilitaet fuer GitOps | NC-Blog 2024 | bewusste Ausnahme MASTER 13; vertretbar, da GitOps-Anbindung wichtiger |
|
||||
| Single-Host + Borg statt Proxmox-Cluster + ZFS-Send | fuer Familien-Homelab ist Cluster Overkill | r/homelab, LTT-Forum | Single-Host korrekt; Cold-Standby (Sprint 6) ist die richtige naechste Stufe |
|
||||
| AdGuard + Unbound statt Pi-hole | aequivalent; AdGuard hat moderne UI, Unbound recursion | gowri/networkchuck Tutorials 2024 | passt |
|
||||
| Posture-Check als Skript statt Goss/InSpec | fuer Single-Host pragmatisch | Goss ist maechtiger, aber Overkill | Skript-Loesung legitim |
|
||||
| Renovate gegen Gitea | mehrere Erfahrungsberichte in Gitea-Issues + Renovate-Docs | docs.renovatebot.com/modules/platform/gitea/ | Standard-Pfad |
|
||||
| CrowdSec vor Traefik | starker Trend 2024-25 in Selfhosted-Community | crowdsec.net/blog, Marius-Hosting-Tutorials | sinnvolle Haertung |
|
||||
|
||||
**Gegenpositionen, die du kennen solltest:**
|
||||
|
||||
- **"Authelia OIDC ist kompliziert, lieber Authentik."** Korrekt, wenn du auch B2B-SAML brauchst. Fuer reine Familien-OIDC ist Authelia leichter wartbar.
|
||||
- **"CrowdSec laedt zentrale Reputation-Listen -> Privacy-Bedenken."** Stimmt, du kannst Local-Only-Mode fahren. Fuer Homelab egal.
|
||||
- **"Renovate-Bot erzeugt Laerm."** Mit Group/Schedule-Rules zaehmbar. Wert > Laerm.
|
||||
- **"Komodo ist zu jung."** Gegenargument: du benutzt es seit Q1/2026 produktiv, Major-Inzidenz war beherrschbar. Der Wechsel zurueck zu Portainer/Dockge waere hoehere Kosten als der Reifegrad-Nachteil.
|
||||
|
||||
---
|
||||
|
||||
# K. Endziel — "Nerd-Level Homelab"
|
||||
|
||||
So sieht dein Homelab aus, wenn es wirklich auf Senior-Level ist:
|
||||
|
||||
**Betrieb im Alltag**
|
||||
|
||||
- Morgens 30 Sekunden auf `monitoring.kaleschke.info`: Family-View zeigt 7 Tier-1-Services gruen, Backup-Job in der Nacht hat 100 % Files erfasst, alle Certs > 30 Tage, Disk < 80 %.
|
||||
- Push-Benachrichtigung auf dem Handy nur, wenn wirklich etwas brennt (Posture-Check critical, Borg > 30 h, Endpoint down ≥ 8 Min, Cert < 14 Tage).
|
||||
- Familienmitglieder loggen sich mit einem Login bei Nextcloud, Immich, Mealie ein. 2FA per TOTP-App, kein App-by-App-Passwortzettel mehr.
|
||||
|
||||
**Updates**
|
||||
|
||||
- Renovate oeffnet woechentlich 5–10 Pull-Requests in Gitea fuer Patch-Versionen. Du siehst sie im Web-UI, pruefst Release Notes, klickst Merge. Komodo deployt automatisch via Webhook. Smoke-Test in der naechsten Glance-Seite.
|
||||
- Major-Updates kommen separat mit Label `major`, behandelst du in einem geplanten Slot mit Restore-Snapshot davor.
|
||||
|
||||
**Backups**
|
||||
|
||||
- Borg lokal alle 6 h, Borg Hetzner taeglich, Wechselplatte monatlich. Borg-Passphrase auf Papier im Bankschliessfach. Alle drei Ziele juenger als 36 h Alert-Schwelle.
|
||||
- Pre-Dump-Hooks erzeugen 15 konsistente Dump-Artefakte pro Lauf, automatische Posture-Check-Vor-Hook bricht Backup ab, wenn FS oder Mount sich veraendert haben.
|
||||
|
||||
**Restore**
|
||||
|
||||
- Monatlicher Mini-Restore-Test fuer Vaultwarden/Gitea/Paperless/Immich nach `/mnt/user/backups/restore-lab/<dienst>/` laeuft automatisiert per Gitea Actions, Erfolgs-Report landet als Datei + ntfy-Info.
|
||||
- Quartalsweise End-to-End-Drill: ein kompletter Stack restauriert, App startet, Smoke-Test passt, Doku validiert. Komodo-Bootstrap-Pfad ist getestet.
|
||||
- Im Ernstfall folgst du `docs/DISASTER_RECOVERY.md` Phase 0–5 und bist nach < 8 h wieder im Vollbetrieb. Repo-Bootstrap aus GitHub-Mirror, Stacks in Stufen 1–5, Verifikation pro Stufe.
|
||||
|
||||
**Monitoring**
|
||||
|
||||
- Prometheus + Loki + Grafana + Alertmanager-ntfy-Bridge. ~15 Alert-Regeln, alle in `alerts.yml` versioniert.
|
||||
- Family-View, Host-Overview, Containers+Logs, Traefik-Standalone, Backup-Frische, Cert-Tage. Sechs Dashboards mehr braucht keine Familie.
|
||||
- Loki sammelt 30 Tage Logs aus allen Containern via Promtail. cAdvisor + node-exporter liefern Container- und Host-Metriken. Blackbox testet oeffentliche Endpoints alle 60 s.
|
||||
|
||||
**Security**
|
||||
|
||||
- Authelia OIDC fuer Nextcloud, Immich, Grafana, Mealie. ForwardAuth fuer Operator-UIs mit 2FA-Pflicht ab Tier-2.
|
||||
- CrowdSec sperrt Brute-Force-IPs auf Traefik-Ebene bevor sie die Apps treffen.
|
||||
- AdGuard-Admin nur via Tailscale. Operator-Pfad ausschliesslich Tailscale.
|
||||
- Authelia-Repo-Baseline und Host-Config sind per Diff-Check im posture-check abgesichert.
|
||||
- Secrets-Mounts mode 600, Borg-Passphrase analog.
|
||||
|
||||
**Dokumentation**
|
||||
|
||||
- SERVICE_CATALOG, RESTORE_MATRIX, DISASTER_RECOVERY, STORAGE_LAYOUT, SECRETS_MAP, WORKFLOW, GITOPS_DRIFT_RUNBOOK, ALERTING_MAP, HOMELAB_ARCHITECTURE_MASTER bleiben aktuelle Single-Source-of-Truth.
|
||||
- `services/komodo-bootstrap/` loest das Henne-Ei. `SERVICES_RECOVERY.md` ist final, nicht Draft.
|
||||
- Familien-Onboarding-Doku als Markdown: "So nutzt du Nextcloud-Web", "So aktivierst du Immich-Foto-Backup auf dem Handy", "So loggst du dich neu per 2FA ein".
|
||||
|
||||
**Taegliche Nutzung**
|
||||
|
||||
- Familie scannt Briefe per ASN-Barcode in `scans_inbox/`, Paperless tagged via paperless-gpt automatisch, alles durchsuchbar.
|
||||
- Immich erfasst Smartphone-Fotos aller Familienmitglieder automatisch, Familie blaettert per Web/App, Tagging per ML.
|
||||
- Nextcloud traegt Kalender, Kontakte, geteilte Familienordner per WebDAV/CardDAV — kein Google/Apple-Lock-In.
|
||||
- Mealie speichert Rezepte, Einkaufsliste auf dem Handy.
|
||||
- Vaultwarden ist der einzige Passwort-Tresor der Familie; Familien-Organisation aktiv.
|
||||
- Plex streamt Heim-Medien an alle Endgeraete.
|
||||
- ntfy schickt dir Vorfaelle aufs Handy — und sonst nichts.
|
||||
- Optional: Firefly III fuer die Familien-Finanzen, Ecowitt-Wetter-Dashboard, Home-Assistant-Automationen fuer Strom-Eigenverbrauch.
|
||||
|
||||
**Was bewusst weggelassen ist**
|
||||
|
||||
- Kein Kubernetes. Komodo + Compose reicht.
|
||||
- Kein zweiter Medienserver neben Plex (Jellyfin-Entscheidung 2026-05-25).
|
||||
- Kein zweites Dashboard neben Glance (Homepage-Entscheidung 2026-05-25).
|
||||
- Kein Uptime-Kuma neben Blackbox (Entscheidung 2026-05-25).
|
||||
- Kein Hermes-Agent, wenn er bis 2026-07-25 keinen klaren Alltagsnutzen liefert.
|
||||
- Kein BentoPDF/paperless-gpt 24/7, wenn nicht aktiv genutzt.
|
||||
- Kein Self-Stack-Komodo (durch `services/komodo-bootstrap/` ersetzt).
|
||||
|
||||
---
|
||||
|
||||
## Schlussbemerkung
|
||||
|
||||
Das Setup ist naeher an Senior-Reife als an Bastel-Niveau. Der groesste Hebel der naechsten drei Monate ist **Konsolidieren statt erweitern** (Hermes-Entscheidung, Altstaende raus, Auth-SSO, Off-Site-Diversitaet), kombiniert mit der einen Aktivierung, die das Setup vom Operator-Tool zum **Familien-Tool** macht: Immich-Smartphone-Backup fuer alle.
|
||||
|
||||
Das vorhandene 2026-05-23-Audit hat die richtigen Sprintziele bereits identifiziert. Diese externe Audit-Sicht ergaenzt:
|
||||
|
||||
- **2FA-Pflicht auf Tier-1-Operator-UIs** (F-04) — fehlt in der Bewertung 2026-05-23 in dieser Klarheit.
|
||||
- **Healthcheck-Luecke** (F-15) und **fehlende Mem-Limits** (F-19) — operative Detail-Findings, die in der strategischen Bewertung nicht auftauchen.
|
||||
- **Komodo-Self-Bootstrap als konkreter Code-Vorschlag** (F-09) statt nur als Risiko-Erwaehnung.
|
||||
- **Authelia-Drift-Detection automatisieren** (F-10) statt nur "manuell merge".
|
||||
- **Monitoring-Stack ohne Digest-Pin** (F-07) — Inkonsistenz mit der eigenen Image-Pinning-Disziplin.
|
||||
- **`infra/redis` ist faktisch nicht shared** (F-16) — Etikett-Realitaet-Drift.
|
||||
- **Alert-Regeln deutlich zu duenn** (F-08) — Sichtbarkeitsluecken bei Cert/Borg/Container-Down.
|
||||
|
||||
Wenn Sprint 1–3 in 4–6 Wochen sitzen, bist du auf einer 1-Note. Wenn dann Sprint 4–5 in weiteren 6–8 Wochen kommen, hat die Familie ein echtes Self-Hosting-System, kein "Container-Sammlung im Keller". Das ist der Unterschied, den der Audit-Auftrag adressiert.
|
||||
@@ -0,0 +1,86 @@
|
||||
# Audit TODO 2026-05-25
|
||||
|
||||
Quelle: `docs/AUDIT_2026-05-25.md`
|
||||
|
||||
Status: Arbeitsliste fuer die Umsetzung. Authelia-2FA/OIDC bleibt bewusst spaet, weil die Ziel-Policy noch nicht final entschieden ist.
|
||||
|
||||
## Leitplanken
|
||||
|
||||
- Keine Authelia-2FA-ACL-Aenderungen in den ersten Sprints.
|
||||
- Keine Live-riskanten Bind-/Port-Aenderungen ohne vorher erfasste Host-Werte, insbesondere Tailscale-IP.
|
||||
- Erst Inventar und Baseline, dann Aenderungen.
|
||||
- Jede produktive Aenderung bekommt Validierung und Rollback-Hinweis.
|
||||
|
||||
## Sprint 0 - Inventar und Baseline
|
||||
|
||||
| Status | Aufgabe | Ergebnis |
|
||||
|---|---|---|
|
||||
| in Arbeit | Hardware-Inventar ausfuellen | CPU, RAM, Mainboard, NIC, Disks und SMART erfasst; USV/Strom/BIOS offen |
|
||||
| in Arbeit | Netzwerk-Inventar ausfuellen | Host-IP, Gateway, Tailscale-IP und AdGuard-Bind erfasst; Router-/VLAN-Details offen |
|
||||
| offen | Externe Abhaengigkeiten dokumentieren | `docs/EXTERNAL_DEPENDENCIES.md` enthaelt Provider, Kritikalitaet, Ausfallplan |
|
||||
| offen | Services-Recovery-Pfade beschreiben | `docs/SERVICES_RECOVERY.md` enthaelt Gitea-/Komodo-/Secrets-Sonderpfade |
|
||||
| offen | Baseline-Tag setzen | `audit-2026-05-25-baseline` ist lokal und remote vorhanden |
|
||||
| erledigt | Policy-Check neu ausfuehren | SEC001-Warnings aus altem Report sind nicht mehr aktuell |
|
||||
|
||||
## Sprint 1 - Nicht-kontroverse Sicherheits- und Repo-Hygiene
|
||||
|
||||
| Status | Aufgabe | Ergebnis |
|
||||
|---|---|---|
|
||||
| offen | Borg-Passphrase analog sichern | Passphrase ist ohne Host/Vaultwarden wiederherstellbar |
|
||||
| erledigt (repo) | AdGuard Admin-Bind vorbereiten | Tailscale-IP `100.80.98.33` erfasst, Compose-Soll geaendert |
|
||||
| offen (deploy) | AdGuard Admin-Port auf Tailscale-IP binden | Nach Deploy muss `ss -ltnp` `100.80.98.33:8082` zeigen |
|
||||
| offen | Alte Monitoring-Verzeichnisse entfernen | `ops/grafana-influxdb/` und `ops/loki/` sind aus Repo/Doku entfernt oder als expliziter Rollback-Archive-Pfad markiert |
|
||||
| offen | Policy-Warnings triagieren | Jede Warning ist behoben oder bewusst dokumentiert |
|
||||
|
||||
## Sprint 2 - Storage und Recovery verbindlich machen
|
||||
|
||||
| Status | Aufgabe | Ergebnis |
|
||||
|---|---|---|
|
||||
| offen | `docs/STORAGE_LAYOUT.draft.md` finalisieren | Datei wird als `docs/STORAGE_LAYOUT.md` Active gefuehrt |
|
||||
| offen | Disk- und Share-TBDs eintragen | Modelle, Groessen, Seriennummern, Filesysteme und Cache-Settings sind dokumentiert |
|
||||
| offen | Gitea-Repo-Mirror-Mechanik definieren | Mirror fuer `/mnt/user/services/gitea/git/repositories/` mit Frequenz <= 6 h ist spezifiziert |
|
||||
| offen | Komodo-Bootstrap-Pfad beschreiben | Kaltstart ohne laufendes Komodo ist dokumentiert |
|
||||
| offen | Immich-Restore-Test planen | Testumfang, Datenpfade und Smoke-Test-Kriterium stehen fest |
|
||||
|
||||
## Sprint 3 - Restore und Monitoring
|
||||
|
||||
| Status | Aufgabe | Ergebnis |
|
||||
|---|---|---|
|
||||
| offen | Immich-Restore-Test implementieren | Restore-Report landet unter `/mnt/user/backups/restore-reports/` |
|
||||
| offen | Borg-Stale-Alert bauen | Alarm feuert, wenn Borg-Archiv zu alt ist |
|
||||
| offen | TLS-Cert-Expiry-Alert bauen | Alarm feuert bei Restlaufzeit unter Schwellwert |
|
||||
| offen | Container-Down-Alert bauen | Unerwartet fehlende Container werden sichtbar |
|
||||
| offen | Family-View Dashboard definieren | Uptime, Backup-Frische, Cert-Tage, Disk-Fuellung auf einer Seite |
|
||||
|
||||
## Sprint 4 - Familien- und Betriebsdoku
|
||||
|
||||
| Status | Aufgabe | Ergebnis |
|
||||
|---|---|---|
|
||||
| offen | Familien-Onboarding schreiben | Nextcloud, Immich, Vaultwarden, 2FA-Verlust, Ausfallverhalten kurz erklaert |
|
||||
| offen | Capacity-/Lifecycle-Review erstellen | Wachstum, Schwellenwerte, Upgrade-Trigger und Disk-Replacement-Plan dokumentiert |
|
||||
| offen | USV-Test oder USV-Entscheidung | Power-Loss-Verhalten ist bekannt und dokumentiert |
|
||||
|
||||
## Sprint 5 - Auth und Frontdoor, bewusst zuletzt
|
||||
|
||||
| Status | Aufgabe | Ergebnis |
|
||||
|---|---|---|
|
||||
| geparkt | Authelia 2FA fuer Operator-UIs erweitern | Erst nach finaler Policy-Entscheidung |
|
||||
| geparkt | Authelia OIDC fuer Apps pruefen | Erst nach Familien-/Client-Auswirkungsanalyse |
|
||||
| geparkt | CrowdSec vor Traefik pruefen | Nach stabiler Auth-/Monitoring-Basis |
|
||||
|
||||
## Offene Host-Werte
|
||||
|
||||
Diese Werte muessen am Unraid-Host erhoben werden, bevor die entsprechenden Aenderungen sauber umgesetzt werden:
|
||||
|
||||
```bash
|
||||
hostname
|
||||
cat /proc/cpuinfo | awk '/model name|flags/ {print; if(/flags/) exit}'
|
||||
free -h
|
||||
dmidecode -t baseboard | head -30
|
||||
ip -br link
|
||||
tailscale ip -4
|
||||
lsblk -o NAME,SIZE,MODEL,SERIAL,FSTYPE,MOUNTPOINT,VENDOR
|
||||
df -h /mnt/cache /mnt/disk1 /mnt/user
|
||||
smartctl -a /dev/nvme0n1 | head -80
|
||||
smartctl -a /dev/sdb | head -80
|
||||
```
|
||||
@@ -0,0 +1,63 @@
|
||||
# Capacity and Lifecycle - KalliLab CORE
|
||||
|
||||
Status: Template, auszufuellen nach Hardware-/Storage-Audit.
|
||||
|
||||
## Zweck
|
||||
|
||||
Dieses Dokument haelt Wachstum, Schwellenwerte und Upgrade-Trigger fest. Es verhindert, dass Storage-, RAM- oder Backup-Entscheidungen erst dann getroffen werden, wenn der Host bereits unter Druck steht.
|
||||
|
||||
## Aktuelle Kapazitaet
|
||||
|
||||
| Bereich | Groesse | Belegt | Frei | Schwellwert | Bewertung |
|
||||
|---|---:|---:|---:|---:|---|
|
||||
| Cache | TBD | TBD | TBD | 70 % Planung / 85 % Aktion | TBD |
|
||||
| Disk1 | TBD | TBD | TBD | 80 % Planung / 90 % Aktion | TBD |
|
||||
| Backups lokal | TBD | TBD | TBD | TBD | TBD |
|
||||
| Hetzner Borg | TBD | TBD | TBD | TBD | TBD |
|
||||
| Externe Cold-Platte | TBD | TBD | TBD | TBD | TBD |
|
||||
|
||||
Pruefkommando:
|
||||
|
||||
```bash
|
||||
df -h /mnt/cache /mnt/disk1 /mnt/user
|
||||
du -sh /mnt/user/appdata/* | sort -hr | head -30
|
||||
du -sh /mnt/user/documents /mnt/user/photos /mnt/user/media /mnt/user/backups 2>/dev/null
|
||||
```
|
||||
|
||||
## Wachstumsbereiche
|
||||
|
||||
| Bereich | Erwartetes Wachstum | Risiko | Naechste Aktion |
|
||||
|---|---|---|---|
|
||||
| Immich Fotos/Videos | TBD | hoechster privater Datentopf | Restore-Test priorisieren |
|
||||
| Paperless Dokumente | TBD | wichtig, moderates Wachstum | Restore-Test existiert |
|
||||
| Nextcloud | TBD | Familiennutzung kann stark wachsen | Quota/Backup pruefen |
|
||||
| Monitoring/Loki | TBD | Retention kann Disk fuellen | Retention dokumentieren |
|
||||
| Borg Dumps | TBD | Retention und Excludes pruefen | Borg-Stale + Groessenprofil |
|
||||
|
||||
## Upgrade-Trigger
|
||||
|
||||
| Trigger | Massnahme |
|
||||
|---|---|
|
||||
| Cache dauerhaft >70 % | Zweite NVMe oder Appdata-Verteilung planen |
|
||||
| Cache >85 % | Sofortmassnahme, keine grossen Deployments |
|
||||
| Disk1 >80 % | Array-Erweiterung planen |
|
||||
| Disk1 >90 % | Keine neuen grossen Datenimporte, Erweiterung priorisieren |
|
||||
| RAM >90 % ueber 10 Minuten regelmaessig | RAM-Ausbau oder Service-Limits pruefen |
|
||||
| Borg-Laufzeit deutlich steigend | Scope, Netzwerk und Ziel pruefen |
|
||||
| SMART-Warnung | Ersatz planen, Restore-/Backup-Frische pruefen |
|
||||
|
||||
## Restore-Zeitziele
|
||||
|
||||
| Tier | Beispiel | Zielzeit | Status |
|
||||
|---|---|---:|---|
|
||||
| Tier 0 | Repo, Secrets, Traefik, DNS | TBD | offen |
|
||||
| Tier 1 | Gitea, Vaultwarden, Paperless, Immich | TBD | offen |
|
||||
| Tier 2 | Nextcloud, Mealie, Monitoring | TBD | offen |
|
||||
| Tier 3 | Komfort-/Ops-Tools | TBD | offen |
|
||||
|
||||
## Review-Log
|
||||
|
||||
| Datum | Befund | Entscheidung |
|
||||
|---|---|---|
|
||||
| TBD | Initial ausfuellen | TBD |
|
||||
|
||||
@@ -9,6 +9,8 @@ Verwandte Dokumente:
|
||||
- `docs/ROLLBACK.md` - Rueckweg bei Fehlern im laufenden GitOps-Betrieb
|
||||
- `docs/RESTORE_MATRIX.md` - Restore-Quellen und Verifikationsregeln pro Dienst
|
||||
- `docs/RESTORE_HANDBOOK.md` - praktische Restore-Betriebsanleitung
|
||||
- `docs/SERVICES_RECOVERY.md` - Recovery-kritische `/mnt/user/services`-Pfade, Gitea-Mirror und Komodo-Bootstrap
|
||||
- `docs/EXTERNAL_DEPENDENCIES.md` - externe Provider/Konten und Ausfall-Szenarien
|
||||
- `ops/borg-ui/BACKUP_SCOPE.md` - Zielbild des Borg-Scopes
|
||||
|
||||
---
|
||||
@@ -66,6 +68,8 @@ Diese Punkte sollten **vor** einem echten Ausfall geklaert sein:
|
||||
| Borg-Passphrase | Host-Secret-Datei vorhanden und fuer Borg-Zugriff verifiziert; externe analoge Hinterlegung bleibt Operator-Aufgabe |
|
||||
| Secrets-Dateien | ueber Borg bzw. Restore-Quellen abgedeckt |
|
||||
| Komodo Stack ENV-Werte | extern dokumentiert, z. B. Vaultwarden |
|
||||
| Services-Recovery | `docs/SERVICES_RECOVERY.md` gepflegt, insbesondere Gitea-Repo-Mirror und Komodo-Bootstrap |
|
||||
| Hardware-/Netzwerkdaten | `docs/HARDWARE_INVENTORY.md` und `docs/NETWORK_INVENTORY.md` mit echten Werten gefuellt |
|
||||
| Restore-Smoke-Tests | fuer mindestens 1-2 kritische Dienste nachgewiesen |
|
||||
|
||||
**Wichtig:** Dieses Dokument ist nur so gut wie die Vorbereitung ausserhalb des Repos.
|
||||
@@ -204,6 +208,7 @@ Besonders kritisch:
|
||||
- `/mnt/user/services/homelab-infra`
|
||||
- `/mnt/user/services/stacks`
|
||||
- `/mnt/user/services/posture-check`
|
||||
- Details zu `/mnt/user/services/` und Komodo/Gitea-Bootstrap stehen in `docs/SERVICES_RECOVERY.md`
|
||||
- `/mnt/user/services/gitea/data`
|
||||
- `/mnt/user/appdata/authelia/config`
|
||||
- `/mnt/user/appdata/komodo/core`
|
||||
|
||||
@@ -0,0 +1,64 @@
|
||||
# External Dependencies - KalliLab CORE
|
||||
|
||||
Status: Template, auszufuellen und quartalsweise zu pruefen.
|
||||
|
||||
## Zweck
|
||||
|
||||
Dieses Dokument beschreibt externe Anbieter und Konten, von denen Betrieb, Recovery oder Zugriff abhaengen. Ziel ist, im Ausfallfall nicht erst suchen zu muessen, welcher Provider welches Teilproblem verursacht.
|
||||
|
||||
## Abhaengigkeiten
|
||||
|
||||
| Anbieter / System | Zweck | Kritikalitaet | Recovery-Auswirkung | Zugang / Besitz | Notfallplan |
|
||||
|---|---|---:|---|---|---|
|
||||
| Domain-Registrar | Besitz `kaleschke.info` | hoch | Ohne Domain brechen Public URLs/TLS-Erneuerung | TBD | Registrar-Zugang und 2FA-Recovery sichern |
|
||||
| Cloudflare DNS | Authoritative DNS, ACME DNS-Challenge | hoch | Neue Zertifikate/DNS-Aenderungen blockiert | TBD | API-Token rotierbar, Account-Recovery dokumentieren |
|
||||
| Hetzner Storage Box | Off-site Borg Backup | kritisch | Restore aus Off-site ggf. nicht moeglich | TBD | Zweites Off-site-Ziel oder Cold-Platte etablieren |
|
||||
| GitHub Mirror | Externer Repo-Mirror | mittel/hoch | Gitea-Verlust abfederbar | TBD | Mirror-URL und Token-Recovery dokumentieren |
|
||||
| Tailscale | Remote-/Operator-Zugang | hoch | Remote-Zugriff erschwert, lokale Bedienung bleibt | TBD | Break-glass LAN-Zugang dokumentieren |
|
||||
| GMX SMTP | Authelia Notifier | mittel | Mail-Notifier faellt aus, Login selbst nicht zwingend | TBD | ntfy/zweiter SMTP als Fallback pruefen |
|
||||
| Let's Encrypt | TLS-Zertifikate | hoch | Cert-Erneuerung faellt aus | via Traefik/Cloudflare | Cert-Expiry Alert einrichten |
|
||||
| Container Registries | Image Pulls | mittel | Redeploy/Update blockiert | oeffentlich/Token TBD | Gepinnte Digests und lokale Runtime helfen kurzfristig |
|
||||
|
||||
## Kritische Secrets ausserhalb des Repos
|
||||
|
||||
Authoritativ ist `docs/SECRETS_MAP.md`. Diese Liste markiert nur externe Abhaengigkeiten.
|
||||
|
||||
| Secret | Zweck | Recovery-Hinweis |
|
||||
|---|---|---|
|
||||
| Borg Passphrase | Entschluesselung Borg-Repos | Muss analog/off-system vorhanden sein |
|
||||
| Cloudflare DNS API Token | ACME DNS-Challenge | Token-Rotation und Scope pruefen |
|
||||
| GitHub Mirror Token | Push-Mirror | In Gitea/GitHub verwaltet, nicht im Repo |
|
||||
| Tailscale Account Recovery | Tailnet-Zugang | Account-2FA/Recovery Codes sichern |
|
||||
| SMTP Passwort | Authelia Mail | In Host-Secret, Fallback pruefen |
|
||||
|
||||
## Ausfall-Szenarien
|
||||
|
||||
### Hetzner Storage Box nicht erreichbar
|
||||
|
||||
- Lokales Borg-Repo und aktuelle Dumps pruefen.
|
||||
- Keine destruktiven Host-Aenderungen starten, solange Off-site unklar ist.
|
||||
- Zweites Off-site-Ziel oder Cold-Platte als Folgeaufgabe umsetzen.
|
||||
|
||||
### Cloudflare Account/DNS gestoert
|
||||
|
||||
- Bestehende Zertifikate laufen bis Ablauf weiter.
|
||||
- Keine Domain-/ACME-Aenderungen moeglich.
|
||||
- Tailscale/LAN-Zugang als Break-glass nutzen.
|
||||
|
||||
### Tailscale gestoert
|
||||
|
||||
- Lokalen LAN-Zugang nutzen.
|
||||
- Direkte Admin-Ports nur gemaess dokumentierten Ausnahmen verwenden.
|
||||
- AdGuard-Admin-Bind muss so geplant werden, dass ein lokaler Break-glass-Weg bekannt ist.
|
||||
|
||||
### Domain verloren oder Registrar-Zugriff verloren
|
||||
|
||||
- Gitea/GitHub Mirror und lokale IP/Tailscale-Pfade fuer Recovery nutzen.
|
||||
- Neue Domain waere separater Migrationsfall fuer Traefik, Authelia, App-URLs und Clients.
|
||||
|
||||
## Review
|
||||
|
||||
| Datum | Ergebnis | Naechste Aktion |
|
||||
|---|---|---|
|
||||
| TBD | Initial ausfuellen | Provider-Zugaenge und Recovery-Codes pruefen |
|
||||
|
||||
@@ -0,0 +1,38 @@
|
||||
# Family Onboarding - KalliLab CORE
|
||||
|
||||
Status: Entwurf. Zielgruppe sind Familienmitglieder, nicht Operatoren.
|
||||
|
||||
## Zweck
|
||||
|
||||
Diese Datei soll spaeter kurz und alltagstauglich erklaeren, wie die wichtigsten Dienste genutzt werden und was bei Problemen zu tun ist. Keine Restore-Matrix, keine Docker-Begriffe.
|
||||
|
||||
## Dienste
|
||||
|
||||
| Dienst | URL | Zweck | Konto / Login | Notiz |
|
||||
|---|---|---|---|---|
|
||||
| Nextcloud | `https://cloud.kaleschke.info` | Dateien, Kalender, Kontakte | TBD | Mobile App/WebDAV/CardDAV |
|
||||
| Immich | `https://immich.kaleschke.info` | Fotos und Smartphone-Backup | TBD | Backup-App pro Handy |
|
||||
| Vaultwarden | `https://vault.kaleschke.info` | Passwoerter | TBD | Familien-Organisation pruefen |
|
||||
| Mealie | `https://mealie.kaleschke.info` | Rezepte und Einkauf | TBD | TBD |
|
||||
| Paperless | `https://paperless.kaleschke.info` | Dokumente | TBD | Scan-/Inbox-Prozess beschreiben |
|
||||
| Plex | intern/App | Medien | TBD | TBD |
|
||||
|
||||
## Was tun bei Problemen?
|
||||
|
||||
| Situation | Verhalten |
|
||||
|---|---|
|
||||
| Webseite nicht erreichbar | 10 Minuten warten, dann Operator informieren |
|
||||
| Passwort vergessen | Operator informieren, nicht selbst neue Konten anlegen |
|
||||
| Handy-Foto-Backup stoppt | App oeffnen, WLAN/Batteriesparmodus pruefen, Operator informieren |
|
||||
| 2FA verloren | Operator informieren; Recovery-Prozess wird separat festgelegt |
|
||||
| Warnmeldung vom Browser | Nicht weiterklicken, Screenshot machen, Operator informieren |
|
||||
|
||||
## Offene Inhalte
|
||||
|
||||
| Status | Aufgabe |
|
||||
|---|---|
|
||||
| offen | Pro Dienst kurze Schritt-fuer-Schritt-Anleitung schreiben |
|
||||
| offen | Konto-/2FA-Policy final entscheiden |
|
||||
| offen | Immich Mobile Backup fuer alle Geraete testen |
|
||||
| offen | Vaultwarden Familienorganisation pruefen |
|
||||
|
||||
@@ -0,0 +1,177 @@
|
||||
# Hardware Inventory - KalliLab CORE
|
||||
|
||||
Status: Initialer Host-Audit erfasst, offene Punkte markiert.
|
||||
Host: `Kallilabcore`
|
||||
Letzte Pruefung: 2026-05-26
|
||||
Naechster Review: 2026-08-26
|
||||
|
||||
## Zweck
|
||||
|
||||
Dieses Dokument beschreibt die physische Basis des Homelabs. Es ist die Grundlage fuer Capacity Planning, Restore-Zeit, Ersatzteilplanung, USV-Verhalten und Entscheidungen wie Immich-ML, Plex-Transcoding oder Storage-Erweiterung.
|
||||
|
||||
## Host
|
||||
|
||||
| Feld | Wert |
|
||||
|---|---|
|
||||
| Hostname | Kallilabcore |
|
||||
| Standort | Heim-LAN, physischer Standort TBD |
|
||||
| Betriebssystem | Unraid |
|
||||
| Unraid-Version | 7.2.4 |
|
||||
| Rolle | Single-Host Homelab, Docker Compose via Komodo |
|
||||
| Boot-Medium | Samsung Flash Drive, 59.8G, FAT32 |
|
||||
| Flash-Backup | In Borg-Scope aufgenommen, siehe `docs/MIGRATION_LOG.md` |
|
||||
|
||||
## CPU
|
||||
|
||||
| Feld | Wert |
|
||||
|---|---|
|
||||
| Modell | 12th Gen Intel(R) Core(TM) i5-12400F |
|
||||
| Kerne / Threads | 6 Kerne / 12 Threads |
|
||||
| Architektur | x86_64 |
|
||||
| Relevante Flags | AVX, AVX2, FMA, AES, VT-x vorhanden; kein AVX-512 |
|
||||
| iGPU / Quick Sync | Nein, `F`-CPU ohne iGPU |
|
||||
|
||||
Pruefkommando:
|
||||
|
||||
```bash
|
||||
cat /proc/cpuinfo | awk '/model name|flags/ {print; if(/flags/) exit}'
|
||||
lscpu
|
||||
```
|
||||
|
||||
## RAM
|
||||
|
||||
| Feld | Wert |
|
||||
|---|---|
|
||||
| Gesamt | 31 GiB |
|
||||
| Belegt im Normalbetrieb | ca. 7.8 GiB genutzt, ca. 23 GiB verfuegbar |
|
||||
| Slots / Ausbau | 4x 8 GB DDR4 belegt |
|
||||
| ECC | Nein |
|
||||
|
||||
Pruefkommando:
|
||||
|
||||
```bash
|
||||
free -h
|
||||
dmidecode -t memory | grep -E "Size|Speed|Locator|Type" | head -40
|
||||
```
|
||||
|
||||
## Mainboard und Controller
|
||||
|
||||
| Feld | Wert |
|
||||
|---|---|
|
||||
| Mainboard | Gigabyte Technology Co., Ltd. B760M DS3H DDR4 |
|
||||
| BIOS/Firmware | TBD |
|
||||
| SATA/HBA Controller | Onboard, Details TBD |
|
||||
| NVMe Slots | mindestens 1 belegt |
|
||||
|
||||
Pruefkommando:
|
||||
|
||||
```bash
|
||||
dmidecode -t baseboard | head -30
|
||||
lspci
|
||||
```
|
||||
|
||||
## Netzwerk-Hardware
|
||||
|
||||
| Interface | Speed | Rolle | Bemerkung |
|
||||
|---|---:|---|---|
|
||||
| eth0 / bond0 / br0 | 1 Gbit/s full duplex | LAN | Host-IP `192.168.178.58/24`, Gateway `192.168.178.1` |
|
||||
| tailscale1 | virtuell | VPN | Tailscale IPv4 `100.80.98.33` |
|
||||
|
||||
Pruefkommando:
|
||||
|
||||
```bash
|
||||
ip -br link
|
||||
ethtool <interface>
|
||||
tailscale ip -4
|
||||
```
|
||||
|
||||
## Storage
|
||||
|
||||
| Slot | Device | Modell | Seriennummer | Groesse | Filesystem | Rolle | Health |
|
||||
|---|---|---|---|---:|---|---|---|
|
||||
| Cache | `nvme0n1p1` | Samsung SSD 970 EVO Plus 2TB | `S4J4NM0W609649H` | 1.8T | XFS | Appdata/system/domains | SMART passed |
|
||||
| Disk1 | `md1p1` / physisch `sdc` | WDC WD60EFAX-68JH4N1 | `WD-WX32D90PC0V0` | 5.5T | XFS auf md1p1 | Array-Daten | SMART passed |
|
||||
| Parity | physisch `sdb` | TOSHIBA HDWG480 | `2460A03VFA3H` | 7.3T | n/a | Parity | SMART passed |
|
||||
| Boot | `sda1` | Samsung Flash Drive | `0375125090000587` | 59.8G | FAT32 | Unraid Boot | aktiv |
|
||||
| Cold Backup | TBD | TBD | TBD | TBD | TBD | Externe Rotation | offen |
|
||||
|
||||
Pruefkommando:
|
||||
|
||||
```bash
|
||||
lsblk -o NAME,SIZE,MODEL,SERIAL,FSTYPE,MOUNTPOINT,VENDOR
|
||||
findmnt -no FSTYPE /mnt/cache /mnt/disk1 /boot
|
||||
df -h /mnt/cache /mnt/disk1 /mnt/user
|
||||
```
|
||||
|
||||
## SMART / Health
|
||||
|
||||
| Device | Letzter Check | Kritische Werte | Bewertung |
|
||||
|---|---|---|---|
|
||||
| /dev/nvme0n1 | 2026-05-26 | Critical Warning `0x00`, Percentage Used `0%`, Media Errors `0`, Power On Hours `370`, Written `5.87 TB` | gut |
|
||||
| /dev/sdb | 2026-05-26 | Reallocated `0`, Pending `0`, Uncorrectable `0`, CRC `1`, Power On Hours `8971` | gut, CRC-Wert beobachten |
|
||||
| /dev/sdc | 2026-05-26 | Reallocated `0`, Pending `0`, Uncorrectable `0`, CRC `0`, Power On Hours `14174` | gut |
|
||||
|
||||
Pruefkommando:
|
||||
|
||||
```bash
|
||||
smartctl -a /dev/nvme0n1
|
||||
smartctl -a /dev/sdb
|
||||
smartctl -a /dev/sdc
|
||||
```
|
||||
|
||||
## USV / Power Loss
|
||||
|
||||
| Feld | Wert |
|
||||
|---|---|
|
||||
| USV vorhanden | Unklar |
|
||||
| Modell | TBD |
|
||||
| Verbindung | TBD |
|
||||
| Software | `apcaccess` vorhanden, aber `apcupsd` auf `localhost:3551` antwortet nicht |
|
||||
| Laufzeit im Idle | TBD |
|
||||
| Shutdown-Schwelle | TBD |
|
||||
| Letzter Shutdown-Test | TBD |
|
||||
|
||||
Bewertung:
|
||||
|
||||
- Wenn keine USV vorhanden ist: Risiko fuer Docker-/DB-State und laufende Writes bleibt offen.
|
||||
- Wenn USV vorhanden ist: Shutdown-Pfad muss mindestens einmal getestet und dokumentiert werden.
|
||||
- Aktueller Befund 2026-05-26: USV-Status ist nicht validiert; `apcaccess status` liefert `Connection refused`.
|
||||
|
||||
## Stromverbrauch
|
||||
|
||||
| Zustand | Verbrauch | Messmethode | Datum |
|
||||
|---|---:|---|---|
|
||||
| Idle | TBD | TBD | TBD |
|
||||
| Normalbetrieb | TBD | TBD | TBD |
|
||||
| Backup-Lauf | TBD | TBD | TBD |
|
||||
| Last | TBD | TBD | TBD |
|
||||
|
||||
## Ersatzteil- und Lifecycle-Plan
|
||||
|
||||
| Komponente | Trigger | Massnahme |
|
||||
|---|---|---|
|
||||
| Cache-NVMe | >70 % Fuellstand oder SMART-Warnung | Zweite NVMe / Pool-Entscheidung; aktuell 6 % belegt |
|
||||
| Disk1 | >80 % Fuellstand oder SMART-Warnung | Array-Erweiterung / Ersatz; aktuell 33 % belegt |
|
||||
| Parity | Kleiner als neue groesste Datenplatte | Parity-Upgrade vor Datenplatten-Upgrade |
|
||||
| Boot-USB | Lesefehler oder Alter TBD | Flash-Backup verifizieren, Ersatzstick vorbereiten |
|
||||
| RAM | Swap/OOM oder Immich/Nextcloud-Druck | Ausbau planen |
|
||||
|
||||
## Audit-Kommandos
|
||||
|
||||
```bash
|
||||
hostname
|
||||
uname -a
|
||||
cat /etc/unraid-version 2>/dev/null || true
|
||||
lscpu
|
||||
free -h
|
||||
dmidecode -t baseboard | head -30
|
||||
dmidecode -t memory | grep -E "Size|Speed|Locator|Type" | head -40
|
||||
ip -br link
|
||||
tailscale ip -4
|
||||
lsblk -o NAME,SIZE,MODEL,SERIAL,FSTYPE,MOUNTPOINT,VENDOR
|
||||
findmnt -no FSTYPE /mnt/cache /mnt/disk1 /boot
|
||||
df -h /mnt/cache /mnt/disk1 /mnt/user
|
||||
smartctl -a /dev/nvme0n1 | head -100
|
||||
smartctl -a /dev/sdb | head -100
|
||||
smartctl -a /dev/sdc | head -100
|
||||
```
|
||||
@@ -16,6 +16,20 @@ Dieses Dokument ist nur noch ein historischer Verlauf. Der aktuelle operative Ab
|
||||
|
||||
## Historische Meilensteine
|
||||
|
||||
### 2026-05-26 - AdGuard Admin-Port auf Tailscale-Soll begrenzt
|
||||
|
||||
- Host-Audit per SSH gegen `Kallilabcore` durchgefuehrt: Tailscale IPv4 ist `100.80.98.33`, LAN-IP ist `192.168.178.58/24`, Gateway `192.168.178.1`.
|
||||
- Repo-Soll fuer `host-services/Adguard/docker-compose.yml` geaendert: DNS `53/tcp+udp` bleibt unveraendert, die Admin-UI bindet nun auf `100.80.98.33:8082:80`.
|
||||
- Architektur, Service-Katalog, Repo-Map, Netzwerk-Inventar und AI-Kontext wurden an das neue Modell angepasst: keine Traefik-/Authelia-2FA-Umstellung, aber keine LAN-weite Admin-Bindung mehr.
|
||||
- Live-Deploy/Validierung bleibt nach GitOps-Commit/Push zu pruefen: `ss -ltnp | grep :8082` muss nur `100.80.98.33:8082` zeigen, DNS auf Port 53 muss weiter funktionieren.
|
||||
|
||||
### 2026-05-26 - Audit-Umsetzung vorbereitet
|
||||
|
||||
- Aus `docs/AUDIT_2026-05-25.md` wurde `docs/AUDIT_2026-05-25_TODO.md` als operative Arbeitsliste abgeleitet. Authelia-2FA/OIDC bleibt bewusst geparkt und wird erst nach finaler Policy-Entscheidung umgesetzt.
|
||||
- Neue Inventar- und Betriebsdokumente angelegt: `docs/HARDWARE_INVENTORY.md`, `docs/NETWORK_INVENTORY.md`, `docs/EXTERNAL_DEPENDENCIES.md`, `docs/CAPACITY_AND_LIFECYCLE.md` und `docs/FAMILY_ONBOARDING.md`.
|
||||
- `docs/SERVICES_RECOVERY.md` beschreibt initial die recovery-kritischen `/mnt/user/services`-Pfade, Gitea-Repo-Mirror-Optionen, Komodo-Bootstrap und Secret-Recovery-Reihenfolge.
|
||||
- Policy-Check lokal erneut ausgefuehrt: die alten SEC001-Warnings fuer `ddns-updater` und `scrutiny` sind nicht mehr aktuell; verbleibende Warnings betreffen Host-Netz-/User-/Image-Tag-Themen und Altstaende.
|
||||
|
||||
### 2026-05-25 - Unraid Flash-Backup in Borg-Scope aufgenommen
|
||||
|
||||
- `pre-backup-dumps.sh` erzeugt zusaetzlich zu den DB-Dumps ein sensibles `unraid-flash-config.tar.gz` aus `/boot/config` inklusive SHA256 und Manifest unter `/mnt/user/backups/borg/dumps/latest`.
|
||||
|
||||
@@ -0,0 +1,106 @@
|
||||
# Network Inventory - KalliLab CORE
|
||||
|
||||
Status: Initialer Host-Audit erfasst, Router-/VLAN-Details offen.
|
||||
Letzte Pruefung: 2026-05-26
|
||||
|
||||
## Zweck
|
||||
|
||||
Dieses Dokument beschreibt Router, DNS, Tailscale, Portfreigaben und Netztrennung. Es ergaenzt das Architektur-Zielbild in `HOMELAB_ARCHITECTURE_MASTER_V2.md` um konkrete Hardware- und Betriebswerte.
|
||||
|
||||
## Internet und Router
|
||||
|
||||
| Feld | Wert |
|
||||
|---|---|
|
||||
| Anschluss / Provider | TBD |
|
||||
| Router-Modell | TBD |
|
||||
| Firmware | TBD |
|
||||
| Router-IP | 192.168.178.1 |
|
||||
| DHCP-Server | vermutlich Router, zu pruefen |
|
||||
| Lokales Subnetz | 192.168.178.0/24 |
|
||||
| IPv6 aktiv | TBD |
|
||||
| DynDNS / DDNS | Cloudflare via `ddns-updater`, Details TBD |
|
||||
|
||||
## DNS
|
||||
|
||||
| Komponente | Rolle | Adresse | Bemerkung |
|
||||
|---|---|---|---|
|
||||
| AdGuard Home | LAN DNS / Filter | Host `192.168.178.58`, Docker `172.23.0.3` | DNS auf Port 53; Admin soll nur via Tailscale-IP `100.80.98.33:8082` erreichbar sein |
|
||||
| Unbound | Rekursiver Resolver | Docker `dns_net` | Upstream fuer AdGuard |
|
||||
| Cloudflare | Authoritative DNS | extern | DNS-Challenge fuer TLS |
|
||||
| Router | DHCP DNS-Verteilung | TBD | Muss auf AdGuard zeigen, falls so betrieben |
|
||||
|
||||
## Tailscale
|
||||
|
||||
| Feld | Wert |
|
||||
|---|---|
|
||||
| Node-Name | Kallilabcore |
|
||||
| Tailscale IPv4 | 100.80.98.33 |
|
||||
| Tailscale IPv6 | TBD |
|
||||
| Exit Node | TBD |
|
||||
| Subnet Router | TBD |
|
||||
| ACL-Policy extern dokumentiert | TBD |
|
||||
|
||||
Pruefkommando:
|
||||
|
||||
```bash
|
||||
tailscale status
|
||||
tailscale ip -4
|
||||
tailscale ip -6
|
||||
```
|
||||
|
||||
## Portfreigaben und Exposure
|
||||
|
||||
| Port | Ziel | Zweck | Bewertung |
|
||||
|---:|---|---|---|
|
||||
| 80/tcp | Traefik | HTTP->HTTPS / ACME | erwartet |
|
||||
| 443/tcp | Traefik | HTTPS | erwartet |
|
||||
| 222/tcp | Gitea SSH | Git SSH | dokumentierte Ausnahme |
|
||||
| 53/tcp+udp | AdGuard | DNS | dokumentierte Ausnahme |
|
||||
| 8082/tcp | AdGuard Admin | Admin UI | Repo-Soll: nur `100.80.98.33:8082`, DNS-Port 53 unveraendert |
|
||||
| 8181/tcp | InfluxDB 3 Core | LAN Writer fuer Home Assistant | LAN-only, Bind-IP pruefen |
|
||||
|
||||
Pruefkommando:
|
||||
|
||||
```bash
|
||||
ss -ltnp | sort -k4
|
||||
docker ps --format "{{.Names}}: {{.Ports}}" | sort
|
||||
```
|
||||
|
||||
## Netztrennung
|
||||
|
||||
| Netz | Status | Bemerkung |
|
||||
|---|---|---|
|
||||
| LAN | 192.168.178.0/24 | Hauptnetz, Host `192.168.178.58` |
|
||||
| Gast-WLAN | TBD | Zugriff auf AdGuard Admin muss ausgeschlossen sein |
|
||||
| IoT-Netz | TBD | Zugriff auf AdGuard Admin muss ausgeschlossen sein |
|
||||
| Tailscale | aktiv | Operator-Zugang, Host-IP `100.80.98.33` |
|
||||
| VLANs | TBD | Router-/Switch-Faehigkeit pruefen |
|
||||
|
||||
## Docker-Netze
|
||||
|
||||
Authoritativ ist `HOMELAB_ARCHITECTURE_MASTER_V2.md`. Dieses Inventar haelt nur den Laufzeit-Snapshot fest.
|
||||
|
||||
| Docker-Netz | Zweck | Erwartung |
|
||||
|---|---|---|
|
||||
| frontend_net | Traefik/Web | external bridge |
|
||||
| backend_net | DB/Cache intern | internal bridge |
|
||||
| dns_net | AdGuard/Unbound | bridge |
|
||||
| monitoring_net | Observability | compose-intern |
|
||||
| app-interne Netze | Stack-isoliert | nur wenn technisch noetig |
|
||||
|
||||
Pruefkommando:
|
||||
|
||||
```bash
|
||||
docker network ls
|
||||
docker network inspect frontend_net | jq '.[0].Containers | keys'
|
||||
docker network inspect backend_net | jq '.[0].Internal'
|
||||
```
|
||||
|
||||
## Offene Entscheidungen
|
||||
|
||||
| Thema | Status | Naechster Schritt |
|
||||
|---|---|---|
|
||||
| AdGuard Admin nur via Tailscale | repo-seitig vorbereitet | Compose bindet Admin-Port auf `100.80.98.33:8082`; Live-Validierung nach Deploy |
|
||||
| Gast-/IoT-Zugriff auf Admin-Ports | offen | Router-Regeln pruefen |
|
||||
| IPv6 Exposure | offen | Router und Traefik/Cloudflare pruefen |
|
||||
| Home Assistant InfluxDB Bind | offen | Effektive Listener-Adresse pruefen |
|
||||
+10
-1
@@ -31,6 +31,13 @@ Secret-Werte werden hier nicht dokumentiert. Aufgefuehrt werden nur Variablennam
|
||||
| `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, Dump-Artefakte und Smoke-Tests je Dienst |
|
||||
| `docs/SERVICES_RECOVERY.md` | Recovery-kritische `/mnt/user/services`-Pfade, Gitea-Mirror und Komodo-Bootstrap |
|
||||
| `docs/HARDWARE_INVENTORY.md` | Hardware-, Disk-, SMART-, USV- und Strom-Inventar |
|
||||
| `docs/NETWORK_INVENTORY.md` | Router, DNS, Tailscale, Portfreigaben und Netztrennung |
|
||||
| `docs/EXTERNAL_DEPENDENCIES.md` | Externe Provider, Konten, Ausfall-Szenarien und kritische Off-Repo-Abhaengigkeiten |
|
||||
| `docs/CAPACITY_AND_LIFECYCLE.md` | Capacity-Schwellen, Wachstum, Upgrade-Trigger und Restore-Zeitziele |
|
||||
| `docs/FAMILY_ONBOARDING.md` | Familienorientierte Nutzungsdoku ohne Operator-Details |
|
||||
| `docs/AUDIT_2026-05-25_TODO.md` | Operative Arbeitsliste aus dem Audit vom 2026-05-25; Authelia-2FA bewusst geparkt |
|
||||
| `docs/ALERTING_MAP.md` | ntfy Topic-Konvention und Sender-Mapping fuer Homelab-Alerts |
|
||||
| `docs/ROLLBACK.md` | Rueckweg bei Fehlern im GitOps-Betrieb |
|
||||
| `docs/SECRETS_MAP.md` | Secret-Namen, Pfade und Einbindungsarten ohne Werte |
|
||||
@@ -97,7 +104,7 @@ Secret-Werte werden hier nicht dokumentiert. Aufgefuehrt werden nur Variablennam
|
||||
|
||||
| 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; Admin 8082 bleibt bewusst LAN-direkt |
|
||||
| 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`, `100.80.98.33:8082:80/tcp` | Unbound in `dns_net`; DNS-Port 53 ist direkte Ausnahme; Admin 8082 ist auf Tailscale-IP begrenzt |
|
||||
| Plex | `host-services/plex/docker-compose.yml` | `plex` -> `plexinc/pms-docker:1.43.1.10611-1e34174b1@sha256:...` | keine Traefik-Route | `network_mode: host` | host network | Medienserver; Host-Netz bleibt fuer Discovery / Plex GDM dokumentierte Ausnahme |
|
||||
| Tailscale | `host-services/tailscale/docker-compose.yml` | `Tailscale-Docker` -> `tailscale/tailscale:stable@sha256:...` | keine | `network_mode: host` | host network | VPN/Remote-Zugang |
|
||||
|
||||
@@ -238,6 +245,8 @@ Das Skript liest Secret-Dateien auf dem Host und schreibt Dump-Artefakte. Bei An
|
||||
## Unsicherheiten / TODOs aus Repo-Sicht
|
||||
|
||||
- Echte `stack.env`- und `.env`-Dateien sind per `.gitignore` ausgeschlossen; nur `*.example`-Dateien gehoeren ins Repo.
|
||||
- Hardware-, Netzwerk- und Provider-Inventare sind initiale Templates und muessen nach einem Host-Audit mit echten Werten gefuellt werden.
|
||||
- Authelia-2FA-/OIDC-Aenderungen sind nach Audit 2026-05-25 bewusst geparkt und werden nicht als Sofortmassnahme behandelt.
|
||||
- Authelia `configuration.yml` ist Repo-Baseline fuer nicht geheime Einstellungen, wird aber nicht automatisch von Komodo auf den Host kopiert. Die produktive Host-Datei kann zusaetzliche OIDC-/Secret-Konfiguration enthalten; Aenderungen muessen manuell gemerged und validiert werden.
|
||||
- `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.
|
||||
|
||||
@@ -0,0 +1,98 @@
|
||||
# Services Recovery - KalliLab CORE
|
||||
|
||||
Status: Initiale Spezifikation, aus dem Audit 2026-05-25 abgeleitet.
|
||||
Verwandte Docs: `docs/DISASTER_RECOVERY.md`, `docs/RESTORE_MATRIX.md`, `docs/STORAGE_LAYOUT.draft.md`, `docs/SECRETS_MAP.md`
|
||||
|
||||
## Zweck
|
||||
|
||||
Der Share `/mnt/user/services/` ist recovery-kritisch, weil dort GitOps- und Host-Automation-Pfade liegen. Dieses Dokument beschreibt, welche Services-Pfade gesichert werden muessen und wie ein Kaltstart ohne laufendes Komodo gedacht ist.
|
||||
|
||||
## Kritische Pfade
|
||||
|
||||
| Pfad | Zweck | Kritikalitaet | Backup-Anforderung |
|
||||
|---|---|---:|---|
|
||||
| `/mnt/user/services/homelab-infra` | Host-Repo-Clone fuer Automation/Posture | hoch | Borg + GitHub/Gitea Mirror |
|
||||
| `/mnt/user/services/stacks` | Komodo Stack Workspaces | hoch | Borg, vor strukturellen Aenderungen extra sichern |
|
||||
| `/mnt/user/services/gitea/git/repositories` | Gitea Repository-Inhalte | kritisch | Borg + separater Mirror <= 6 h |
|
||||
| `/mnt/user/services/posture-check` | Hostseitig ausgefuehrte Checks | hoch | Borg + Repo-Abgleich |
|
||||
| `/mnt/user/appdata/secrets` | Runtime Secrets | kritisch | Borg + ausgewählte analoge/off-system Kopien |
|
||||
|
||||
## Gitea Repository Mirror
|
||||
|
||||
Ziel: Verlustfenster fuer `/mnt/user/services/gitea/git/repositories/` auf maximal 6 Stunden begrenzen.
|
||||
|
||||
Optionen:
|
||||
|
||||
| Option | Bewertung |
|
||||
|---|---|
|
||||
| `git bundle` je Repository auf zweites Medium | Sehr gut fuer Git-Recovery, transparent, gut pruefbar |
|
||||
| `rsync` auf externe Platte oder zweiten Host | Einfach, aber Ziel muss regelmaessig erreichbar und geprueft sein |
|
||||
| Separates Borg-Repo mit kurzem Schedule | Konsistent zum bestehenden Backup, aber wieder Borg-/Passphrase-abhaengig |
|
||||
|
||||
Empfohlener Start:
|
||||
|
||||
1. `git bundle`-Job fuer alle Gitea-Repositories definieren.
|
||||
2. Ziel auf zweitem physischen Medium oder separatem Off-site-Ziel ablegen.
|
||||
3. Job alle 6 Stunden ausfuehren.
|
||||
4. Stichprobe: ein Bundle in Wegwerfpfad klonen.
|
||||
|
||||
Erfolgskriterium:
|
||||
|
||||
```bash
|
||||
git clone /path/to/repo.bundle /tmp/repo-restore-test
|
||||
git -C /tmp/repo-restore-test fsck
|
||||
```
|
||||
|
||||
## Komodo Bootstrap
|
||||
|
||||
Problem: Komodo verwaltet Stacks, ist aber selbst Teil des Recovery-Pfads. Ein kalter Host darf nicht voraussetzen, dass Komodo schon laeuft.
|
||||
|
||||
Minimaler Wiederanlauf:
|
||||
|
||||
1. Docker und externe Netze herstellen (`frontend_net`, `backend_net`, ggf. weitere dokumentierte Netze).
|
||||
2. Repo aus Gitea/GitHub Mirror klonen.
|
||||
3. Komodo Compose aus `ops/komodo/docker-compose.yml` oder einem spaeteren Bootstrap-Pfad starten.
|
||||
4. Erforderliche `.env`/Secrets aus Host-Secret-Backup wiederherstellen.
|
||||
5. Komodo-Core, Periphery und Mongo starten.
|
||||
6. Web-UI und Periphery-Verbindung pruefen.
|
||||
|
||||
Offene Aufgabe:
|
||||
|
||||
- Entscheiden, ob ein eigener Pfad `services/komodo-bootstrap/` ins Repo kommt oder `ops/komodo/docker-compose.yml` die verbindliche Bootstrap-Quelle bleibt.
|
||||
|
||||
Validierung:
|
||||
|
||||
```bash
|
||||
docker compose -f ops/komodo/docker-compose.yml config
|
||||
docker compose -f ops/komodo/docker-compose.yml up -d
|
||||
docker ps --filter "name=komodo"
|
||||
```
|
||||
|
||||
## Secrets Recovery Reihenfolge
|
||||
|
||||
Authoritativ ist `docs/SECRETS_MAP.md`. Fuer den Kaltstart ist diese Reihenfolge praktisch:
|
||||
|
||||
1. Borg-Passphrase analog/off-system beschaffen.
|
||||
2. Borg-Repo-Zugang/SSH-Key wiederherstellen.
|
||||
3. `/mnt/user/appdata/secrets/` aus Borg wiederherstellen.
|
||||
4. Komodo Stack ENV / Recovery ENV wiederherstellen.
|
||||
5. Gitea Secrets und SSH-Material wiederherstellen.
|
||||
6. Traefik/Cloudflare Secret wiederherstellen.
|
||||
7. App-spezifische Secrets nach Tier-Reihenfolge wiederherstellen.
|
||||
|
||||
## Break-glass Regeln
|
||||
|
||||
- Keine Secret-Werte in Git oder Tickets kopieren.
|
||||
- Restore-Tests laufen in Wegwerfpfaden, nie direkt gegen produktive Pfade.
|
||||
- Wenn Gitea und Komodo beide down sind, gewinnt der externe GitHub-Mirror als Repo-Quelle.
|
||||
- Wenn Borg ohne Passphrase nicht entschluesselbar ist, ist Recovery blockiert. Deshalb ist die analoge Passphrase-Sicherung P0.
|
||||
|
||||
## Naechste Aufgaben
|
||||
|
||||
| Status | Aufgabe |
|
||||
|---|---|
|
||||
| offen | Gitea-Bundle- oder Mirror-Mechanik final entscheiden |
|
||||
| offen | Komodo-Bootstrap-Quelle finalisieren |
|
||||
| offen | Restore-Kommandos nach erstem Trockenlauf mit echten Pfaden ergaenzen |
|
||||
| offen | Services-Recovery in `docs/DISASTER_RECOVERY.md` verlinken |
|
||||
|
||||
@@ -11,7 +11,7 @@ Secret-Werte sind nicht enthalten. Es werden nur Secret-Namen, Env-Key-Namen und
|
||||
| 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 bleibt bewusst LAN-direkt ohne Traefik/2FA (Operator-Entscheidung 2026-05-25) |
|
||||
| `adguard` | DNS-Server / LAN DNS | `host-services/Adguard/docker-compose.yml` | LAN-Port `53`, Admin `100.80.98.33:8082` | `dns_net`, `frontend_net`, Unbound | `/mnt/user/appdata/adguard/conf`, `/mnt/user/appdata/adguard/work` | Tier 1, config relevant | nein | Direkter DNS-Port 53 bleibt; Admin-Port ist bewusst ohne Traefik/2FA, aber auf Tailscale-IP begrenzt (Operator-Entscheidung 2026-05-26) |
|
||||
| `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`, `NET_ADMIN`, `NET_RAW` und `/dev/net/tun` sind dokumentierte VPN-Ausnahmen |
|
||||
| `gitea` | Git-Server / origin fuer GitOps | `core/gitea/docker-compose.yml` | `https://git.kaleschke.info`, SSH `222` | Traefik, `frontend_net`, externe DNS-Resolver fuer GitHub-Push-Mirror | `/mnt/user/services/gitea/data` | Tier 1, `gitea.sqlite.dump` + Share; privater GitHub-Push-Mirror fuer Repo-Bootstrap | ja | SSH-Port 222 direkte Host-Port-Ausnahme; Push-Mirror nach `michaelkaleschke-spec/homelab-infra` reduziert das DR-Bootstrap-Risiko |
|
||||
|
||||
@@ -318,6 +318,9 @@ Nach jeder erfolgreichen Migration oder relevanten Aenderung muessen diese Datei
|
||||
- `docs/MIGRATION_LOG.md`
|
||||
- `docs/SECRETS_MAP.md`
|
||||
- `docs/ROLLBACK.md`
|
||||
- `docs/SERVICES_RECOVERY.md` falls `/mnt/user/services`, Gitea, Komodo oder Host-Automation betroffen sind
|
||||
- `docs/HARDWARE_INVENTORY.md` und `docs/CAPACITY_AND_LIFECYCLE.md` falls Hardware, Disks, Cache, RAM oder USV betroffen sind
|
||||
- `docs/NETWORK_INVENTORY.md` und `docs/EXTERNAL_DEPENDENCIES.md` falls Router, DNS, Tailscale, Portfreigaben oder Provider betroffen sind
|
||||
- `HOMELAB_ARCHITECTURE_MASTER_V2.md` falls Architektur betroffen ist
|
||||
- `docs/GITOPS_DRIFT_RUNBOOK.md` falls GitOps-/Komodo-/Runtime-Drift betroffen ist
|
||||
|
||||
|
||||
@@ -13,7 +13,7 @@ services:
|
||||
ports:
|
||||
- "53:53/tcp"
|
||||
- "53:53/udp"
|
||||
- "8082:80"
|
||||
- "100.80.98.33:8082:80"
|
||||
security_opt:
|
||||
- no-new-privileges:true
|
||||
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
"adguard": [
|
||||
"53:53/tcp",
|
||||
"53:53/udp",
|
||||
"8082:80"
|
||||
"100.80.98.33:8082:80"
|
||||
],
|
||||
"gitea": [
|
||||
"222:22"
|
||||
|
||||
@@ -1,26 +1,30 @@
|
||||
# Policy Check Report
|
||||
|
||||
## Summary
|
||||
- Compose files checked: 29
|
||||
- Compose files checked: 31
|
||||
- Critical findings: 0
|
||||
- Warnings: 4
|
||||
- Info findings: 9
|
||||
- Warnings: 7
|
||||
- Info findings: 10
|
||||
|
||||
## Critical
|
||||
- none
|
||||
|
||||
## Warnings
|
||||
- [SEC001] infra\ddns-updater\docker-compose.yml :: ddns-updater: Missing security_opt no-new-privileges:true.
|
||||
- [HOSTNET002] host-services\plex\docker-compose.yml :: plex: network_mode: host is enabled.
|
||||
- [IMAGE001] infra\ddns-updater\docker-compose.yml :: ddns-updater: Image uses a latest tag. Prefer a concrete version tag, even when a digest is present.
|
||||
- [USER001] monitoring\docker-compose.yml :: influxdb3-core: Runs as user 0. Documented exception, keep visible for hardening.
|
||||
- [IMAGE001] ops\glances\docker-compose.yml :: glances: Image uses a latest tag. Prefer a concrete version tag, even when a digest is present.
|
||||
- [USER001] ops\grafana-influxdb\docker-compose.yml :: grafana: Runs as user 0. Documented exception, keep visible for hardening.
|
||||
- [USER001] ops\grafana-influxdb\docker-compose.yml :: influxdb3-core: Runs as user 0. Documented exception, keep visible for hardening.
|
||||
- [SEC001] ops\scrutiny\docker-compose.yml :: scrutiny: Missing security_opt no-new-privileges:true.
|
||||
- [IMAGE001] ops\scrutiny\docker-compose.yml :: scrutiny: Image uses a latest tag. Prefer a concrete version tag, even when a digest is present.
|
||||
|
||||
## Info
|
||||
- [PORT001] core\gitea\docker-compose.yml :: gitea: Allowed host port mapping: 222:22
|
||||
- [PORT001] host-services\Adguard\docker-compose.yml :: adguard: Allowed host port mapping: 53:53/tcp
|
||||
- [PORT001] host-services\Adguard\docker-compose.yml :: adguard: Allowed host port mapping: 53:53/udp
|
||||
- [PORT001] host-services\Adguard\docker-compose.yml :: adguard: Allowed host port mapping: 8082:80
|
||||
- [PORT001] host-services\Adguard\docker-compose.yml :: adguard: Allowed host port mapping: 100.80.98.33:8082:80
|
||||
- [HOSTNET001] host-services\tailscale\docker-compose.yml :: tailscale: network_mode: host is a documented exception.
|
||||
- [PORT001] monitoring\docker-compose.yml :: influxdb3-core: Allowed host port mapping: ${INFLUXDB_BIND_IP:-127.0.0.1}:8181:8181
|
||||
- [PORT001] ops\grafana-influxdb\docker-compose.yml :: influxdb3-core: Allowed host port mapping: ${INFLUXDB_BIND_IP:-127.0.0.1}:8181:8181
|
||||
- [PRIV001] ops\scrutiny\docker-compose.yml :: scrutiny: Privileged mode is a documented exception.
|
||||
- [PORT001] traefik\docker-compose.yml :: traefik: Allowed host port mapping: 80:80
|
||||
|
||||
Reference in New Issue
Block a user