diff --git a/HOMELAB_ARCHITECTURE_MASTER_V2.md b/HOMELAB_ARCHITECTURE_MASTER_V2.md new file mode 100644 index 0000000..6a0cfc1 --- /dev/null +++ b/HOMELAB_ARCHITECTURE_MASTER_V2.md @@ -0,0 +1,557 @@ +# 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. + +--- + +## 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. [Migrationsstrategie (Blöcke A–F)](#9-migrationsstrategie-blöcke-a-f) +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) + +--- + +## 1. Systemüberblick + +| Eigenschaft | Wert | +|---|---| +| Host-OS | Unraid | +| Hostname | Kallilabcore | +| Reverse Proxy | Traefik v3 | +| VPN / Remote-Zugang | Tailscale (`Tailscale-Docker`, host-Netz) | +| DNS-Stack | Pi-hole (host) → Unbound (`dns_net`) | +| Basis-Domain | `kaleschke.info` | +| TLS | Let's Encrypt via Cloudflare DNS Challenge | +| Certresolver | `le` | +| Compose-Standard | Unraid Compose Manager | +| Zusatz-Tool | Portainer als Verwaltungs-UI | +| 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 final direkte Host-Ports außer `traefik` selbst. +Begründete Ausnahmen: `gitea`-SSH, `Plex-Media-Server`, `binhex-official-pihole`, `Tailscale-Docker`. + +### P2 — Das Setup bleibt bewusst einfach: `frontend_net` + `backend_net` + app-interne Netze +Die Quellenlage für Homelabs mit Traefik spricht für ein simples 2-Netz-Modell: +- `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`, `scanopy_scanopy`, `dns_net`) + +Es gibt **keine künstlichen globalen Zusatznetze** wie `admin_net`, `monitoring_net` oder `media_net`. + +### 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 +Portainer, Dozzle, filebrowser, scrutiny, UptimeKuma, dashdot, code-server, luckyBackup, Traefik-Dashboard, netdata, Glances und netalertx sind standardmäßig **Tailscale-only** oder hinter Traefik **mit zentraler Middleware** abgesichert. + +### 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 in `_FILE`-Variablen. +Ziel: kein sensibles Secret mehr sichtbar in `docker inspect`. + +### 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 +- `read_only: true` und Non-Root nur nach getesteter Image-Kompatibilität +- Docker-Socket standardmäßig vorsichtig behandeln; **PortainerCE ist eine 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 für `unbound` | bleibt | +| `mealie_internal` | bridge, `internal: true` | internes Netz nur für `mealie` + `mealie-postgres` | Ziel | +| `immich_default` | Compose-intern | internes Immich-Netz | bleibt | +| `scanopy_scanopy` | Compose-intern | internes Scanopy-Netz | bleibt | +| `diun_default` | Compose-intern | Compose-Netz für diun | bleibt, zusätzlich Join zu `frontend_net` | +| `host` | host | nur für echte Sonderfälle | begründet | + +### 3.2 Finales Diagramm (vereinfacht) + +```text +Internet + │ + ▼ +traefik (80/443) + │ + └── frontend_net + ├── öffentliche Apps + ├── Admin-UIs mit Middleware + └── interne Web-UIs für Tailscale-only + +backend_net (internal: true) + ├── postgresql17 + ├── Redis + ├── mail-archiver + └── paperless / andere Backends + +App-interne Netze + ├── mealie_internal + ├── immich_default + └── scanopy_scanopy + +Host-Sonderfälle + ├── Tailscale-Docker + ├── binhex-official-pihole + ├── Plex-Media-Server + ├── netdata + ├── Glances + └── netalertx +``` + +### 3.3 Architekturentscheidung (final) +**Wir bleiben final bei wenigen Netzen.** +Das ist bewusst näher an aktuellen Homelab-Traefik-Setups als ein künstlich übersegmentiertes Docker-Netzmodell. +Trennung erfolgt primär über: +- Traefik +- Auth-/Security-Middlewares +- Tailscale +- kein direktes Port-Publishing +- app-interne Netze +- Host-Sonderfälle nur mit Begründung + +--- + +## 4. Zugangsmodell: Traefik vs. Tailscale + +### 4.1 Öffentlich über Traefik +Diese Dienste dürfen final über echte `*.kaleschke.info`-Domains erreichbar sein: + +- `homepage` +- `vaultwarden` +- `mealie` +- `paperless-ngx` +- `gotify` +- `gitea` (Web) +- `immich_server` +- optional `mail-archiver` +- optional `backrest` +- optional `Stash` (nur wenn bewusst gewünscht) + +### 4.2 Nicht öffentlich / nur Tailscale oder Traefik + Middleware +Diese Dienste sind **keine Public Apps**: + +- `PortainerCE` +- `Dozzle` +- `UptimeKuma` +- `dashdot` +- `filebrowser` +- `scrutiny` +- `luckyBackup` +- `code-server` +- `scanopy-server` +- `Traefik-Dashboard` +- `netdata` +- `Glances` +- `netalertx` + +### 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 zusätzlich durch Tailscale bzw. Auth begrenzt ist + +--- + +## 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` +5. `no-new-privileges:true` ergänzen, wo praktikabel +6. `traefik.docker.network=frontend_net` immer explizit setzen +7. Admin-Dienste immer mit `dashboard-auth@file,secure-headers@file` +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 Manager / YAML +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 eine DB / Redis / interne Backends? +- **Ja** → zusätzlich `backend_net` oder eigenes app-internes Netz +- **Nein** → nur das funktional nötige Netz + +### Schritt 3 — Ist es eine Datenbank oder ein Cache? +- **Ja** → niemals `frontend_net`, nur `backend_net` oder internes Compose-Netz + +### Schritt 4 — Ist es ein Admin-/Monitoring-Dienst? +- **Ja** → wenn Web-UI vorhanden trotzdem `frontend_net`, aber nur mit: + - Middleware + - keiner direkten Portfreigabe + - Tailscale-only-Charakter + +### Schritt 5 — Braucht der Dienst Host-/Discovery-/L2-Sicht? +- **Ja** → `host` nur mit dokumentierter Begründung +- **Nein** → kein `host` + +### Schritt 6 — Braucht die App ein eigenes internes App-Netz? +- **Ja** → Compose-internes Netz mit `internal: true` +- **Nein** → kein weiteres Netz anlegen + +### Kurzregel +- **UI** → `frontend_net` +- **DB/Cache** → `backend_net` +- **Spezialfall** → app-internes Netz +- **Host-Zugriff** → nur dokumentierte Ausnahme + +--- + +## 7. Container-Zielbild (vollständig) + +Legende Status: +- `✅` = bereits weitgehend passend +- `⏳` = noch zu migrieren / zu korrigieren + +### 7.1 Infrastruktur / Core + +| Container | Status | Soll-Netz(e) | Finaler Zugang | Finaler Sollzustand | Offene Punkte | +|---|---|---|---|---|---| +| `traefik` | ✅ | `frontend_net`, `backend_net` | öffentlich | zentraler Ingress, 80/443 direkt | Middleware-File-Provider sauber pflegen | +| `homepage` | ✅ | `frontend_net` | Traefik | öffentliche Startseite | — | +| `ddns-updater` | ⏳ | `backend_net` | intern | kein Grund für `frontend_net` | aus `frontend_net` raus | +| `Tailscale-Docker` | ⏳ | `host` | VPN-Zugang | bleibt Host-Sonderfall | `restart` fixen; `TS_USERSPACE`/`privileged` später prüfen, nicht als Quick Win | +| `binhex-official-pihole` | ⏳ | `host` | LAN DNS / intern | bleibt Host-Sonderfall | `restart` fixen | +| `unbound` | ✅ | `dns_net` | intern | Resolver bleibt isoliert | — | +| `backrest` | ⏳ | `frontend_net`, `backend_net` | Traefik oder intern | UI via Traefik, Repo intern | `traefik.docker.network` auf `frontend_net`; DNS-Hardcoding entfernen; Mounts straffen | +| `diun` | ⏳ | `diun_default`, `frontend_net` | intern | braucht `frontend_net`, um `gotify` zu erreichen | Gotify-Endpoint per Container-Name | +| `theme-park` | ⏳ | `frontend_net` oder rein intern | intern oder Traefik | nur veröffentlichen, wenn wirklich genutzt | Placeholder-Labels bereinigen | +| `scanopy-daemon` | ⏳ | `host`, `scanopy_scanopy` falls nötig | intern | Host-naher Sonderfall | Privileged nur dokumentiert belassen oder später testen | + +### 7.2 Sicherheit / Identity + +| Container | Status | Soll-Netz(e) | Finaler Zugang | Finaler Sollzustand | Offene Punkte | +|---|---|---|---|---|---| +| `vaultwarden` | ⏳ | `frontend_net` | Traefik | keine Host-Ports, kein `bridge`, Secret-Datei | `ADMIN_TOKEN`-Bug fixen; Port 4743 entfernen; Compose-Migration | + +### 7.3 Datenbanken / Caches + +| Container | Status | Soll-Netz(e) | Finaler Zugang | Finaler Sollzustand | Offene Punkte | +|---|---|---|---|---|---| +| `postgresql17` | ⏳ | `backend_net` | intern | keine Host-Ports, kein `bridge` | Port 5432 entfernen; Secret-Datei; Compose-Migration | +| `Redis` | ✅ | `backend_net` | intern | intern-only Cache | optional named volume statt anonym | +| `mealie-postgres` | ⏳ | `mealie_internal` | intern | nur intern, nie `frontend_net` | aus `frontend_net` raus; Secret-Datei | +| `immich_postgres` | ⏳ | `immich_default` | intern | intern-only | Passwort rotieren; named volume prüfen | +| `immich_redis` | ⏳ | `immich_default` | intern | intern-only | anonymes Volume perspektivisch bereinigen | +| `scanopy-postgres` | ⏳ | `scanopy_scanopy` | intern | intern-only | Passwort rotieren (aktuell Wiederverwendung) | + +### 7.4 Öffentliche Apps + +| Container | Status | Soll-Netz(e) | Finaler Zugang | Finaler Sollzustand | Offene Punkte | +|---|---|---|---|---|---| +| `paperless-ngx` | ⏳ | `frontend_net`, `backend_net` | Traefik | vorbereitete Labels final aktivieren | `traefik.enable=true`; echte Domain; Port entfernen; Secret-Datei | +| `Paperless-AI` | ⏳ | `frontend_net` | Traefik oder intern | Port nicht mehr direkt offen | echte Domain; Labels aktivieren | +| `mealie` | ⏳ | `frontend_net`, `mealie_internal` | Traefik | sauber getrennte App/DB-Struktur | Port entfernen; Secret-Datei | +| `gotify` | ⏳ | `frontend_net` | Traefik oder intern | intern per Container-Name für `diun` erreichbar | Passwort rotieren; Port entfernen | +| `gitea` | ⏳ | `frontend_net` | Traefik + SSH | Web via Traefik, SSH-Port bleibt | HTTP-Labels sauberziehen | +| `immich_server` | ⏳ | `immich_default`, `frontend_net` | Traefik | internes Immich-Netz bleibt; Web via Traefik | Port 2283 entfernen; Secret-Datei; `frontend_net` ergänzen | +| `immich_machine_learning` | ✅ | `immich_default` | intern | bleibt intern | — | +| `Stash` | ⏳ | `frontend_net` | intern oder Traefik | aus `bridge` raus; nur veröffentlichen wenn bewusst gewünscht | Port entfernen; ggf. Traefik-Labels | + +### 7.5 Admin / Operations + +| Container | Status | Soll-Netz(e) | Finaler Zugang | Finaler Sollzustand | Offene Punkte | +|---|---|---|---|---|---| +| `code-server` | ⏳ | `frontend_net` | Traefik + Middleware / Tailscale-only | nicht öffentlich offen | `PASSWORD` → `HASHED_PASSWORD`; Secret-Datei | +| `PortainerCE` | ⏳ | `frontend_net` | Traefik + Middleware / Tailscale-only | keine Host-Ports | echte Domain; Labels aktivieren; direkte Ports entfernen; **Docker-Socket nicht blind auf `:ro`** | +| `Dozzle` | ⏳ | `frontend_net` | Traefik + Middleware / Tailscale-only | keine Host-Ports | Labels aktivieren; direkte Ports entfernen | +| `filebrowser` | ⏳ | `frontend_net` | Traefik + Middleware / Tailscale-only | aus `bridge`; breite FS-Mounts prüfen | Port entfernen; Mounts einschränken | +| `scanopy-server` | ⏳ | `scanopy_scanopy`, `frontend_net` | Traefik + Middleware / Tailscale-only | kein direkter Host-Port | `frontend_net` ergänzen; Port entfernen | +| `luckyBackup` | ⏳ | `frontend_net` | Traefik + Middleware / Tailscale-only | aus `bridge`; nur intern | Port entfernen; breite Mounts prüfen | + +### 7.6 Monitoring / Status + +| Container | Status | Soll-Netz(e) | Finaler Zugang | Finaler Sollzustand | Offene Punkte | +|---|---|---|---|---|---| +| `UptimeKuma` | ⏳ | `frontend_net` | Traefik + Middleware / Tailscale-only | keine direkten Ports | Labels sauberziehen; Port entfernen | +| `dashdot` | ⏳ | `frontend_net` | Traefik + Middleware / Tailscale-only | keine direkten Ports | Placeholder-Domain raus; Labels aktivieren | +| `Glances` | ⏳ | `host` | Tailscale-only | Host-Metriken | optional später hinter Traefik, aber nicht nötig | +| `netdata` | ⏳ | `host` | Tailscale-only | Host-Metriken | `restart` fixen; leere CLAIM-Vars aufräumen | +| `scrutiny` | ⏳ | `frontend_net` | Traefik + Middleware / Tailscale-only | aus `bridge`; echtes Image beibehalten | Ports entfernen; später prüfen, ob `privileged` reduziert werden kann | +| `netalertx` | ✅ | `host` | Tailscale-only | Host-/Netzsicht bleibt | optional später hinter Traefik, aber kein Muss | + +--- + +## 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..rule=Host(`.kaleschke.info`) + - traefik.http.routers..entrypoints=websecure + - traefik.http.routers..tls=true + - traefik.http.routers..tls.certresolver=le + - traefik.http.services..loadbalancer.server.port= +``` + +### Zusatz für Admin-Dienste +```yaml + - traefik.http.routers..middlewares=dashboard-auth@file,secure-headers@file +``` + +### Regeln +- `traefik.docker.network` immer explizit auf `frontend_net` +- keine `yourdomain.tld`-Platzhalter +- certresolver immer `le` +- wenn Traefik aktiv ist, werden direkte Host-Ports entfernt +- Admin-Dienste niemals ohne Middleware veröffentlichen + +--- + +## 9. Migrationsstrategie (Blöcke A–F) + +**Letzte Aktualisierung:** 2026-03-23 + +### Block A — Quick Wins (geringes Risiko, sofort) + +```text +[ ] restart: unless-stopped für: + - Tailscale-Docker + - binhex-official-pihole + - postgresql17 + - vaultwarden + - mail-archiver + - scrutiny + - netdata + - Stash + - Plex-Media-Server + +[ ] vaultwarden ADMIN_TOKEN-Doppelpräfix korrigieren +[ ] backrest DNS-Hardcoding entfernen +[ ] diun ↔ gotify Erreichbarkeit prüfen / herstellen +[ ] leere Netzwerke prüfen und entfernen: br0, immich_net, kopia_default, netbox_default +[ ] ungenutzte anonyme Volumes prüfen +``` + +### Block B — Kritische Kernmigrationen (höchste Priorität) + +```text +[ ] vaultwarden + - von bridge weg + - Host-Port weg + - Secret-Datei + - Traefik sauber aktiv + +[ ] postgresql17 + - Port 5432 entfernen + - nur backend_net + - Secret-Datei + - aus bridge raus + +[ ] diun + - Join zu frontend_net + - gotify via Container-Name + +[ ] mealie-postgres + - aus frontend_net raus + - mealie_internal +``` + +### Block C — Frontend-Stack finalisieren + +```text +[ ] paperless-ngx + - traefik.enable=true + - paperless.kaleschke.info + - Port entfernen + +[ ] Paperless-AI + - traefik.enable=true + - paperless-ai.kaleschke.info + - Port entfernen + +[ ] PortainerCE + - traefik.enable=true + - portainer.kaleschke.info + - Middleware + - direkte Ports entfernen + +[ ] Dozzle + - traefik.enable=true + - dozzle.kaleschke.info + - Middleware + - direkte Ports entfernen + +[ ] dashdot + - traefik.enable=true + - dash.kaleschke.info + - Middleware + - direkte Ports entfernen + +[ ] theme-park + - nur wenn wirklich benötigt veröffentlichen +``` + +### Block D — Bridge-/Dockerman-Container in Compose + +```text +[ ] vaultwarden +[ ] postgresql17 +[ ] mail-archiver +[ ] scrutiny +[ ] filebrowser +[ ] luckyBackup +[ ] Stash +[ ] Tailscale-Docker +[ ] netdata +[ ] Plex-Media-Server +[ ] binhex-official-pihole +``` + +### Block E — Secrets-Migration + +```text +[ ] vaultwarden → ADMIN_TOKEN_FILE +[ ] postgresql17 → POSTGRES_PASSWORD_FILE +[ ] mail-archiver → Authentication__Password_FILE +[ ] mealie → POSTGRES_PASSWORD_FILE +[ ] mealie-postgres → POSTGRES_PASSWORD_FILE +[ ] gotify → Passwort rotieren + Secret-Datei +[ ] diun → GOTIFY token als Datei +[ ] paperless-ngx → PAPERLESS_DBPASS_FILE +[ ] code-server → HASHED_PASSWORD / Secret +[ ] immich_server → DB_PASSWORD rotieren + Datei +[ ] immich_postgres → POSTGRES_PASSWORD_FILE +[ ] scanopy-postgres → Passwort rotieren +``` + +### Block F — Feinschliff / Hardening + +```text +[ ] backrest + - traefik.docker.network → frontend_net + - Mounts straffen + +[ ] Redis + - optional named volume + +[ ] immich_redis + - optional named volume + +[ ] netdata + - leere CLAIM-Vars entfernen + +[ ] scrutiny + - später prüfen, ob privileged reduziert werden kann + +[ ] Tailscale-Docker + - später prüfen, ob TS_USERSPACE/privileged bereinigt werden kann + +[ ] Pi-hole + - zuletzt konsolidieren, nicht als Erstprojekt +``` + +--- + +## 10. Bekannte Ausnahmen und Begründungen + +| Container | Ausnahme | Begründung | +|---|---|---| +| `traefik` | Host-Ports 80/443 | zentraler Reverse Proxy | +| `Tailscale-Docker` | `host`, aktuell `privileged`, `TS_USERSPACE=true` | bestehender VPN-Zugang; Umstellung nur kontrolliert | +| `binhex-official-pihole` | `host` | DNS-/DHCP-naher Sonderfall | +| `Plex-Media-Server` | `host` | Discovery / mDNS / Plex GDM | +| `netdata` | `host` + zusätzliche Rechte | Host-Metriken | +| `Glances` | `host` | Host-Metriken | +| `netalertx` | `host` + Netzwerksicht | ARP / Netzwerkscan | +| `scanopy-daemon` | `host`, aktuell privilegiert | hardware-/systemnaher Sonderfall | +| `PortainerCE` | Docker-Socket nicht dogmatisch `:ro` | Management-UI; Schreiboperationen können nötig sein | + +--- + +## 11. Projektorganisation und Arbeitsmodus + +### 11.1 Unser Arbeitsprinzip +Dieses Projekt wird **blockweise** umgesetzt, nicht wild containerweise. + +### 11.2 Reihenfolge der Umsetzung +1. **Sprint 1:** Quick Wins + `vaultwarden` +2. **Sprint 2:** `postgresql17` + `diun/gotify` +3. **Sprint 3:** `mealie` / `mealie-postgres` + `mail-archiver` +4. **Sprint 4:** Frontend-Stack (`paperless`, `Portainer`, `Dozzle`, `dashdot`, etc.) +5. **Sprint 5:** Compose-Migration der Dockerman-Container +6. **Sprint 6:** Hardening / Secrets / Volumes / Sonderfälle + +### 11.3 Regel für jede Änderung +Jeder Sprint folgt demselben Schema: + +1. Zielbild in diesem Dokument prüfen +2. nur den aktuellen Block anfassen +3. Compose-Datei ändern +4. deployen +5. testen +6. dokumentieren / abhaken +7. erst dann nächster Schritt + +### 11.4 Source-of-Truth-Hierarchie +1. **Dieses Dokument** +2. Compose-Dateien +3. operative Checklisten / Excel +4. ad-hoc Notizen / Chat + +--- + +## 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 + +--- + +## 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 alle Web-UIs, `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, keine produktiven `bridge`-Container mehr.