Files
homelab-infra/HOMELAB_ARCHITECTURE_MASTER_V2.md
T

473 lines
30 KiB
Markdown

# HOMELAB_ARCHITECTURE — MASTER v2
> **Single Source of Truth** für Docker-Netzwerkarchitektur, Sicherheitsregeln, Zielbild und Migration des Kallilabcore-Homelabs.
> **Arbeitsregel für KI-Assistenten:** Dieses Dokument immer zuerst lesen, bevor Fragen zu Containern, Netzwerken, Traefik, Tailscale, Migration oder Security beantwortet werden.
**Stand:** 2026-06-13 | **Aktueller Schwerpunkt:** Home Assistant Energy Dashboard: Tibber / SolarEdge
---
## Inhaltsverzeichnis
1. [Systemüberblick](#1-systemüberblick)
2. [Architektur-Prinzipien](#2-architektur-prinzipien)
3. [Finales Netzwerk-Zielbild](#3-finales-netzwerk-zielbild)
4. [Zugangsmodell: Traefik vs. Tailscale](#4-zugangsmodell-traefik-vs-tailscale)
5. [Globale Sicherheitsregeln](#5-globale-sicherheitsregeln)
6. [Einordnungsschema für neue Container](#6-einordnungsschema-für-neue-container)
7. [Container-Zielbild (vollständig)](#7-container-zielbild-vollständig)
8. [Traefik-Label-Standard](#8-traefik-label-standard)
9. [Historische Migration (abgeschlossen)](#9-historische-migration-abgeschlossen)
10. [Bekannte Ausnahmen und Begründungen](#10-bekannte-ausnahmen-und-begründungen)
11. [Projektorganisation und Arbeitsmodus](#11-projektorganisation-und-arbeitsmodus)
12. [Nutzung mit KI / Kontext-Regel](#12-nutzung-mit-ki--kontext-regel)
13. [Betriebserfahrungen und Entscheidungs-Log (ausgelagert)](#13-betriebserfahrungen-und-entscheidungs-log-ausgelagert)
---
## 1. Systemüberblick
| Eigenschaft | Wert |
|---|---|
| Host-OS | Unraid |
| Hostname | Kallilabcore |
| Reverse Proxy | Traefik v3 (Service-Routing via Docker-Labels, File-Provider fuer Middlewares, TLS und Dashboards) |
| VPN / Remote-Zugang | Tailscale (`tailscale`, host-Netz, Git-Stack) |
| DNS-Stack | AdGuard Home (`dns_net` + `frontend_net`) → Unbound (`dns_net`) |
| Basis-Domain | `kaleschke.info` |
| TLS | Let's Encrypt via Cloudflare DNS Challenge |
| Certresolver | `le` |
| Compose-Standard | Komodo (GitOps, Stack aus Gitea) |
| Legacy | Portainer CE entfernt; Komodo ist alleiniger Stack-Manager |
| Homelab-Compose-Pfad | `/mnt/user/services/homelab/` |
| Secrets-Pfad | `/mnt/user/appdata/secrets/` |
| Grundsatz | Keine neuen Dockerman-Einzelcontainer |
---
## 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 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
- `backend_net` = intern für DB/Cache/App-Kommunikation
- zusätzliche Netze nur app-intern, wenn technisch nötig (`mealie_internal`, `immich_default`, `dns_net`)
Es gibt **keine künstlichen globalen Zusatznetze** wie `admin_net` oder `media_net`. `monitoring_net` ist die dokumentierte Ausnahme fuer den zentralen Observability-Stack.
### P3 — Datenbanken gehören nie ins `frontend_net`
Postgres, Redis und ähnliche Dienste laufen ausschließlich in `backend_net` oder einem eigenen internen Compose-Netz.
### P4 — Admin-UIs sind nicht öffentlich
filebrowser, scrutiny, code-server, Traefik-Dashboard und borg-ui sind standardmaessig **Tailscale-only** oder hinter Traefik **mit zentraler Middleware** abgesichert. `Komodo` ist die dokumentierte Ausnahme und bleibt bewusst bei nativer Authentifizierung ohne pauschal vorgeschaltete ForwardAuth-Middleware.
### P5 — Compose-first
Alle produktiven Container werden als Compose verwaltet. Bestehende Dockerman-/Ad-hoc-Container werden schrittweise migriert.
### P6 — Secrets nie im Klartext
Passwörter, Tokens und API-Keys gehören in Secret-Dateien unter `/mnt/user/appdata/secrets/` oder als Komodo Stack Environment Variables mit `${VARIABLE}` in der Compose.
### P7 — `restart: unless-stopped` ist Pflichtstandard
Jeder produktive Container nutzt `restart: unless-stopped`, außer eine Ausnahme ist dokumentiert.
### P8 — Least Privilege
- `security_opt: ["no-new-privileges:true"]` standardmäßig ergänzen
- `privileged: true` nur mit dokumentierter Begründung
- Docker-Socket standardmäßig vorsichtig behandeln; **Komodo ist dokumentierte Ausnahme**
---
## 3. Finales Netzwerk-Zielbild
### 3.1 Netz-Logik
| Netzwerk | Typ | Zweck | Status |
|---|---|---|---|
| `frontend_net` | bridge, external | einziges Traefik-/Web-Netz | Standard |
| `backend_net` | bridge, `internal: true` | interne App-/DB-/Cache-Kommunikation | Standard |
| `dns_net` | bridge | Resolver-Schicht: AdGuard Home + Unbound | bleibt |
| `mealie_internal` | bridge, `internal: true` | internes Netz nur für `mealie` + `mealie-postgres` | ✅ umgesetzt |
| `immich_default` | Compose-intern, `internal: true` | internes Immich-Netz | ✅ umgesetzt |
| `nextcloud_internal` | bridge, `internal: true` | internes Netz nur fuer `nextcloud` + `nextcloud-postgres` + `nextcloud-redis` | ✅ vorbereitet |
| `monitoring_net` | Compose-intern, bridge | zentraler Observability-Stack fuer Prometheus, Loki, Grafana, Promtail, Exporter und InfluxDB | Zielzustand |
| `monitoring_influx_lan` | Compose-intern, bridge | nicht-oeffentliches Zusatznetz nur fuer Docker Host-Port-Publishing von InfluxDB 8181 | Zielzustand |
| `glance_socket_net` | Compose-intern, `internal: true` | interner Zugriff von Glance auf den Docker-Socket-Proxy | umgesetzt |
| `smarthome_net` | bridge, `internal: true` | interne Smart-Home-Kommunikation zwischen Home Assistant, Mosquitto, spaeter Zigbee2MQTT/ESPHome | vorbereitet |
| `host` | host | nur für echte Sonderfälle | begründet |
### 3.2 Finales Diagramm (vereinfacht)
```text
Internet
traefik (80/443)
└── frontend_net
├── öffentliche Apps (vaultwarden, mealie, paperless, immich, gitea, ntfy, mail-archiver, nextcloud)
├── geschützte UIs mit Middleware (glance, paperless-gpt, filebrowser, scrutiny, code-server, borg-ui, glances, speedtest, bentopdf, monitoring-grafana)
├── Admin-UI mit nativer Auth (komodo)
└── Dienste mit Internetbedarf ohne öffentliche UI (ddns-updater)
backend_net (internal: true)
├── postgresql17
├── Redis
├── mail-archiver
└── paperless-ngx
dns_net
├── AdGuard Home (+ frontend_net, feste IP 172.23.0.3)
└── unbound
App-interne Netze
├── mealie_internal (internal: true) ✅
├── immich_default (internal: true) ✅
├── nextcloud_internal (internal: true) ✅
├── monitoring_net (zentraler Observability-Stack)
├── monitoring_influx_lan (Bridge fuer LAN-Port-Publishing, keine Traefik-Route)
└── smarthome_net (HA, Mosquitto, spaeter Zigbee2MQTT/ESPHome)
Host-Sonderfälle
├── tailscale
└── Plex-Media-Server
```
---
## 4. Zugangsmodell: Traefik vs. Tailscale
### 4.1 Öffentlich über Traefik
Diese Dienste sind über echte `*.kaleschke.info`-Domains erreichbar:
- `vaultwarden` — vault.kaleschke.info
- `mealie` — mealie.kaleschke.info
- `paperless-ngx` — paperless.kaleschke.info
- `ntfy` — ntfy.kaleschke.info
- `gitea` (Web) — git.kaleschke.info
- `immich_server` — immich.kaleschke.info
- `nextcloud` — cloud.kaleschke.info
- `plex` — plex.kaleschke.info (Traefik, native Plex-Auth; Plex Remote Access/Port 32400 bleibt aus)
- `homeassistant` — home.kaleschke.info (Traefik, native Home-Assistant-Auth)
### 4.2 Nicht öffentlich / nur Tailscale oder Traefik + Middleware
Diese Dienste sind **keine Public Apps**:
- `Komodo` — komodo.kaleschke.info (Traefik, aber bewusst ohne zentrale Middleware; native Auth bleibt aktiv)
- `filebrowser` — files.kaleschke.info (Middleware)
- `scrutiny` — scrutiny.kaleschke.info (Middleware)
- `code-server` — Traefik + Middleware
- `borg-ui` — borg.kaleschke.info (Middleware)
- `glance` — glance.kaleschke.info (Middleware)
- `paperless-gpt` — paperless-gpt.kaleschke.info (Middleware)
- `mail-archiver` — mail.kaleschke.info (Middleware + App-Auth)
- `glances` — glances.kaleschke.info (Middleware)
- `speedtest-tracker` — speedtest.kaleschke.info (Middleware)
- `bentopdf` — pdf.kaleschke.info (Middleware)
- `monitoring-grafana` — monitoring.kaleschke.info (Middleware)
- `hermes-dashboard` — hermes.kaleschke.info (Middleware)
- `super-productivity` — sp.kaleschke.info (Middleware)
- `n8n` — n8n.kaleschke.info (Traefik ohne pauschale Middleware, native Auth + Webhook-Ausnahme analog Komodo)
- `Traefik-Dashboard`
- `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:
- Traefik sie routet
- zentrale Middleware aktiv ist
- keine direkten Host-Ports bestehen
- Zugriff durch Tailscale bzw. Auth begrenzt ist
`Komodo` ist hiervon die dokumentierte Ausnahme: Traefik ja, aber keine pauschale ForwardAuth-Middleware, damit Webhooks, API und Periphery-Kommunikation nicht versehentlich beeintraechtigt werden.
---
## 5. Globale Sicherheitsregeln
1. Keine produktiven Dienste im Docker-Default-`bridge`
2. Keine direkten Host-Ports für Web-UIs außer dokumentierte Ausnahmen
3. `restart: unless-stopped` als Standard
4. Secrets als Datei / `_FILE` oder Komodo Stack Environment Variables mit `${VAR}`
5. `no-new-privileges:true` ergänzen, wo praktikabel
6. `traefik.docker.network=frontend_net` immer explizit setzen
7. Admin- und interne Web-Dienste standardmaessig mit zentraler Middleware absichern (`authelia@file,secure-headers@file` oder dokumentierte Ausnahme)
8. Placeholder-Domains (`yourdomain.tld`) sind verboten
9. `privileged: true` nur mit Begründung
10. Volume-Mounts so klein und so read-only wie möglich
11. Neue Dienste nur via Compose / Git-Stack
12. Änderungen immer gegen dieses Dokument prüfen
---
## 6. Einordnungsschema für neue Container
### Schritt 1 — Hat der Dienst eine Web-UI?
- **Ja** → `frontend_net`
- **Nein** → weiter zu Schritt 2
### Schritt 2 — Braucht der Dienst externe Internetverbindungen?
- **Ja** → `frontend_net` (auch ohne Web-UI)
- **Nein** → weiter zu Schritt 3
### Schritt 3 — Braucht der Dienst eine DB / Redis / interne Backends?
- **Ja** → zusätzlich `backend_net` oder eigenes app-internes Netz
- **Nein** → nur das funktional nötige Netz
### Schritt 4 — Ist es eine Datenbank oder ein Cache?
- **Ja** → niemals `frontend_net`, nur `backend_net` oder internes Compose-Netz
### Schritt 5 — Ist es ein Admin-/Monitoring-Dienst?
- **Ja** → wenn Web-UI vorhanden trotzdem `frontend_net`, aber nur mit Middleware und ohne direkte Portfreigabe
### Schritt 6 — Braucht der Dienst Host-/Discovery-/L2-Sicht?
- **Ja** → `host` nur mit dokumentierter Begründung
### Schritt 7 — Braucht die App ein eigenes internes App-Netz?
- **Ja** → Compose-internes Netz mit `internal: true`
---
## 7. Container-Zielbild (vollständig)
Legende Status:
- `✅` = umgesetzt und in Git-Stack
- `✅ (Dockerman)` = Traefik/Netz korrekt konfiguriert, noch kein Git-Stack
- `⏳` = noch zu migrieren / zu korrigieren
- `⚠️ Legacy` = läuft, wird abgelöst
- `❌` = entfernt
### 7.1 Infrastruktur / Core
| 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 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 / Subnet-Router | **Natives Unraid-Plugin** (`tailscale.plg`, Interface `tailscale1`, State `/boot/config/plugins/tailscale/state`) — **nicht** repo-/Komodo-verwaltet | Subnet-Router fuer `192.168.178.0/24`; der redundante userspace-Docker-Stack `host-services/tailscale/` wurde am 2026-06-06 entfernt |
### 7.2 Sicherheit / Identity
| Container | Status | Soll-Netz(e) | Finaler Zugang | Finaler Sollzustand | Offene Punkte |
|---|---|---|---|---|---|
| `vaultwarden` | ✅ | `frontend_net` | Traefik | kein Host-Port, `ADMIN_TOKEN_FILE` | — |
| `authelia` | ✅ | `frontend_net`, `backend_net` | Traefik via `auth.kaleschke.info` | aktiver ForwardAuth-Provider, Secrets via `_FILE`, PostgreSQL Storage; bewusst ohne Redis-Session-Backend | — |
### 7.3 Datenbanken / Caches
| Container | Status | Soll-Netz(e) | Finaler Zugang | Finaler Sollzustand | Offene Punkte |
|---|---|---|---|---|---|
| `postgresql17` | ✅ | `backend_net` | intern | kein Host-Port, `POSTGRES_PASSWORD_FILE` | — |
| `Redis` | ✅ | `backend_net` | intern | intern-only Cache | optional named volume |
| `mealie-postgres` | ✅ | `mealie_internal` | intern | isoliert, nie `frontend_net` | — |
| `immich_postgres` | ✅ | `immich_default` | intern | intern-only | — |
| `immich_redis` | ⏳ | `immich_default` | intern | intern-only | anonymes Volume → named volume |
| `nextcloud-postgres` | ✅ | `nextcloud_internal` | intern | app-eigene Nextcloud-Datenbank mit `_FILE`-Secret | — |
| `nextcloud-redis` | ✅ | `nextcloud_internal` | intern | app-eigener Cache fuer File Locking / Sessions | — |
| `smarthome-mosquitto` | ✅ | `smarthome_net` | intern `1883`, kein Host-Port in Phase 1 | MQTT-Datenbus fuer Home Assistant, spaeter ESPHome und Zigbee2MQTT; Passwortdatei und ACLs in `/mnt/user/appdata/mosquitto/config`; MQTT-Smoke und HA-MQTT-Integration am 2026-06-13 erfolgreich | LAN-Port erst in ESPHome-Phase mit ACLs/per-Device-Usern |
### 7.4 Produktive Apps
| Container | Status | Soll-Netz(e) | Finaler Zugang | Finaler Sollzustand | Offene Punkte |
|---|---|---|---|---|---|
| `paperless-ngx` | ✅ | `frontend_net`, `backend_net` | Traefik | aktiv via `paperless.kaleschke.info` | — |
| `mail-archiver` | ✅ | `frontend_net`, `backend_net` | Traefik + Middleware | aktiv via `mail.kaleschke.info`; IMAP-Abruf + DB-Zugang; App-eigene Auth bleibt zusaetzliche Schutzschicht | — |
| `mealie` | ✅ | `frontend_net`, `mealie_internal` | Traefik | sauber getrennte App/DB-Struktur | — |
| `ntfy` | ✅ | `frontend_net` | Traefik | aktiv via `ntfy.kaleschke.info`, Git-Stack | — |
| `gitea` | ✅ | `frontend_net` | Traefik + SSH-Port 222 | Web via Traefik, SSH direkt gebunden | — |
| `immich_server` | ✅ | `immich_default`, `frontend_net` | Traefik | aktiv via `immich.kaleschke.info` | — |
| `immich_machine_learning` | ✅ | `immich_default` | intern | bleibt intern | — |
| `nextcloud` | ✅ | `frontend_net`, `nextcloud_internal` | Traefik | aktiv via `cloud.kaleschke.info`, nativer Nextcloud-Login, WebDAV/CardDAV faehig | CalDAV/CardDAV-Redirect via Traefik-Labels |
| `homeassistant` | ✅ | `frontend_net`, `smarthome_net` | Traefik via `home.kaleschke.info`, native HA-Auth | Home Assistant Container im GitOps-Stack `smart-home/`; kein HAOS, kein Supervised; Fach-YAML kommt aus `smart-home-kalli`, `.storage` bleibt in `/mnt/user/appdata/homeassistant`; Komodo-Stack und Gitea-Webhook aktiv; HA-native Backup-Erzeugung, Restore-Probe und HA-MQTT-Integration am 2026-06-13 erfolgreich | Tibber, SolarEdge Cloud-vs-Modbus-Entscheidung, Energy Dashboard |
| `plex` | ✅ | `host` | Traefik via `plex.kaleschke.info` + Plex native Auth; LAN direkt `:32400` | Compose-Stack unter `host-services/plex/`; Host-Netz bleibt fuer Discovery / Plex GDM dokumentierte Ausnahme; Traefik routet per File-Provider-Ausnahme auf `http://192.168.178.58:32400`, weil Docker-Labels Host-Netz-Container aus Traefik heraus auf `127.0.0.1` routen wuerden; kein direkter WAN-Port 32400 und Plex Remote Access bleibt aus; Server geclaimt von `Xeridos`; Smart-TVs (Schlafzimmer, Wohnzimmer) ueber WLAN-LAN per mDNS | — |
| `super-productivity` | ✅ vorbereitet | `frontend_net` | Traefik + Middleware | Persoenliche Task-PWA des Operators; Issues kommen aus Gitea `Micha/mails` via n8n-Mail-Workflow | Deploy + Webhook + DNS-Eintrag offen |
| `n8n` | ✅ vorbereitet | `frontend_net` | Traefik, native Auth (keine pauschale Authelia) | Workflow-Automation; erster Workflow: GMX-Mail -> OpenAI-Extraktion -> Gitea-Issue in `Micha/mails`; `N8N_ENCRYPTION_KEY` ist Stack-ENV-Pflichtsecret | Deploy + Webhook + Owner-Setup offen |
### 7.5 Admin / Operations
| Container | Status | Soll-Netz(e) | Finaler Zugang | Finaler Sollzustand | Offene Punkte |
|---|---|---|---|---|---|
| `komodo` | ✅ | `frontend_net` | Traefik, native Auth | primaerer GitOps-Stack-Manager | bewusste Ausnahme: keine pauschale ForwardAuth-Middleware vor UI/API/Webhooks/Periphery |
| `code-server` | ✅ | `frontend_net` | Traefik + Middleware | `PASSWORD_FILE` aktiv | — |
| `PortainerCE` | ❌ entfernt | - | - | 2026-03-29 abgeschaltet | historisch; nicht mehr deployen |
| `filebrowser` | ✅ | `frontend_net` | Traefik + Middleware | aktiv via `files.kaleschke.info` | Appdata-Breitmount entfernt; nur Documents/Photos/Projekte plus eigener App-State |
| `borg-ui` | ✅ | `frontend_net` | Traefik + Middleware | produktiver Borg-/Restore-Dienst; `/local/secrets` ist bewusst Teil des Restore-Scopes | BorgBase-Repo und Key laufend pflegen |
| `paperless-gpt` | ✅ | `frontend_net` | Traefik + Middleware | aktiv via `paperless-gpt.kaleschke.info` | — |
| `bentopdf` | ✅ vorbereitet | `frontend_net` | Traefik + Middleware | PDF-Tooling via `pdf.kaleschke.info`; browserseitige Verarbeitung, COOP/COEP fuer Office-Konvertierung | Deploy und fachliche Abnahme offen |
| `hermes-dashboard` | ✅ | `frontend_net`, `hermes_net` | Traefik + Middleware | aktiv via `hermes.kaleschke.info`; Dashboard bindet intern mit `--insecure` auf `0.0.0.0`, externe Absicherung ueber Authelia | — |
### 7.6 Monitoring / Status
| Container | Status | Soll-Netz(e) | Finaler Zugang | Finaler Sollzustand | Offene Punkte |
|---|---|---|---|---|---|
| `glance` | ✅ | `frontend_net`, `glance_socket_net` | Traefik + Middleware | einziges Homelab-Dashboard via `glance.kaleschke.info`; Docker-Status nur ueber internen Socket-Proxy | — |
| `glances` | ✅ | `frontend_net` | Traefik + Middleware | aktiv via `glances.kaleschke.info` | — |
| `scrutiny` | ✅ | `frontend_net` | Traefik + Middleware | aktiv via `scrutiny.kaleschke.info`, Git-Stack | `privileged` später prüfen |
| `speedtest-tracker` | ✅ | `frontend_net` | Traefik + Middleware | aktiv via `speedtest.kaleschke.info` | — |
| `monitoring-grafana` | ✅ | `frontend_net`, `monitoring_net` | Traefik + Middleware | zentrale UI via `monitoring.kaleschke.info`; Datasources fuer Prometheus, Loki und InfluxDB | — |
| `monitoring-influxdb3-core` | ✅ | `monitoring_net`, `monitoring_influx_lan` + LAN-Bind | LAN-Port nur fuer interne Writer | InfluxDB 3 Core fuer Home-Assistant-/Ecowitt-Langzeitdaten; keine Traefik-/Public-Freigabe; Port 8181 nur via `INFLUXDB_BIND_IP` | HA-Write-Token und Sensor-Export finalisieren |
| `monitoring-loki` | ✅ | `monitoring_net` | intern | interner Container-Logspeicher ohne Public Route; Monitoring-Grafana greift ueber Loki-Datasource zu | Retention/Storage beobachten |
| `monitoring-promtail` | ✅ | `monitoring_net` | intern | Docker-Log-Collector mit read-only Docker-Socket-Ausnahme; schreibt nach Loki | Socket-Ausnahme regelmaessig pruefen |
| `grafana` / `influxdb3-core` / `loki` / `alloy` | entfernt | - | abgeloest | alte Docker-Runtime frei von Altcontainern; Compose-Pfade am 2026-05-26 aus aktivem Repo entfernt | Rollback nur ueber Git-Historie |
### 7.7 Noch offene Sonderfälle
| Container | Status | Ziel |
|---|---|---|
| — | — | Plex ist nicht mehr direkt offen: der Dienst ist als Repo-Compose-Stack unter `host-services/plex/` dokumentiert; `host`-Netz bleibt als Discovery-Ausnahme. Externer Zugriff laeuft ausschliesslich ueber Traefik/443 auf `plex.kaleschke.info`; keine direkte 32400-WAN-Freigabe. Technisch nutzt Plex als einzige Host-Netz-Route `traefik/dynamic/plex.yml`, weil Docker-Labels fuer `network_mode: host` in Traefik auf `127.0.0.1:32400` zeigen. |
### 7.8 Entfernte Container
| Container | Entfernt am | Begründung |
|---|---|---|
| `scanopy-server` | 2026-03-26 | nicht genutzt, durch paperless-ngx ersetzt |
| `scanopy-postgres` | 2026-03-26 | zusammen mit scanopy entfernt |
| `scanopy-daemon` | 2026-03-26 | zusammen mit scanopy entfernt |
| `diun` | 2026-03-28 | Update-Monitoring via Komodo; Stack + Netz `diun_diun_default` + Repo-Eintrag entfernt |
| `binhex-official-pihole` | 2026-03-28 | ersetzt durch AdGuard Home + Unbound |
| `gotify` | 2026-03-28 | nicht mehr aktiv; Push-Notifications via ntfy abgedeckt |
| `Dozzle` | 2026-03-28 | nicht mehr aktiv |
| `dashdot` | 2026-03-28 | nicht mehr aktiv |
| `netdata` | 2026-03-28 | nicht mehr aktiv |
| `netalertx` | 2026-03-28 | nicht mehr aktiv |
| `luckyBackup` | 2026-03-28 | nicht mehr aktiv; Backup via Borg |
| `backrest` | 2026-05-15 | entfernt; Borg ist die alleinige Backup-Technologie, WD MyBookLive ist kein Backup-Ziel mehr |
| `Stash` | 2026-03-28 | nicht mehr aktiv |
| `PortainerCE` | 2026-03-29 | abgeschaltet; Komodo ist alleiniger Stack-Manager |
| `beszel` | nicht dokumentiert | bereits entfernt; nicht mehr Teil des Zielbilds |
| `beszel-agent` | nicht dokumentiert | bereits entfernt; nicht mehr Teil des Zielbilds |
| `jellyfin` | 2026-05-25 | doppelter Medienserver neben Plex; Plex bleibt einziger Medienserver |
| `homepage` | 2026-05-25 | doppeltes Dashboard neben Glance; Glance bleibt einziges Homelab-Dashboard |
| `uptime-kuma` | 2026-05-25 | durch `monitoring-blackbox-exporter`, Prometheus-Alerts und `monitoring-grafana` ersetzt |
---
## 8. Traefik-Label-Standard
Jeder Dienst mit Traefik-Routing nutzt dieses Muster:
```yaml
labels:
- traefik.enable=true
- traefik.docker.network=frontend_net
- traefik.http.routers.<name>.rule=Host(`<subdomain>.kaleschke.info`)
- traefik.http.routers.<name>.entrypoints=websecure
- traefik.http.routers.<name>.tls=true
- traefik.http.routers.<name>.tls.certresolver=le
- traefik.http.services.<name>.loadbalancer.server.port=<interner-port>
```
### Zusatz fuer Admin-Dienste (Standard)
```yaml
- traefik.http.routers.<name>.middlewares=authelia@file,secure-headers@file
```
### Regeln
- `traefik.docker.network` immer explizit auf `frontend_net`
- keine `yourdomain.tld`-Platzhalter
- certresolver immer `le`
- `tls=true` immer explizit setzen
- wenn Traefik aktiv ist, werden direkte Host-Ports entfernt
- Admin-Dienste standardmaessig nicht ohne Middleware veroeffentlichen
- Das Traefik-Dashboard nutzt ebenfalls `authelia@file`; dokumentierte Ausnahmen wie `Komodo` bleiben moeglich
- **File-Provider nur noch für:** `middlewares.yml`, `tls.yml`, `dashboards.yml` — keine Service-Routen mehr via File-Provider
- dokumentierte Ausnahmen muessen in Abschnitt 10 begruendet werden
---
## 9. Historische Migration (abgeschlossen)
Die Blockmigration aus der Portainer-/Dockerman-Phase ist abgeschlossen: Traefik laeuft labelbasiert ohne File-Provider-Service-Routen, Komodo ist alleiniger Stack-Manager, Portainer CE ist entfernt, Borg/Dumps/Restore-Tests sind produktiv. Entscheidungen und Hintergruende stehen in `docs/DECISIONS.md`; die Sprint-Historie liegt in Git.
## 10. Bekannte Ausnahmen und Begründungen
| Container | Ausnahme | Begründung |
|---|---|---|
| `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 + `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 |
| `glance-docker-socket-proxy` | Docker-Socket read-only | Glance benoetigt Containerstatus; Zugriff wird ueber einen internen Socket-Proxy auf lesende Docker-API-Endpunkte begrenzt und nicht ins `frontend_net` gelegt |
| `Komodo` | keine pauschale zentrale Middleware | Webhooks (`/listener`), API und Periphery-WebSocket (`/ws/periphery`) sollen nicht durch vorgeschaltete ForwardAuth gebrochen werden |
| `gitea` | SSH-Port 222 direkt gebunden (LAN/Tailscale) | Git-SSH-Zugang; kein HTTP-Proxy für SSH möglich. Bewusst **nicht** in FRITZ!Box-WAN freigegeben (Operator-Entscheidung 2026-05-28): Tailscale ist Operator-Pfad, GitHub-Mirror deckt DR-Bootstrap ab, SSH-Brute-Force-Vektor extern vermeiden. |
| `ddns-updater` | bleibt in `frontend_net` statt `backend_net` | braucht Cloudflare-API-Zugang; `backend_net` ist `internal: true` |
| `mail-archiver` | `frontend_net` + `backend_net` | braucht Internetzugang für IMAP-Abruf (GMX, Gmail) und DB-Zugang |
| `traefik/dynamic/*` | manueller Host-Sync trotz GitOps | File-Provider bleibt bewusst fuer `middlewares.yml`, `tls.yml` und `dashboards.yml`; Komodo deployed diese Dateien nicht automatisch |
| `nextcloud` | keine zentrale ForwardAuth-Middleware | Nextcloud bringt eigene Auth, Clients und WebDAV/CardDAV-Endpunkte mit; Traefik bleibt Reverse Proxy, Auth bleibt app-nativ |
| `monitoring-influxdb3-core` | Host-Port 8181 auf LAN-IP; `user: "0"` | Home Assistant schreibt spaeter Langzeitdaten. Nach der HA-Container-Entscheidung muss der Writer-Pfad in der Influx-Phase explizit gewaehlt werden: entweder LAN-Bind via `INFLUXDB_BIND_IP` oder gezieltes gemeinsames internes Netz. Keine Traefik-Route, Zugriff nur ueber Token; InfluxDB 3 Core benoetigt im aktuellen Container-Setup Root-Rechte fuer den lokalen Object-Store-Pfad im named volume |
| `monitoring-promtail` | Docker-Socket read-only | Docker-Log-Discovery fuer Loki; keine Schreibrechte, keine Appdaten-Persistenz ueber den Socket |
| `n8n` | keine pauschale Authelia-Middleware | Webhook-Endpunkte (`/webhook/*`, `/webhook-test/*`) muessen ohne ForwardAuth erreichbar bleiben; n8n bringt eigene Owner-/Login-Auth mit (analog Komodo/Nextcloud) |
| `plex` | Traefik ohne Authelia, File-Provider-Ausnahme trotz Host-Netz | Plex bringt native Konto-/Client-Auth mit; vorgeschaltete ForwardAuth wuerde Plex Web, Apps und Client-Flows stoeren. Docker-Labels sind fuer diesen Host-Netz-Container ungeeignet, weil Traefik sonst `127.0.0.1:32400` nutzt; daher `traefik/dynamic/plex.yml` mit Ziel `192.168.178.58:32400`. Route nur ueber Traefik/443 (`plex.kaleschke.info`), direkter Plex-WAN-Port 32400 und Plex Remote Access bleiben deaktiviert. |
| `homeassistant` | Traefik ohne Authelia, Fach-YAML aus separatem Repo | Home Assistant bringt eigene Auth, mobile Apps, Webhooks und Integrationsfluesse mit. Der Container haengt in `frontend_net` fuer Traefik und in `smarthome_net` fuer MQTT/Zigbee2MQTT/ESPHome. `.storage` und Secrets bleiben in Appdata und werden per Borg gesichert, nicht versioniert. |
| `Ecowitt` | spaetere HTTP-Ausnahme offen | Ecowitt kann nur HTTP. Wegen globalem Traefik-HTTP-Redirect wird in Phase 2 entschieden, ob Traefik eine selektive Webhook-Ausnahme bekommt oder ob ein LAN-only HA-Port `8123` als dokumentierte Host-Port-Ausnahme noetig wird. |
---
## 11. Projektorganisation und Arbeitsmodus
### 11.1 Unser Arbeitsprinzip
Dieses Projekt wird heute nicht mehr sprintweise im Dokument gesteuert, sondern über einen stabilen GitOps-Betrieb.
### 11.2 Operativer Ablauf
1. Zielbild prüfen
2. lokal synchronisieren
3. gezielt ändern
4. Commit + Push
5. Komodo-Webhook und Ergebnis prüfen
6. Dokumentation nachziehen
### 11.3 Regel für jede Änderung
1. Zielbild in diesem Dokument prüfen
2. nur den betroffenen Bereich anfassen
3. Änderung lokal vorbereiten
4. nach Gitea pushen
5. automatische Reaktion von Komodo beachten
6. testen
7. dokumentieren
### 11.4 Source-of-Truth-Hierarchie
1. **Gitea Online (`origin/master`)**
2. lokaler Clone / GitHub Desktop
3. Compose-Dateien im Git-Repo
4. Komodo als Deploy-Consumer
5. operative Checklisten und Notizen
### 11.5 Operativer Git-Workflow
- Gitea Online ist der verbindliche Sollzustand.
- Lokal wird standardmäßig über GitHub Desktop gearbeitet.
- Komodo deployt aus Gitea und ist kein Bearbeitungsort.
- Webhooks sind aktiv: Ein Push kann unmittelbar einen Komodo-Deploy auslösen.
- Wenn online in Gitea editiert wurde, muss vor der nächsten lokalen Änderung zuerst `Fetch origin` und danach `Pull origin` erfolgen.
## 12. Nutzung mit KI / Kontext-Regel
Wenn mit einer KI gearbeitet wird, gilt immer:
> **„Lies zuerst `HOMELAB_ARCHITECTURE_MASTER_V2.md`, dann beantworte meine Frage."**
Damit ist sofort klar:
- welche Netze Standard sind
- welche Container wohin gehören
- welche Dienste öffentlich sein dürfen
- welche Dienste nur intern/VPN-only sind
- welche Migrationen noch offen sind
- welche Ausnahmen bewusst dokumentiert sind
---
## 13. Betriebserfahrungen und Entscheidungs-Log (ausgelagert)
Architektur- und Betriebsentscheidungen werden seit 2026-06-11 zentral in
`docs/DECISIONS.md` gefuehrt (ADR-light: Entscheidung, Kontext, Review-Trigger).
Dieses Dokument haelt nur noch das Zielbild. Neue Entscheidungen werden dort
eingetragen; hier aendert sich nur etwas, wenn das Zielbild selbst betroffen
ist (Netze, Zugangsmodell, Ausnahmen in Sektion 10).
---
## Schlussformel
Dieses Dokument ist keine lose Notiz, sondern das **operative Masterdokument** für die Docker- und Zugriffsarchitektur des Homelabs.
**Zielbild in einem Satz:**
`frontend_net` für Web-UIs und Dienste mit Internetbedarf, `backend_net` für interne Backends, app-interne Netze nur wenn technisch nötig, Tailscale für Remote-Admin-Zugriff, Traefik als einziger Web-Einstieg (Service-Routing via Docker-Labels, File-Provider nur für zentrale Dynamic-Config), Komodo als GitOps-Stack-Manager, AdGuard Home + Unbound für DNS, keine produktiven Container im Docker-Default-`bridge`.