# migrations-backup runbook — vor dem full-wipe > Ziel: alles sichern → verifizieren → NVMe + Tank wipen → Proxmox & Tank frisch nach Manifest → zurückspielen. > **Regel: solange das Backup nicht getestet ist, wird nichts gewiped.** Nach dem Wipe gibt es keinen `zpool import` mehr — das Backup ist die einzige Kopie. ## ausgangslage (aus deinen screenshots) - Root liegt auf **local-lvm (LVM-Thin)**, nicht ZFS → Reinstall ist der einzige Weg zum ZFS-Root. - **tank** = ZFS-Mirror (die Bulk-Daten). - **ext-hdd01** (`/mnt/pve/ext-hdd01`, Directory, Backup-fähig) = Backup-Ziel, überlebt den Wipe. ## dein inventar | ID | Name | Typ | Annahme: stateful? | |----|------|-----|--------------------| | 100 | nextcloud | LXC | DB + Files | | 101 | immich | LXC | Postgres + Files | | 102 | vaultwarden | LXC | Daten/SQLite | | 103 | mailserver | LXC | **KRITISCH** — Mail + DB + DKIM | | 105 | obsidian-livesync | LXC | CouchDB? | | 106 | gitea | LXC | DB + Repos | | 107 | openbureau | LXC | Postgres? | | 110 | flarum | LXC | DB | | 111 | nginx-proxy-manager | LXC | Config/Certs | | 200 | kgva-website | LXC | meist statisch | | 210 | openbureau-web | LXC | meist statisch | | 211 | rapport-website | LXC | meist statisch | | 212 | dossier-website | LXC | meist statisch | | 219 | dev.openbureau | LXC | ? | | 220 | trattoriamarina.ch | LXC | meist statisch | | 900 | rapport-server | LXC | Postgres/Supabase? | | 500 | windows | **VM** | grösster Brocken — Platz checken | | 800 | homeassistant-os | **VM** | Config | > Die „stateful?"-Spalte sind **Annahmen** — bitte bestätigen/korrigieren (siehe Schritt 0). --- ## schritt 0 — discovery (mountpoints + backup-flags aufdecken) ```bash # was ist wo gemountet, und ist backup=1 oder backup=0? for id in $(pct list | awk 'NR>1{print $1}'); do echo "=== CT $id ==="; pct config $id | grep -E '^(rootfs|mp[0-9]+):' done # was liegt auf dem tank? zfs list -r tank # freier platz auf der backup-platte? df -h /mnt/pve/ext-hdd01 ``` Das zeigt, welche Daten schon in den vzdumps stecken (rootfs + `backup=1`-Mounts) und welche **separat per Restic** müssen (`backup=0`-Mounts auf dem Tank). → **Diese Ausgabe brauche ich, um die exakten Restic-Pfade einzusetzen.** --- ## schritt 1 — stateful dienste app-level dumpen (portabel über den rebuild) Macht die Wiederherstellung sauber unabhängig von Block-Konsistenz. Dumps in einen Pfad schreiben, der mitgesichert wird (rootfs oder ein `backup=1`-Mount). - **103 mailserver** — sein eigenes Backup nutzen. Bei docker-mailserver: `setup backup` bzw. das Mailcow-Backup-Skript. **DKIM-Keys + DNS-Records (SPF/DMARC/MX) separat notieren** — der häufigste Migrations-Schmerz. - **DB-Dienste** (100/101/106/110/107/900 — je nach Engine): ```bash # Postgres (im docker-container): pct exec -- docker exec pg_dumpall -U postgres > /pfad/dump.sql # MariaDB/MySQL: pct exec -- docker exec mysqldump --all-databases -uroot -p > /pfad/dump.sql ``` - **102 vaultwarden / 105 obsidian-livesync** — vor dem Sichern stoppen, dann ist der Datenstand konsistent. --- ## schritt 2 — container + VMs sichern (vzdump → ext-hdd01) Weil wir eh wipen, ist Downtime okay → `--mode stop` = sauber konsistent. ```bash # alle CTs und VMs: for id in $(pct list | awk 'NR>1{print $1}') $(qm list | awk 'NR>1{print $1}'); do vzdump $id --mode stop --compress zstd --storage ext-hdd01 done ``` > Achtung: **500 (windows)** ist vermutlich der grösste Brocken. Vorher `df -h /mnt/pve/ext-hdd01` prüfen. --- ## schritt 3 — tank-daten sichern (restic → ext-hdd01 UND hetzner) Pfade aus Schritt 0 einsetzen. Zwei unabhängige Kopien, weil es nach dem Wipe die einzige Quelle ist. ```bash export RESTIC_PASSWORD_FILE=/root/.restic-pw # lokal auf die externe platte export RESTIC_REPOSITORY=/mnt/pve/ext-hdd01/restic-tank restic init restic backup /tank/ /tank/ /tank/<...> # offsite nach hetzner export RESTIC_REPOSITORY=sftp:uXXXX@uXXXX.your-storagebox.de:/tank restic init restic backup /tank/ /tank/ /tank/<...> ``` Restic als root → Eigentümer/Rechte (inkl. Idmap-Offsets der Shares) kommen 1:1 zurück. --- ## schritt 4 — verifizieren + restore-test (PFLICHT) ```bash restic -r /mnt/pve/ext-hdd01/restic-tank check # einen container testweise auf freie ID zurückholen: pct restore 999 /mnt/pve/ext-hdd01/dump/vzdump-lxc-102-*.tar.zst --storage local-lvm pct start 999 # läuft er? dann wieder weg: pct stop 999 && pct destroy 999 # einen tank-pfad testweise restoren: restic -r /mnt/pve/ext-hdd01/restic-tank restore latest --target /tmp/rtest --include /tank/ ls -la /tmp/rtest/tank/ ``` --- ## schritt 5 — wipe-freigabe (erst wenn ALLES grün) - [ ] vzdump aller 18 Gäste auf ext-hdd01 vorhanden - [ ] Tank-Restic auf ext-hdd01 **und** Hetzner, `restic check` ok - [ ] DB-/Mail-Dumps vorhanden und im Backup enthalten - [ ] je 1 Container- **und** 1 Tank-Restore erfolgreich getestet - [ ] DKIM-Keys + DNS-Records notiert - [ ] beim Reinstall wird **ext-hdd01 NICHT** als Ziel gewählt --- ## schritt 6 — nach dem rebuild: reihenfolge 1. Proxmox neu auf NVMe, **ZFS-root (rpool)** — nur NVMe als Ziel. 2. `tank` neu als Mirror + Datasets/Quotas nach Manifest. 3. ext-hdd01 wieder mounten. 4. Tank-Daten per `restic restore` zurück in die frischen Datasets. 5. Container/VMs aus vzdump zurück: `pct restore --storage ...` bzw. `qmrestore ` für die VMs. Dabei kannst du gleich auf das neue Manifest-Schema umnummerieren. 6. **mailserver zuletzt** und mit Ruhe; DKIM/DNS prüfen, Testmail. 7. PBS + sanoid + Restic als laufendes System einrichten (permanentes Backup).