initial homelab structure from NAS
This commit is contained in:
295
MIGRATION.md
Executable file
295
MIGRATION.md
Executable file
@@ -0,0 +1,295 @@
|
||||
# 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.
|
||||
Reference in New Issue
Block a user