# Homelab Migration – Operativer Plan ## Dateistruktur ``` homelab/ ├── 00_setup-networks.sh ├── 01_stack-backend.yml ├── 01_paperless.sql ← manuell per stdin einspielen, nicht gemountet ├── 02_stack-dns.yml ├── 03_stack-frontend.yml ├── 04_stack-traefik.yml ← Phase 5, noch nicht aktiv ├── .env ← nicht in Git! ├── .gitignore ├── secrets/ │ └── postgres_password.txt ← nicht in Git!, muss vor Phase 3 existieren └── traefik/ ← Phase 5 vorbereiten ├── traefik.yml └── dynamic/ └── middlewares.yml ``` --- ## Phase 0 – Vorbereitung (nichts migrieren, nur prüfen) ### 0a – Zugangsdaten rotieren Die Mail-Archiver-Credentials waren in `docker inspect` im Klartext sichtbar. ```bash # Neue Passwörter in .env setzen: # MAILARCHIVER_DB_PASSWORD, MAILARCHIVER_USERNAME, MAILARCHIVER_PASSWORD ``` ### 0b – Secrets anlegen ```bash mkdir -p secrets echo "sicheres_postgres_passwort" > secrets/postgres_password.txt chmod 600 secrets/postgres_password.txt # Dieses Passwort ist das POSTGRES Superuser-Passwort, nicht das paperless-Passwort! ``` ### 0c – .env befüllen Alle `AENDERN_*`-Werte in `.env` durch echte Passwörter ersetzen. **KRITISCH:** `REDIS_PASSWORD` und `PAPERLESS_DB_PASSWORD` müssen konsistent sein: - `REDIS_PASSWORD` → steht in `.env`, wird von Redis Container UND paperless-ngx verwendet - `PAPERLESS_DB_PASSWORD` → steht in `.env`, muss in `01_paperless.sql` gespiegelt sein ### 0d – PostgreSQL-Zustand prüfen ```bash # Läuft postgresql17 gerade? docker exec -it postgresql17 psql -U postgres -c "\l" docker exec -it postgresql17 psql -U postgres -c "\du" # Fragen die beantwortet sein müssen: # 1. Existiert ein User "paperless" bereits? # 2. Existiert eine DB "paperless" bereits? # 3. Liegt mailarchiver-DB ebenfalls auf dieser Instanz? # (docker exec -it postgresql17 psql -U postgres -c "\l" zeigt alle DBs) ``` ### 0e – 01_paperless.sql vorbereiten Passwort-Platzhalter ersetzen: ```bash # PAPERLESS_DB_PASSWORD aus .env nehmen und hier eintragen: sed -i 's/HIER_PAPERLESS_DB_PASSWORD_EINTRAGEN/dein_passwort/g' 01_paperless.sql ``` --- ## Phase 1 – Infrastruktur-Netze **Dauer: ~3 Min | Kein Ausfall | Sicher jederzeit** ```bash chmod +x 00_setup-networks.sh ./00_setup-networks.sh # ntopng entfernen docker stop ntopng && docker rm ntopng # Prüfen docker network ls | grep -E "frontend_net|backend_net|dns_net" ``` ✅ Immich, scanopy, host-Netz-Container → **nicht anfassen** --- ## Phase 2 – DNS **Dauer: ~10 Min | DNS-Ausfall: ~60 Sekunden** ### Vorbereitung ```bash # Aktuellen Pi-hole-Stand dokumentieren (Screenshots, Blocklists etc.) # Router-DNS auf 1.1.1.1 setzen falls pihole dein einziger DNS ist ``` ### Migration ```bash # 1. Alte Container stoppen docker stop binhex-official-pihole unbound docker rm binhex-official-pihole unbound # 2. Unbound zuerst starten docker compose -f 02_stack-dns.yml up -d unbound # 3. Warten bis unbound healthy watch -n3 'docker inspect --format "{{.State.Health.Status}}" unbound' # Erwartung: healthy # 4. Erst dann pihole docker compose -f 02_stack-dns.yml up -d binhex-official-pihole ``` ### Verifikation ```bash # pihole → unbound Verbindung docker exec binhex-official-pihole nslookup google.com unbound # Erwartung: Antwort kommt zurück # DNS von außen (Router-DNS zurückstellen auf deine IP) nslookup google.com 192.168.178.58 # Erwartung: Auflösung klappt ``` --- ## Phase 3 – Backend (Postgres + Redis + Paperless) **Dauer: ~20 Min | paperless-Ausfall: ~3 Minuten** ⚠ Backup vorhanden ✓ — trotzdem: Phase 0d zuerst abschließen! ### Phase 3a – DB-Zustand prüfen (nichts umbauen) ```bash docker exec -it postgresql17 psql -U postgres -c "\l" docker exec -it postgresql17 psql -U postgres -c "\du" ``` **Wenn paperless-User und -DB bereits existieren** → weiter zu Phase 3b, SQL überspringen. **Wenn paperless-User/DB fehlen** → erst 01_paperless.sql einspielen: ```bash # Variante B (kein Volume-Mount nötig — stdin direkt pipen): docker exec -i postgresql17 psql -U postgres < 01_paperless.sql # Prüfen docker exec -it postgresql17 psql -U postgres -c "\l" docker exec -it postgresql17 psql -U postgres -c "\du" # Erwartung: paperless-DB und paperless-User sichtbar ``` ### Phase 3b – paperless stoppen ```bash docker stop paperless-ngx Paperless-AI docker rm paperless-ngx Paperless-AI ``` ### Phase 3c – Redis + Postgres in backend_net ziehen ```bash # Alte Container stoppen docker stop Redis postgresql17 docker rm Redis postgresql17 # Backend-Stack starten docker compose -f 01_stack-backend.yml up -d # Health abwarten — NICHT weitermachen bevor beide healthy sind! watch -n3 'docker ps --filter "name=postgresql17" --filter "name=Redis" --format "table {{.Names}}\t{{.Status}}"' # Erwartung: beide "(healthy)" ``` ### Phase 3d – Verbindungen testen ```bash # PostgreSQL von backend_net erreichbar? docker run --rm --network backend_net postgres:17 \ psql "host=postgresql17 user=postgres password=$(cat secrets/postgres_password.txt) dbname=postgres" \ -c "SELECT version();" # Erwartung: PostgreSQL-Version # PostgreSQL vom Host NICHT mehr erreichbar? nc -zv 127.0.0.1 5432 # Erwartung: Connection refused ✓ # Redis PONG? docker run --rm --network backend_net redis:7-alpine \ redis-cli -h Redis -a "${REDIS_PASSWORD}" ping # Erwartung: PONG ``` ### Phase 3e – Paperless starten ```bash docker compose -f 03_stack-frontend.yml up -d paperless-ngx Paperless-AI # Logs die ersten 60 Sekunden beobachten docker logs -f paperless-ngx # Worauf achten: # ✓ Keine "AUTH failed"-Fehler (Redis-Passwort stimmt) # ✓ Keine "password authentication failed for user paperless" (DB-Passwort stimmt) # ✓ "Migrating..." läuft durch # ✓ Webinterface auf http://HOST:8000 erreichbar ``` --- ## Phase 4 – Frontend in Wellen **Pro Welle: ~5 Min | pro Container: ~15 Sek Ausfall** ### Welle A – unkritisch ```bash for c in homarr homepage Dozzle dashdot theme-park; do docker stop $c && docker rm $c && echo "✓ $c entfernt" done docker compose -f 03_stack-frontend.yml up -d homarr homepage Dozzle dashdot theme-park docker ps --filter "name=homarr" --filter "name=homepage" --filter "name=Dozzle" ``` ### Welle B – mittelkritisch ```bash for c in UptimeKuma scrutiny code-server; do docker stop $c && docker rm $c && echo "✓ $c entfernt" done docker compose -f 03_stack-frontend.yml up -d UptimeKuma scrutiny code-server ``` ### Welle C – sensibel (einzeln) ```bash # PortainerCE docker stop PortainerCE && docker rm PortainerCE docker compose -f 03_stack-frontend.yml up -d PortainerCE # vaultwarden — danach Tailscale-Zugang sofort testen! docker stop vaultwarden && docker rm vaultwarden docker compose -f 03_stack-frontend.yml up -d vaultwarden # Test: https://kallilabcore.taild9fcf2.ts.net:4743/admin erreichbar? # mail-archiver — danach Login und Sync prüfen docker stop mail-archiver && docker rm mail-archiver docker compose -f 03_stack-frontend.yml up -d mail-archiver docker logs -f mail-archiver # auf DB-Verbindungsfehler achten # Stash — separat je nach Nutzung docker stop Stash && docker rm Stash docker compose -f 03_stack-frontend.yml up -d Stash # luckyBackup docker stop luckyBackup && docker rm luckyBackup docker compose -f 03_stack-frontend.yml up -d luckyBackup ``` --- ## Abschlusskontrolle ```bash # Alle Container laufen? docker ps --format "table {{.Names}}\t{{.Status}}\t{{.Networks}}" # Port 5432 nicht mehr öffentlich? nc -zv 127.0.0.1 5432 # → Connection refused ✓ nc -zv 127.0.0.1 6379 # → Connection refused ✓ (alter Redis-Port) nc -zv 127.0.0.1 6382 # → Connection refused ✓ (alter Redis-Port) # Netzwerk-Isolation: Portainer kann postgresql17 NICHT sehen docker exec PortainerCE ping postgresql17 2>&1 | head -2 # → Name or service not known ✓ # paperless-ngx kann postgresql17 sehen docker exec paperless-ngx nc -zv postgresql17 5432 2>&1 # → Connection succeeded ✓ ``` --- ## Phase 5 – Traefik (separat, wenn bereit) Erst wenn Phase 1–4 stabil laufen: 1. `traefik/traefik.yml` anlegen (Vorlage in `04_stack-traefik.yml`) 2. Domain + DNS-Eintrag einrichten 3. Port 80 + 443 auf Router weiterleiten 4. `docker compose -f 04_stack-traefik.yml up -d` 5. Dashboard testen: `https://traefik.yourdomain.tld` 6. Pro Container: `traefik.enable: "false"` → `"true"`, Port auskommentieren --- ## Was unberührt bleibt | Stack | Grund | |---|---| | immich (immich_default) | bereits korrekt isoliert | | scanopy (scanopy_scanopy) | bereits korrekt isoliert | | Plex, Tailscale, ntopng* | host-Netz technisch bedingt | | Netdata, Glances, netalertx | host-Netz technisch bedingt | *ntopng wird entfernt und später sauber neu aufgesetzt.