feat: add smart home runtime foundation
This commit is contained in:
@@ -11,6 +11,45 @@ in `HOMELAB_ARCHITECTURE_MASTER_V2.md` §13, `docs/MASTER_TODO.md` (Geparkt),
|
||||
|
||||
---
|
||||
|
||||
## 2026-06-12 - Home Assistant als Container im GitOps-Stack
|
||||
|
||||
**Entscheidung:** Home Assistant laeuft neu als `homeassistant` Container im
|
||||
Stack `smart-home/`, nicht als HAOS-VM und nicht als Supervised-Installation.
|
||||
Mosquitto laeuft als eigener Container im selben Stack; Zigbee2MQTT und ESPHome
|
||||
werden spaeter ebenfalls als eigenstaendige Container ergaenzt. HA haengt in
|
||||
`frontend_net` fuer Traefik und in `smarthome_net` fuer MQTT/Zigbee2MQTT/ESPHome.
|
||||
Das Fachrepo `smart-home-kalli` liefert versionierte HA-YAML-Dateien read-only;
|
||||
`.storage`, `secrets.yaml` und Integrations-State bleiben in
|
||||
`/mnt/user/appdata/homeassistant`.
|
||||
|
||||
**Kontext:** Das fruehere HAOS-VM-Setup ging bei einem Crash ohne brauchbares
|
||||
Backup verloren. Das Homelab betreibt produktive Dienste inzwischen ueber
|
||||
Gitea, Komodo, Compose, Renovate und Borg. HA Container passt in dieses
|
||||
Betriebsmodell und vermeidet eine zweite Update-/Backup-Welt. Supervised ist
|
||||
kein Zielpfad mehr; HAOS bleibt die Alternative, falls Add-on-Komfort,
|
||||
Matter/Thread/HomeKit-Discovery oder Host-nahe HA-Funktionen wichtiger werden
|
||||
als GitOps-Konformitaet.
|
||||
|
||||
**Review-Trigger:** Viele mDNS-/SSDP-abhaengige lokale Integrationen
|
||||
(HomeKit, Cast, Matter/Thread), Bedarf an HA-Add-ons als Betriebsstandard,
|
||||
oder wiederholte Probleme durch Bridge-Netzwerkbetrieb.
|
||||
|
||||
## 2026-06-12 - Ecowitt-Ingress bleibt bewusste Phase-2-Entscheidung
|
||||
|
||||
**Entscheidung:** In Phase 1 wird kein Host-Port `8123` fuer Home Assistant
|
||||
veroeffentlicht. Ecowitt wird spaeter entweder ueber eine gezielte
|
||||
Traefik-HTTP-Ausnahme fuer den Webhook-Pfad angebunden oder, falls der globale
|
||||
HTTP-zu-HTTPS-EntryPoint-Redirect nicht sauber selektiv abloesbar ist, ueber
|
||||
einen dokumentierten LAN-only Host-Port `8123`.
|
||||
|
||||
**Kontext:** Ecowitt kann nur HTTP und kein HTTPS. Traefik hat aktuell einen
|
||||
globalen `web` -> `websecure` Redirect auf EntryPoint-Ebene. Ein normaler
|
||||
HTTP-Router kann diese Regel voraussichtlich nicht umgehen, ohne Traefik selbst
|
||||
umzubauen. Deshalb wird die Entscheidung nicht vorgezogen.
|
||||
|
||||
**Review-Trigger:** Start der Ecowitt-/InfluxDB-Phase oder Umbau der Traefik
|
||||
HTTP-Redirect-Architektur.
|
||||
|
||||
## 2026-06-11 — Host-DNS-Fallback aktiv (AdGuard-SPOF entschaerft)
|
||||
|
||||
**Entscheidung:** Unraid-Host nutzt `eth0` DNS server 1 = `192.168.178.58` (AdGuard) und **DNS server 2 = `192.168.178.1`** (FRITZ!Box) als Failover.
|
||||
|
||||
@@ -60,6 +60,9 @@ Sie ist die fachliche Ergaenzung zu `docs/DISASTER_RECOVERY.md`.
|
||||
| Glance | Git / Borg-Repo | Repo-Konfiguration unter `ops/glance/config/glance.yml`; keine kritische Datenpersistenz | keine | `GLANCE_IMMICH_API_KEY`, `GLANCE_ADGUARD_USERNAME`, `GLANCE_ADGUARD_PASSWORD`, `GLANCE_SPEEDTEST_API_KEY` | Traefik, Authelia, optional interne API-Ziele | Dashboard startet, Widgets laden, Docker-Status laeuft nur ueber `glance-docker-socket-proxy` |
|
||||
| ntfy | Borg / Share | `/mnt/user/appdata/ntfy` | keine | keine besonderen Secret-Dateien dokumentiert | Traefik | UI und Push-Endpunkt erreichbar |
|
||||
| Paperless-GPT | Borg / Share | `/mnt/user/appdata/paperless-gpt` | keine eigene DB | `PAPERLESS_API_TOKEN`, `OPENAI_API_KEY` | Traefik, Paperless, OpenAI API | UI startet, Konfiguration vorhanden; LLM-Provider zeigt `openai` / `gpt-5.4-mini` |
|
||||
| Home Assistant | Borg + HA-native Backups + Fachrepo | `/mnt/user/appdata/homeassistant` inkl. `.storage`, `secrets.yaml`, `trusted_proxies.yaml`; Fach-YAML aus `/mnt/user/services/smart-home-kalli/home-assistant` | HA-native Backup-Artefakte unter `/mnt/user/appdata/homeassistant/backups` falls vorhanden; keine externe DB in Phase 1 | HA-Secrets in `secrets.yaml`, Integrations-Tokens in `.storage`, MQTT-Credentials, spaeter InfluxDB-Token | Traefik, `frontend_net`, `smarthome_net`, Mosquitto, Fachrepo-Clone | `https://home.kaleschke.info` zeigt Login, MQTT-Integration verbindet sich, `backup.create` funktioniert, Energy-Dashboard-Konfiguration bleibt erhalten |
|
||||
| Smart-Home MQTT / Mosquitto | Borg / Share | `/mnt/user/appdata/mosquitto/config`, `/mnt/user/appdata/mosquitto/data`, `/mnt/user/appdata/mosquitto/log` | Mosquitto persistiert retained messages/subscriptions dateibasiert | `passwordfile`, `aclfile`, spaeter per-Device-User | `smarthome_net`, Home Assistant, spaeter ESPHome/Zigbee2MQTT | Container startet, HA kann sich authentifiziert verbinden, retained Testtopic bleibt nach Restart erhalten |
|
||||
| Smart-Home Fachrepo | Gitea + Borg-Repo-Clone | `/mnt/user/services/smart-home-kalli` | keine | keine echten Secrets im Repo; `secrets-template/` nur Beispiele | Gitea, Home Assistant Mounts | `git status` sauber, HA liest `configuration.yaml` und `packages/` aus dem Clone |
|
||||
|
||||
---
|
||||
|
||||
@@ -77,6 +80,8 @@ Sie ist die fachliche Ergaenzung zu `docs/DISASTER_RECOVERY.md`.
|
||||
| InfluxDB 3 Core | historischer Altstand / Datenuebernahme | `/mnt/user/appdata/influxdb3/data`, `/mnt/user/appdata/influxdb3/plugins` | dateibasierter Object Store | `influxdb3_admin_token.json` | `monitoring-influxdb3-core` | Datenpfad wird vom Monitoring-Zielstack weitergenutzt und darf nicht blind geloescht werden |
|
||||
| Loki / Alloy | historischer Altstand | `/mnt/user/appdata/loki/config`, `/mnt/user/appdata/loki/data`, `/mnt/user/appdata/alloy/config` | keine primaere DB; Loki-Dateispeicher war transient | keine zusaetzlichen Secrets | nicht aktiv | Compose-Pfad aus aktivem Repo entfernt; aktuelle Logsammlung laeuft ueber `monitoring-loki`/`monitoring-promtail` |
|
||||
| Monitoring Stack | Rebuild + named volumes + InfluxDB-Appdata | `prometheus_data`, `loki_data`, `promtail_positions`, `grafana_data`; InfluxDB unter `/mnt/user/appdata/influxdb3/data` und `/mnt/user/appdata/influxdb3/plugins`; Provisioning aus `monitoring/grafana/provisioning` | Prometheus-TSDB, Loki-Dateispeicher und InfluxDB-Dateistore; Diagnose-/Langzeitdaten, keine Tier-1-Restore-Quelle | `monitoring_grafana_admin_password.txt`, `monitoring_grafana_influxdb_token.txt`, `influxdb3_admin_token.json` | `monitoring_net`, `monitoring_influx_lan`, `frontend_net`, Traefik, Authelia, Docker socket read-only fuer Promtail, Host-Mounts fuer node-exporter/cAdvisor | `https://monitoring.kaleschke.info` leitet zu Authelia; Prometheus Targets sind up; Grafana-Datasources `Prometheus`, `Loki` und `InfluxDB 3 Core` funktionieren |
|
||||
| Zigbee2MQTT (geplant) | Borg + Fachrepo | `/mnt/user/appdata/zigbee2mqtt` inkl. `configuration.yaml`, `database.db`, `coordinator_backup.json`, `state.json`; Fach-Doku im Repo `smart-home-kalli` | keine externe DB | `network_key`, MQTT-Credentials, LAN-Koordinator-IP/Firmwarestand | Mosquitto, LAN-PoE-Koordinator, `smarthome_net` | Z2M startet, Coordinator verbindet sich, geraete bleiben gepairt, Testgeraet sendet MQTT-State |
|
||||
| ESPHome (geplant) | Fachrepo + Borg fuer Build-/Runtime-State | `/mnt/user/appdata/esphome` falls Dashboard/Build-Cache genutzt wird; YAML unter `/mnt/user/services/smart-home-kalli/esphome` | keine | ESPHome-Secrets ausserhalb Git, API-/OTA-Keys | WLAN/LAN, Mosquitto falls MQTT genutzt wird | Dashboard startet, ein Testgeraet kompiliert/validiert, OTA/API-Verbindung funktioniert |
|
||||
| Hermes Agent | VM-seitig offen | `/mnt/user/appdata/hermes-agent/data`, `/mnt/user/appdata/hermes-agent/ssh` | keine eigene DB | Host-`.env` fuer Provider-/API-/Home-Assistant-Tokens, `hermes_runner_id_ed25519`, `HERMES_DASHBOARD_HOST` | separate Hermes-VM/Runner, Traefik, Authelia, `hermes_net` | NAS-Stack nicht starten, solange Runner-VM und echte `.env` fehlen |
|
||||
| ddns-updater | Rebuildbar | geringe Persistenzrelevanz | keine | Provider-Zugang ueber Stack ENV | Internetzugang | Update-Job laeuft |
|
||||
|
||||
@@ -180,4 +185,4 @@ Verbleibende offene Restore-Pfade ohne vollstaendigen Test:
|
||||
Die Ablaeufe je Dienst liegen als Runbooks und automatisierte Skripte unter
|
||||
`ops/restore-tests/` (Einstieg: `ops/restore-tests/README.md`). Fuer die noch
|
||||
offenen Pfade: `ops/restore-tests/unraid-flash-runbook.md` und
|
||||
`ops/restore-tests/tailscale-runbook.md`.
|
||||
`ops/restore-tests/tailscale-runbook.md`.
|
||||
|
||||
@@ -75,11 +75,18 @@ Secret-Werte sind nicht enthalten. Es werden nur Secret-Namen, Env-Key-Namen und
|
||||
| `monitoring-promtail` | Docker-Log-Collector fuer Monitoring-Loki | `monitoring/docker-compose.yml`, `monitoring/promtail/promtail-config.yml` | intern | Docker socket read-only, Docker json-file Logs, Loki | named volume `promtail_positions` | rebuildbar | nein | Dokumentierte Host-Observability-Ausnahme: `/var/run/docker.sock:/var/run/docker.sock:ro` und `/var/lib/docker/containers:ro`; keine Appdaten, nur Log-Discovery |
|
||||
| `monitoring-node-exporter` | Host-Metriken fuer Prometheus | `monitoring/docker-compose.yml` | intern `:9100` | Host `/proc`, `/sys`, `/` read-only, Prometheus | kein kritischer Zustand | rebuildbar | nein | Host-Observability-Ausnahme mit read-only Rootfs/Proc/Sys-Mounts |
|
||||
| `monitoring-cadvisor` | Container-Metriken fuer Prometheus | `monitoring/docker-compose.yml` | intern `:8080` | Docker/Host read-only Mounts, Prometheus | kein kritischer Zustand | rebuildbar | nein | Host-Observability-Ausnahme fuer Container-Metriken; keine direkten Ports |
|
||||
| `monitoring-influxdb3-core` | InfluxDB 3 Core fuer Home-Assistant-/Ecowitt-Langzeitdaten | `monitoring/docker-compose.yml` | Host-Port `8181` je `INFLUXDB_BIND_IP`, keine Public URL | Monitoring-Grafana, Home Assistant Writer | `/mnt/user/appdata/influxdb3/data`, `/mnt/user/appdata/influxdb3/plugins` | Tier 3 | nein | 2026-05-31 effektiv auf `127.0.0.1:8181` gebunden, also nicht LAN-exponiert; `user: "0"` ist fuer den lokalen Object-Store-Pfad dokumentiert; uebernimmt den bisherigen InfluxDB-Daten-/Token-Katalog; `401 Unauthorized` beim Curl ohne Token ist erwarteter Reachability-Test |
|
||||
| `monitoring-influxdb3-core` | InfluxDB 3 Core fuer Home-Assistant-/Ecowitt-Langzeitdaten | `monitoring/docker-compose.yml` | Host-Port `8181` je `INFLUXDB_BIND_IP`, keine Public URL | Monitoring-Grafana, Home Assistant Writer | `/mnt/user/appdata/influxdb3/data`, `/mnt/user/appdata/influxdb3/plugins` | Tier 3 | nein | 2026-05-31 effektiv auf `127.0.0.1:8181` gebunden, also nicht LAN-exponiert; vor dem HA-Writer muss entschieden werden, ob `INFLUXDB_BIND_IP` auf eine LAN-IP geht oder HA gezielt ein gemeinsames internes Netz mit InfluxDB bekommt. `user: "0"` ist fuer den lokalen Object-Store-Pfad dokumentiert; `401 Unauthorized` beim Curl ohne Token ist erwarteter Reachability-Test |
|
||||
| `hermes-gateway` | Hermes Agent Gateway/API intern | `ops/hermes-agent/docker-compose.yml` | intern `8642` auf `hermes_net` | SSH Runner (VM 192.168.178.143), LLM Provider, optional Home Assistant | `/mnt/user/appdata/hermes-agent/data`, SSH key path | Tier 3, Borg/Share | nein | NAS-Stack bleibt deaktiviert, solange die separate Hermes-VM/Runner-Seite nicht wiederhergestellt ist; kein Docker-Socket |
|
||||
| `hermes-dashboard` | Hermes Dashboard | `ops/hermes-agent/docker-compose.yml` | `https://hermes.kaleschke.info` via `${HERMES_DASHBOARD_HOST}` | `hermes-gateway`, Traefik + Authelia | shared read-only data mount | Tier 3, Borg/Share | ja + Authelia | Compose-Profil `dashboard`; aktuell VM-seitig offen, nicht Teil des NAS-Finalstarts |
|
||||
| `n8n` | Workflow-Automation; aktuell genutzt fuer Mail->LLM->Gitea-Issue (Inbox `Micha/mails`) | `apps/n8n/docker-compose.yml`, `apps/n8n/workflows/*.json` | `https://n8n.kaleschke.info` | Traefik (ohne pauschale Authelia, analog Komodo/Nextcloud), GMX IMAP, OpenAI API, Gitea API | `/mnt/user/appdata/n8n/data` (SQLite, Credentials, Workflows) | Tier 2, Borg + `n8n-data` (Credentials sind nur mit `N8N_ENCRYPTION_KEY` entschluesselbar) | ja, native Auth | Wegen Webhook-Endpunkten (`/webhook/*`) bewusst ohne `authelia@file`; eigene Login-/Owner-Auth bleibt Pflicht; `N8N_ENCRYPTION_KEY` ist Stack-ENV-Pflichtsecret, Verlust macht Credentials unbrauchbar. |
|
||||
|
||||
## Smart Home
|
||||
|
||||
| Service | Zweck | Autoritativer Pfad | URL / Zugang | Abhaengigkeiten | Datenpfade | Backup / Restore | Traefik | Besonderheiten / TODOs |
|
||||
|---|---|---|---|---|---|---|---|---|
|
||||
| `homeassistant` | Zentrale Smart-Home-Steuerung, Energy Dashboard, Integrations-Hub | Runtime: `smart-home/docker-compose.yml`; Fachkonfiguration: Repo `smart-home-kalli` | `https://home.kaleschke.info`; kein direkter Host-Port in Phase 1 | Traefik, `frontend_net`, `smarthome_net`, `smarthome-mosquitto`, Fachrepo unter `/mnt/user/services/smart-home-kalli` | `/mnt/user/appdata/homeassistant` inkl. `.storage`, `secrets.yaml`, `trusted_proxies.yaml`; YAML-Fachdateien read-only aus `/mnt/user/services/smart-home-kalli/home-assistant` | Tier 2, Borg + HA-native Backups; Restore-Probe Pflicht vor produktiven Energie-Automationen | ja, native HA-Auth | HA Container statt HAOS-VM; keine Add-ons, keine Supervised-Installation. `configuration.yaml` kommt aus dem Fachrepo, `.storage` wird nicht versioniert. `http.use_x_forwarded_for` und `trusted_proxies` muessen zur Traefik-Route passen. Ecowitt-HTTP bleibt Phase-2-Entscheidung wegen globalem Traefik-Redirect. |
|
||||
| `smarthome-mosquitto` | MQTT-Broker fuer HA, spaeter ESPHome und Zigbee2MQTT | `smart-home/docker-compose.yml`, `smart-home/mosquitto/config/mosquitto.conf` | intern `smarthome_net:1883`; kein LAN-Port in Phase 1 | `smarthome_net`, Passwort-/ACL-Dateien in Appdata | `/mnt/user/appdata/mosquitto/config`, `/mnt/user/appdata/mosquitto/data`, `/mnt/user/appdata/mosquitto/log` | Tier 2, Borg; Passwortdatei, ACLs und persistente Broker-Daten relevant | nein | LAN-Port `1883` erst in ESPHome-Phase mit ACLs und per-Device-Usern. |
|
||||
|
||||
## Host Operations
|
||||
|
||||
| Service | Zweck | Autoritativer Pfad | URL / Zugang | Abhaengigkeiten | Datenpfade | Backup / Restore | Traefik | Besonderheiten / TODOs |
|
||||
|
||||
@@ -0,0 +1,85 @@
|
||||
# Smart-Home Bootstrap
|
||||
|
||||
Ziel: Den Stack `smart-home/` auf Kallilabcore initial startklar machen, ohne
|
||||
Secrets oder UI-State ins Git zu schreiben.
|
||||
|
||||
## 1. Fachrepo auf dem Host bereitstellen
|
||||
|
||||
```sh
|
||||
cd /mnt/user/services
|
||||
git clone https://git.kaleschke.info/Micha/smart-home-kalli.git smart-home-kalli
|
||||
cd smart-home-kalli
|
||||
git checkout main
|
||||
```
|
||||
|
||||
Der Home-Assistant-Container mountet daraus einzelne YAML-Dateien read-only nach
|
||||
`/config`.
|
||||
|
||||
## 2. Home-Assistant-Appdata vorbereiten
|
||||
|
||||
```sh
|
||||
mkdir -p /mnt/user/appdata/homeassistant
|
||||
cp /mnt/user/services/smart-home-kalli/secrets-template/secrets.yaml.example \
|
||||
/mnt/user/appdata/homeassistant/secrets.yaml
|
||||
cp /mnt/user/services/smart-home-kalli/secrets-template/trusted_proxies.yaml.example \
|
||||
/mnt/user/appdata/homeassistant/trusted_proxies.yaml
|
||||
```
|
||||
|
||||
Danach `trusted_proxies.yaml` auf das echte Traefik-/`frontend_net`-Subnetz
|
||||
anpassen:
|
||||
|
||||
```sh
|
||||
docker network inspect frontend_net
|
||||
```
|
||||
|
||||
## 3. Mosquitto vorbereiten
|
||||
|
||||
```sh
|
||||
mkdir -p /mnt/user/appdata/mosquitto/config \
|
||||
/mnt/user/appdata/mosquitto/data \
|
||||
/mnt/user/appdata/mosquitto/log
|
||||
|
||||
docker run --rm -it \
|
||||
-v /mnt/user/appdata/mosquitto/config:/mosquitto/external_config \
|
||||
eclipse-mosquitto:2.0.22 \
|
||||
mosquitto_passwd -c /mosquitto/external_config/passwordfile homeassistant
|
||||
|
||||
cat > /mnt/user/appdata/mosquitto/config/aclfile <<'EOF'
|
||||
user homeassistant
|
||||
topic readwrite #
|
||||
EOF
|
||||
```
|
||||
|
||||
Das initiale Passwort anschliessend in
|
||||
`/mnt/user/appdata/homeassistant/secrets.yaml` eintragen. LAN-Port `1883` bleibt
|
||||
in Phase 1 geschlossen.
|
||||
|
||||
## 4. Stack deployen
|
||||
|
||||
Komodo-Stack:
|
||||
|
||||
- Repo: `homelab-infra`
|
||||
- Pfad: `smart-home/docker-compose.yml`
|
||||
- Branch: nach Review `master`
|
||||
|
||||
Nach dem Start pruefen:
|
||||
|
||||
```sh
|
||||
docker ps --filter name=homeassistant
|
||||
docker ps --filter name=smarthome-mosquitto
|
||||
docker logs --tail=100 homeassistant
|
||||
docker logs --tail=100 smarthome-mosquitto
|
||||
```
|
||||
|
||||
## 5. Smoke-Test
|
||||
|
||||
- `https://home.kaleschke.info` zeigt die Home-Assistant-Oberflaeche.
|
||||
- Keine Trusted-Proxy-Fehler im HA-Log.
|
||||
- MQTT-Integration verbindet sich mit Host `smarthome-mosquitto`, Port `1883`.
|
||||
- HA-native Backup-Erstellung funktioniert.
|
||||
|
||||
## 6. Abnahmebedingung
|
||||
|
||||
Vor produktiven Energie-Automationen muss ein Restore-Test fuer
|
||||
`/mnt/user/appdata/homeassistant`, `/mnt/user/appdata/mosquitto` und den Clone
|
||||
`/mnt/user/services/smart-home-kalli` dokumentiert sein.
|
||||
Reference in New Issue
Block a user