Files
homelab/MIGRATION.md

296 lines
8.7 KiB
Markdown
Executable File
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 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 14 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.