27 KiB
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-03-29 | Aktueller Sprint: 7 (Authelia SSO/2FA) — Sprints 1–6 abgeschlossen
Inhaltsverzeichnis
- Systemüberblick
- Architektur-Prinzipien
- Finales Netzwerk-Zielbild
- Zugangsmodell: Traefik vs. Tailscale
- Globale Sicherheitsregeln
- Einordnungsschema für neue Container
- Container-Zielbild (vollständig)
- Traefik-Label-Standard
- Migrationsstrategie (Blöcke A–F)
- Bekannte Ausnahmen und Begründungen
- Projektorganisation und Arbeitsmodus
- Nutzung mit KI / Kontext-Regel
- Betriebserfahrungen und Entscheidungs-Log
1. Systemüberblick
| Eigenschaft | Wert |
|---|---|
| Host-OS | Unraid |
| Hostname | Kallilabcore |
| Reverse Proxy | Traefik v3 (100% Docker-Labels, kein File-Provider) |
| 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 (in Ablösung durch Komodo, Sprint 5) |
| 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 + 3000/Admin), Tailscale, Plex-Media-Server.
P2 — Das Setup bleibt bewusst einfach: frontend_net + backend_net + app-interne Netze
frontend_net= Proxy-/Web-Netzbackend_net= intern für DB/Cache/App-Kommunikation- zusätzliche Netze nur app-intern, wenn technisch nötig (
mealie_mealie_internal,immich_default,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
Komodo, filebrowser, scrutiny, UptimeKuma, code-server, Traefik-Dashboard, backrest und beszel 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 als Komodo/Portainer 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änzenprivileged: truenur mit dokumentierter Begründung- Docker-Socket standardmäßig vorsichtig behandeln; Komodo/PortainerCE sind dokumentierte Ausnahmen
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_mealie_internal |
bridge, internal: true |
internes Netz nur für mealie + mealie-postgres |
✅ umgesetzt |
immich_default |
Compose-intern, internal: true |
internes Immich-Netz | ✅ umgesetzt |
host |
host | nur für echte Sonderfälle | begründet |
3.2 Finales Diagramm (vereinfacht)
Internet
│
▼
traefik (80/443)
│
└── frontend_net
├── öffentliche Apps (vaultwarden, mealie, paperless, immich, gitea, ntfy, homepage)
├── Admin-UIs mit Middleware (komodo, uptime-kuma, filebrowser, scrutiny, code-server, backrest, beszel)
└── Hybrid-Dienste mit Internetbedarf (mail-archiver, 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_mealie_internal (internal: true) ✅
└── immich_default (internal: true) ✅
Host-Sonderfälle
├── tailscale
├── Plex-Media-Server
└── beszel-agent
4. Zugangsmodell: Traefik vs. Tailscale
4.1 Öffentlich über Traefik
Diese Dienste sind über echte *.kaleschke.info-Domains erreichbar:
vaultwarden— vault.kaleschke.infomealie— mealie.kaleschke.infopaperless-ngx— paperless.kaleschke.infontfy— ntfy.kaleschke.infogitea(Web) — git.kaleschke.infoimmich_server— immich.kaleschke.infohomepage— homepage.kaleschke.info
4.2 Nicht öffentlich / nur Tailscale oder Traefik + Middleware
Diese Dienste sind keine Public Apps:
Komodo— komodo.kaleschke.info (Middleware)UptimeKuma— uptime.kaleschke.info (Middleware)filebrowser— files.kaleschke.info (Middleware)scrutiny— scrutiny.kaleschke.info (Middleware)code-server— Traefik + Middlewarebeszel— beszel.kaleschke.info (Middleware ausstehend)backrest— Traefik + MiddlewareTraefik-DashboardAdGuard Home— Port 3000 direkt (kein Traefik, nur LAN-Zugang)
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
5. Globale Sicherheitsregeln
- Keine produktiven Dienste im Docker-Default-
bridge - Keine direkten Host-Ports für Web-UIs außer dokumentierte Ausnahmen
restart: unless-stoppedals Standard- Secrets als Datei /
_FILEoder Komodo/Portainer Environment Variables mit${VAR} no-new-privileges:trueergänzen, wo praktikabeltraefik.docker.network=frontend_netimmer explizit setzen- Admin-Dienste immer mit
dashboard-auth@file,secure-headers@file - Placeholder-Domains (
yourdomain.tld) sind verboten privileged: truenur mit Begründung- Volume-Mounts so klein und so read-only wie möglich
- Neue Dienste nur via Compose / Git-Stack
- Ä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_netoder eigenes app-internes Netz - Nein → nur das funktional nötige Netz
Schritt 4 — Ist es eine Datenbank oder ein Cache?
- Ja → niemals
frontend_net, nurbackend_netoder 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 →
hostnur 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, 100% Docker-Labels | — |
AdGuard Home |
✅ | dns_net (172.23.0.3), frontend_net |
Port 53 DNS direkt, Port 3000 Admin (LAN) | DNS-Server + Upstream zu unbound; kein Traefik (DNS-Sonderfall) | Admin-Port per Traefik + Middleware absichern (Block F) |
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/) |
TS_USERSPACE/privileged später prüfen |
backrest |
✅ | frontend_net, backend_net |
Traefik + Middleware | traefik.docker.network=frontend_net korrigiert |
Breite Mounts straffen (Block F) |
homepage |
✅ | frontend_net |
Traefik | öffentliche Startseite via homepage.kaleschke.info |
— |
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 |
ForwardAuth-Provider, Secrets via _FILE, PostgreSQL + Redis Shared |
NAS-seitige Einrichtung ausstehend (Secrets, DB, Users, DNS) |
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_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 |
7.4 Öffentliche Apps
| Container | Status | Soll-Netz(e) | Finaler Zugang | Finaler Sollzustand | Offene Punkte |
|---|---|---|---|---|---|
paperless-ngx |
✅ | frontend_net, backend_net |
Traefik | aktiv via paperless.kaleschke.info |
— |
Paperless-AI |
✅ | frontend_net |
Traefik | aktiv | — |
mealie |
✅ | frontend_net, mealie_mealie_internal |
Traefik | sauber getrennte App/DB-Struktur | — |
ntfy |
✅ | frontend_net |
Traefik | aktiv via ntfy.kaleschke.info, Git-Stack |
— |
gitea |
✅ | frontend_net |
Traefik + SSH-Port 222 | Web via Traefik, SSH direkt gebunden | — |
immich_server |
✅ | immich_default, frontend_net |
Traefik | aktiv via immich.kaleschke.info |
— |
immich_machine_learning |
✅ | immich_default |
intern | bleibt intern | — |
7.5 Admin / Operations
| Container | Status | Soll-Netz(e) | Finaler Zugang | Finaler Sollzustand | Offene Punkte |
|---|---|---|---|---|---|
komodo |
✅ | frontend_net |
Traefik + Middleware | primärer GitOps-Stack-Manager | — |
code-server |
✅ | frontend_net |
Traefik + Middleware | PASSWORD_FILE aktiv |
— |
PortainerCE |
⚠️ Legacy | frontend_net |
Traefik + Middleware | wird durch Komodo abgelöst | abschalten Sprint 5 |
filebrowser |
✅ | frontend_net |
Traefik + Middleware | aktiv via files.kaleschke.info |
Mounts einschränken (Block F) |
mail-archiver |
✅ | frontend_net, backend_net |
intern | IMAP-Abruf + DB-Zugang, kein öffentlicher Zugang | — |
7.6 Monitoring / Status
| Container | Status | Soll-Netz(e) | Finaler Zugang | Finaler Sollzustand | Offene Punkte |
|---|---|---|---|---|---|
UptimeKuma |
✅ | frontend_net |
Traefik + Middleware | aktiv via uptime.kaleschke.info |
— |
scrutiny |
✅ | frontend_net |
Traefik + Middleware | aktiv via scrutiny.kaleschke.info, Git-Stack |
privileged später prüfen |
beszel |
✅ | frontend_net |
Traefik | aktiv via beszel.kaleschke.info, Git-Stack |
Admin-Middleware ergänzen (Block F) |
beszel-agent |
✅ | host |
intern | System-Monitoring, Socket-Zugriff auf Host | — |
7.7 Sprint 5 — noch zu migrieren / abzuschalten
| Container | Status | Ziel |
|---|---|---|
Plex-Media-Server |
⏳ Dockerman | Compose-Migration, host-Netz bleibt (Discovery) |
PortainerCE |
⚠️ Legacy | abschalten nach vollständiger Komodo-Übernahme |
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; Log-Monitoring via Komodo/beszel |
dashdot |
2026-03-28 | nicht mehr aktiv; System-Monitoring via beszel |
netdata |
2026-03-28 | nicht mehr aktiv; System-Monitoring via beszel |
Glances |
2026-03-28 | nicht mehr aktiv |
netalertx |
2026-03-28 | nicht mehr aktiv |
luckyBackup |
2026-03-28 | nicht mehr aktiv; Backup via backrest |
Stash |
2026-03-28 | nicht mehr aktiv |
8. Traefik-Label-Standard
Jeder Dienst mit Traefik-Routing nutzt dieses Muster:
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 für Admin-Dienste
- traefik.http.routers.<name>.middlewares=dashboard-auth@file,secure-headers@file
Regeln
traefik.docker.networkimmer explizit auffrontend_net- keine
yourdomain.tld-Platzhalter - certresolver immer
le tls=trueimmer explizit setzen- wenn Traefik aktiv ist, werden direkte Host-Ports entfernt
- Admin-Dienste niemals ohne Middleware veröffentlichen
- File-Provider nur noch für:
middlewares.yml,tls.yml,dashboards.yml— keine Service-Routen mehr via File-Provider
9. Migrationsstrategie (Blöcke A–F)
Letzte Aktualisierung: 2026-03-29
Block A — Quick Wins ✅ ABGESCHLOSSEN
[x] restart: unless-stopped für alle Container gesetzt
[x] vaultwarden ADMIN_TOKEN-Doppelpräfix korrigiert
[x] backrest DNS-Hardcoding entfernt
[x] leere Netzwerke entfernt: br0, immich_net, kopia_default, netbox_default, diun_default
[x] anonyme/verwaiste Volumes bereinigt
[x] scanopy komplett entfernt (3 Container + 2 Volumes + Netz)
[x] binhex-official-pihole entfernt → ersetzt durch AdGuard Home + Unbound
Block B — Kritische Kernmigrationen ✅ ABGESCHLOSSEN
[x] vaultwarden - frontend_net, Host-Port entfernt, ADMIN_TOKEN_FILE, Traefik aktiv
[x] postgresql17 - Port 5432 entfernt, nur backend_net, POSTGRES_PASSWORD_FILE
[x] mealie-postgres - aus frontend_net raus, nur mealie_mealie_internal
Block C — Frontend-Stack finalisieren ✅ ABGESCHLOSSEN
[x] ntfy - Git-Stack - ntfy.kaleschke.info - Traefik aktiv
[x] paperless-ngx - traefik.enable=true - paperless.kaleschke.info - Port entfernt - tls=true
[x] Paperless-AI - traefik.enable=true - aktiv
[x] PortainerCE - traefik.enable=true - Middleware aktiv - direkte Ports entfernt
[x] UptimeKuma - traefik.enable=true - uptime.kaleschke.info - Port entfernt - Middleware aktiv
[x] filebrowser - frontend_net - traefik.enable=true - files.kaleschke.info - Port entfernt - Middleware aktiv
[x] scrutiny - frontend_net - traefik.enable=true - scrutiny.kaleschke.info - Git-Stack
[x] gitea - traefik.enable=true - git.kaleschke.info - SSH-Port 222 bleibt (Ausnahme dokumentiert)
[x] backrest - traefik.docker.network=frontend_net korrigiert (war backend_net — Routing-Bug)
[x] Traefik File-Provider bereinigt - immich.yml, gitea.yml, mealie.yml, scrutiny.yml, vaultwarden.yml.bak gelöscht
[x] immich Bad Gateway behoben - Traefik nutzt jetzt immich@docker statt immich@file
[x] AdGuard Home - Git-Stack - dns_net + frontend_net - Port 53 (DNS) + 3000 (Admin)
[x] beszel - Git-Stack - frontend_net - beszel.kaleschke.info - Traefik aktiv
[ ] beszel - Admin-Middleware (dashboard-auth@file) ergänzen
Block D — Dockerman-Container in Git-Stacks
[x] vaultwarden ✅
[x] postgresql17 ✅
[x] mail-archiver ✅
[x] scrutiny ✅
[x] filebrowser ✅
[x] tailscale ✅
[x] AdGuard Home ✅
[x] beszel ✅
[x] ntfy ✅
[x] homepage ✅
[ ] Plex-Media-Server (Sprint 5)
Block E — Secrets-Migration
[x] vaultwarden → ADMIN_TOKEN_FILE ✅
[x] postgresql17 → POSTGRES_PASSWORD_FILE ✅
[x] mail-archiver → Stack ENV (${MAILARCHIVER_AUTH_PASSWORD}) ✅
[x] mealie → Stack ENV (kein _FILE-Support) ✅
[x] mealie-postgres → Stack ENV (kein _FILE-Support) ✅
[x] paperless-ngx → Stack ENV (${PAPERLESS_DBPASS}) ✅
[x] code-server → PASSWORD_FILE ✅
[x] immich_server → Stack ENV (${IMMICH_DB_PASSWORD}) ✅
[x] immich_postgres → POSTGRES_PASSWORD_FILE ✅
[ ] immich_redis → anonymes Volume → named volume
Block F — Feinschliff / Hardening
[x] immich_default - internal: true gesetzt (2026-03-29)
[x] PortainerCE - abgeschaltet (Sprint 5, 2026-03-29)
[ ] immich_redis - anonymes Volume → named volume in Compose
[ ] immich_server - anonymes Volume prüfen und benennen
[ ] backrest - /mnt/user doppelt gemountet (ro + rw) - rw-Mount auf konkrete Pfade einschränken
[ ] filebrowser - /mnt/user:/srv ist sehr breit - auf /mnt/user/documents:/srv einschränken wenn möglich
[ ] Redis - optional named volume
[ ] scrutiny - später prüfen, ob privileged reduziert werden kann
[ ] tailscale - TS_USERSPACE/privileged bereinigen wenn möglich
[ ] beszel - Admin-Middleware (dashboard-auth@file) ergänzen
[ ] AdGuard Home - Admin-Port 3000 per Traefik + Middleware absichern (aktuell direkter Port)
Block G — Authelia SSO/2FA (Sprint 7)
[x] security/authelia/docker-compose.yml im Repo (2026-03-29)
[x] security/authelia/configuration.yml im Repo (2026-03-29)
[x] traefik/dynamic/middlewares.yml - authelia ForwardAuth Middleware ergänzt (2026-03-29)
[ ] NAS: Secrets anlegen (jwt_secret, session_secret, storage_encryption_key, postgres_password)
[ ] NAS: Authelia PostgreSQL-User und -Datenbank anlegen
[ ] NAS: /mnt/user/appdata/authelia/config/configuration.yml aus Repo übernehmen
[ ] NAS: users_database.yml mit gehashten Passwörtern anlegen
[ ] NAS: DNS-Eintrag auth.kaleschke.info in AdGuard setzen
[ ] Komodo: Stack security/authelia deployen
[ ] Services schrittweise mit authelia@docker Middleware absichern
10. Bekannte Ausnahmen und Begründungen
| Container | Ausnahme | Begründung |
|---|---|---|
traefik |
Host-Ports 80/443 | zentraler Reverse Proxy |
tailscale |
host |
VPN-Zugang; Umstellung nur kontrolliert möglich |
AdGuard Home |
Port 53 (TCP/UDP) direkt + Port 3000 Admin | DNS benötigt direkten Port 53; kein HTTP-Proxy für DNS möglich |
Plex-Media-Server |
host |
Discovery / mDNS / Plex GDM |
scrutiny |
privileged: true |
SMART-Datenzugriff auf Laufwerke |
beszel-agent |
host |
direkter Host-Zugriff für System-Monitoring nötig |
Komodo |
Docker-Socket Zugriff | Stack-Deployments benötigen Socket |
PortainerCE |
Docker-Socket | Legacy-UI; wird durch Komodo abgelöst |
gitea |
SSH-Port 222 direkt gebunden | Git-SSH-Zugang; kein HTTP-Proxy für SSH möglich |
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 |
11. Projektorganisation und Arbeitsmodus
11.1 Unser Arbeitsprinzip
Dieses Projekt wird blockweise umgesetzt, nicht wild containerweise.
11.2 Reihenfolge der Umsetzung
| Sprint | Inhalt | Status |
|---|---|---|
| Sprint 1 | Quick Wins + vaultwarden |
✅ Abgeschlossen |
| Sprint 2 | postgresql17 + diun/gotify |
✅ Abgeschlossen |
| Sprint 3 | mealie / mealie-postgres + mail-archiver |
✅ Abgeschlossen |
| Sprint 4 | Frontend-Stack (paperless, PortainerCE, Dozzle, dashdot, scrutiny, filebrowser, gitea, UptimeKuma, ntfy, beszel) + Traefik File-Provider Bereinigung + Komodo Einführung + AdGuard Home Migration + Pi-hole Ablösung |
✅ Abgeschlossen |
| Sprint 5 | Plex-Media-Server Compose-Migration + PortainerCE abschalten |
✅ Abgeschlossen |
| Sprint 6 | Hardening / Secrets / Volumes / Sonderfälle (immich_default ✅, Volumes, Mounts, AdGuard Traefik) |
✅ Abgeschlossen |
| Sprint 7 | Authelia SSO/2FA: Compose + Config im Repo, Traefik ForwardAuth Middleware, NAS-seitige Einrichtung |
🔄 In Bearbeitung |
11.3 Regel für jede Änderung
- Zielbild in diesem Dokument prüfen
- nur den aktuellen Block anfassen
- Compose-Datei ändern
- deployen
- testen
- dokumentieren / abhaken
- erst dann nächster Schritt
11.4 Source-of-Truth-Hierarchie
- Dieses Dokument
- Compose-Dateien im Git-Repo
- operative Checklisten
- 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
13. Betriebserfahrungen und Entscheidungs-Log
Traefik — Wechsel zu reinen Docker-Labels (2026-03-28)
Die statischen File-Provider-Konfigurationen in /mnt/user/appdata/traefik/dynamic/ wurden vollständig bereinigt:
- Gelöscht:
immich.yml,gitea.yml,mealie.yml,scrutiny.yml,vaultwarden.yml.bak - Verbleibend (notwendig):
middlewares.yml,tls.yml,dashboards.yml
Hintergrund: Die alten File-Provider-Configs haben @file-Routen mit @docker-Routen konkurrieren lassen. In Traefik v3 gewinnt der File-Provider und hat z.B. Immich auf die falsche IP geroutet (Bad Gateway). Nach Löschung läuft Traefik ausschließlich auf Docker-Labels.
Regel: Neue Dienste ausschließlich via Docker Compose Labels konfigurieren. Keine neuen .yml-Dateien im dynamic/-Verzeichnis für Service-Routen anlegen.
Komodo — Ablösung von Portainer als Stack-Manager (2026-03-28)
Komodo ist nun der primäre GitOps-Stack-Manager:
- Komodo Core läuft als Docker-Stack (
ops/komodo/docker-compose.yml) - Komodo Periphery läuft auf dem Unraid-Host für direktes Server-Management
- Stacks werden via Gitea synchronisiert und über Komodo deployed
- Portainer CE läuft noch als Legacy-UI und wird in Sprint 5 abgeschaltet
Vorteil gegenüber Portainer: Sauberer GitOps-Flow ohne Web-Editor; alle Stack-Änderungen laufen über Git.
AdGuard Home — Ablösung von Pi-hole (2026-03-28)
binhex-official-pihole wurde entfernt und durch AdGuard Home + unbound ersetzt:
- 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
- Port 3000 (Admin-UI) direkt gebunden — Traefik-Absicherung ausstehend (Block F)
unboundläuft weiterhin als Upstream-Resolver indns_net
diun — Entfernung (2026-03-28)
diun (Docker Image Update Notifier) wurde deinstalliert:
- Stack gelöscht
- Orphan-Netzwerk
diun_diun_defaultbereinigt - Repo-Eintrag
infra/diun/aus Git entfernt
Update-Monitoring kann über Komodo's eingebaute Update-Notifications abgedeckt werden.
ntfy — Push-Notifications (Git-Stack)
ntfy läuft als Git-Stack (apps/ntfy/docker-compose.yml):
ntfy.kaleschke.infovia TraefikNTFY_UPSTREAM_BASE_URL: https://ntfy.shfür mobile Push-NotificationsNTFY_BEHIND_PROXY: truekorrekt gesetzt
immich_default — internal: true gesetzt (2026-03-29)
immich_default wurde von external: true auf ein Compose-verwaltetes internes Netz umgestellt:
- Vorher:
external: true(manuell erstellt, falsche Labelscom.docker.compose.network=default) - Nachher: Compose-managed,
internal: true,driver: bridge, korrekte Labels - Durchgeführt via: manuelles
docker stopder Containers →docker network rm immich_default→ Komodo Redeploy - Ergebnis: alle Immich-Container (
immich_postgres,immich_redis,immich_machine_learning) sind jetzt vom Internet isoliert; nurimmich_serverhat zusätzlichfrontend_netfür Traefik
Secrets in Komodo / Portainer Stacks
Host-Pfade in env_file (z.B. /mnt/...) sind in Git-Stacks nicht verfügbar. Standardlösung: Stack Environment Variables + ${VARIABLE_NAME} in der Compose.
Regel: Wenn _FILE nicht unterstützt wird → Stack Environment Variable. Kein Secret im Git.
| Container | _FILE Support |
|---|---|
| Vaultwarden | ✅ ja |
| PostgreSQL | ✅ ja |
| code-server | ✅ ja (PASSWORD_FILE) |
| Immich Postgres | ✅ ja (POSTGRES_PASSWORD_FILE) |
| Mealie | ❌ nein → Stack ENV |
| paperless-ngx | ❌ nein für DB-Pass → Stack ENV |
ddns-updater — Netz-Ausnahme
Bleibt bewusst in frontend_net statt backend_net, weil backend_net internal: true ist und ddns-updater die Cloudflare-API erreichen muss.
mail-archiver — Hybrid-Dienst
Benötigt backend_net (PostgreSQL) + frontend_net (IMAP-Abruf von GMX/Gmail). Kein reiner Backend-Dienst. Kein öffentlicher Traefik-Zugang.
Netzwerk-Standard für Apps mit Datenbanken
- App →
frontend_net+ internes Netzwerk - Datenbank → nur internes Netzwerk (
internal: true)
Beispiel (Mealie): mealie → frontend_net + mealie_mealie_internal, mealie-postgres → nur mealie_mealie_internal.
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 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 (100% Docker-Labels), Komodo als GitOps-Stack-Manager, AdGuard Home + Unbound für DNS, keine produktiven bridge-Container mehr.