Zsync Einrichtung - 2 Platten
Zsync Erklärung - sowie unterschied zu dem normalen Proxmox Backup
bashclub-zsync ist ein Script, das ZFS-Datasets (also z. B. die virtuellen Festplatten eurer VMs) samt ihren Snapshots auf einen anderen ZFS-Speicher kopiert, etwa auf eine USB-Platte oder einen zweiten Server. Dabei wird nach der ersten Vollübertragung immer nur das übertragen, was sich seit dem letzten gemeinsamen Snapshot geändert hat, deshalb ist es sehr schnell und das Ziel ist eine fast identische, sofort startbare Kopie der Daten.
Der Unterschied zu einem normalen Backup (z. B. mit Proxmox Backup Server) ist: Ein PBS-Backup sichert jede VM als eigenständige, dedupliziert gespeicherte Sicherung mit vielen Ständen, die man gezielt wiederherstellen und prüfen kann, auch auf ganz anderer Hardware. zsync dagegen spiegelt die ZFS-Daten 1:1 und hängt an einer lückenlosen Snapshot-Kette, reißt die ab (z. B. weil eine USB-Platte zu lange nicht dran war), ist eine komplette Neuübertragung nötig. Deshalb ergänzen sich beide gut: zsync für eine schnelle, aktuelle Kopie, PBS für eine unabhängige, langfristige Datensicherung.
=> In unserer Nextcloud sind die Dateien zu finden: Nextcloud\Freigaben\DiMa\#PROXMOX ZSYNC\Zsync - 1 Platte\Zsync 2 Platten
Konzept
Zwei Platten werden wöchentlich im Wechsel eingesetzt — eine ist am Server, die andere liegt extern (Offsite).
- Woche 1 → Platte 01 anstecken → Backup läuft täglich → nächsten Montag tauschen
- Woche 2 → Platte 02 anstecken → Backup läuft täglich → nächsten Montag tauschen
Ist die jeweilige Platte nicht angesteckt → Fehler-Mail + Log-Eintrag, kein Absturz.
Dateien ablegen
/etc/bashclub/zsync_lib.sh
/etc/bashclub/push_usb01.conf
/etc/bashclub/push_usb02.conf
/etc/bashclub/bashclub-zsync_usb01
/etc/bashclub/bashclub-zsync_usb02
cp zsync_lib.sh /etc/bashclub/zsync_lib.sh
cp push_usb01.conf /etc/bashclub/push_usb01.conf
cp push_usb02.conf /etc/bashclub/push_usb02.conf
cp bashclub-zsync_usb01 /etc/bashclub/bashclub-zsync_usb01
cp bashclub-zsync_usb02 /etc/bashclub/bashclub-zsync_usb02
chmod +x /etc/bashclub/bashclub-zsync_usb01
chmod +x /etc/bashclub/bashclub-zsync_usb02
Abhängigkeiten installieren
apt install smartmontools mailutils
Hostnamen in beiden .conf-Dateien anpassen
hostname
Gibt den Hostnamen aus, z.B. GKZ01PVE01.
nano /etc/bashclub/push_usb01.conf
nano /etc/bashclub/push_usb02.conf
Inhalt push_usb01.conf:
target=backup_usb_pool01/repl/GKZ01PVE01
source=root@localhost
sshport=22
tag=bashclub:zsync
snapshot_filter="daily"
min_keep=3
zfs_auto_snapshot_keep=0
zfs_auto_snapshot_label=backup
Inhalt push_usb02.conf:
target=backup_usb_pool02/repl/GKZ01PVE01
source=root@localhost
sshport=22
tag=bashclub:zsync
snapshot_filter="daily"
min_keep=3
zfs_auto_snapshot_keep=0
zfs_auto_snapshot_label=backup
GKZ01PVE01 in beiden Dateien durch den eigenen Hostnamen ersetzen.
# 1. Wirkungslose max_age-Zeilen aus den push-Configs entfernen:
sed -i '/^checkzfs_max_age=/d' /etc/bashclub/push_usb01.conf
sed -i '/^checkzfs_max_age=/d' /etc/bashclub/push_usb02.conf
# 2. Threshold im Skript korrigieren (Werte in MINUTEN: 2880=48h WARN / 10080=7 Tage CRIT):
sed -i 's/--threshold 240,336/--threshold 2880,10080/g' /etc/bashclub/zsync_lib.sh
# 3. Kontrolle:
echo "=== push-Configs (sollte leer sein) ==="
grep max_age /etc/bashclub/push_usb01.conf /etc/bashclub/push_usb02.conf
echo "=== Skript (beide Zeilen sollten 2880,10080 zeigen) ==="
grep -n 'threshold' /etc/bashclub/zsync_lib.sh
🔌 USB-Platten identifizieren
Platte anstecken, dann:
lsblk -o NAME,SIZE,TRAN,MODEL,SERIAL | grep -E "NAME|usb"
Beispielausgabe:
NAME SIZE TRAN MODEL SERIAL
sdf 2.0T usb Samsung_T7 S12345 ← USB-Platte 01
sdg 4.0T usb WD_MyPassport W98765 ← USB-Platte 02
Nur Geräte mit TRAN=usb verwenden. Den Gerätenamen (sdf, sdg) für den nächsten Schritt notieren.
ZFS-Pools einrichten (einmalig, je Platte einmal)
Achtung: Alle Daten auf der jeweiligen USB-Platte werden gelöscht!
Platte 01 angesteckt:
HOSTNAME=$(hostname)
zpool create backup_usb_pool01 /dev/sdf
zfs create -o com.sun:auto-snapshot=false "backup_usb_pool01/repl"
zfs create -o com.sun:auto-snapshot=false "backup_usb_pool01/repl/$HOSTNAME"
Platte 01 exportieren, Platte 02 anstecken:
synczpool export -f backup_usb_pool01
Gerätenamen der Platte 02 prüfen:
lsblk -o NAME,SIZE,TRAN,MODEL,SERIAL | grep -E "NAME|usb"
Platte 02 einrichten:
zpool create backup_usb_pool02 /dev/sdg
zfs create -o com.sun:auto-snapshot=false "backup_usb_pool02/repl"
zfs create -o com.sun:auto-snapshot=false "backup_usb_pool02/repl/$HOSTNAME"
sync
zpool export -f backup_usb_pool02
ZFS-Markierungen setzen
zfs set bashclub:zsync=all store01
zfs set bashclub:zsync=all rpool/pveconf
Setzt die Eigenschaft, die zsync mitteilt welche Datasets gesichert werden sollen. Nur einmal nötig, gilt für beide Pools.
zfs get bashclub:zsync store01 rpool/pveconf
Erwartete Ausgabe:
NAME PROPERTY VALUE SOURCE
store01 bashclub:zsync all local
rpool/pveconf bashclub:zsync all local
Snapshots prüfen
zfs list -t snapshot -r store01
zfs list -t snapshot -r rpool/pveconf
Mögliche Ergebnisse:
- ✅ Snapshots werden angezeigt → weiter mit Crontab
- ❌ Keine Ausgabe → manuell anlegen:
zfs snapshot -r rpool@daily-2026-06-03
zfs snapshot -r store01@daily-2026-06-03
Datum auf das aktuelle Datum anpassen (Format YYYY-MM-DD).
Crontab einrichten
crontab -e
Einträge einfügen:
0 20 * * * /etc/bashclub/bashclub-zsync_usb01
0 21 * * * /etc/bashclub/bashclub-zsync_usb02
Beide Skripte laufen täglich. Ist die jeweilige Platte nicht angesteckt → Fehler-Mail + Log-Eintrag, das andere Skript läuft normal weiter.
Wochenwechsel jeden Montag:
- Alte Platte sauber exportieren (siehe Abschnitt unten)
- Neue Platte anstecken — fertig, der Crontab erkennt automatisch welcher Pool verfügbar ist
crontab -l
Prüft ob beide Einträge korrekt gesetzt sind.
Testlauf starten
Platte 01 anstecken:
/etc/bashclub/bashclub-zsync_usb01
tail -f /var/log/bashclub-zsync_backup_usb_pool01.log
Platte 01 abziehen (sauber!), Platte 02 anstecken:
sync
zpool export -f backup_usb_pool01
/etc/bashclub/bashclub-zsync_usb02
tail -f /var/log/bashclub-zsync_backup_usb_pool02.log
Mögliche Ergebnisse am Ende des Logs:
- ✅ Exit: 0 → Backup erfolgreich, Pool wurde exportiert
- ❌ Exit: 1 oder ERROR → Fehler aufgetreten
Was die Skripte beim Lauf machen (Reihenfolge)
- Pool importieren – backup_usb_pool01 bzw. 02 wird gesucht und importiert
- Disk-Info loggen – Gerät, Interface, Größe, SMART-Werte (Temperatur, Laufzeit, Reallocated Sectors)
- Zsync Replikation – bashclub-zsync -d -c /etc/bashclub/push_usb01.conf bzw. 02
- Pool-Status loggen – nach der Replikation
- CheckZFS (CheckMK) – Ergebnis nach /var/lib/check_mk_agent/spool/90000_checkzfs_backup_usb_pool01 bzw. 02
- CheckZFS (HTML + Mail) – Report gespeichert, Mail an wartung@dimait.de
- Pool exportieren – sync + zpool export -f backup_usb_pool01 bzw. 02
Pool-Status prüfen
zpool status backup_usb_pool01zpool status backup_usb_pool02
Mögliche Zustände:
Status | Bedeutung |
|---|---|
ONLINE | Normal, Backup läuft durch |
DEGRADED | Backup läuft noch, aber Platte hat Fehler – Prüfung empfohlen |
SUSPENDED | Skript führt automatisch Clear + Export + Re-Import durch |
NOTFOUND | Pool nicht aktiv, wird importiert |
Log-Rotation
Das Skript rotiert das Log automatisch ab 10 MB:
Datei | Inhalt |
|---|---|
/var/log/bashclub-zsync_backup_usb_pool01.log | Aktuelles Log Platte 01 |
/var/log/bashclub-zsync_backup_usb_pool01.log.1–3 | Ältere Generationen |
/var/log/bashclub-zsync_backup_usb_pool02.log | Aktuelles Log Platte 02 |
/var/log/bashclub-zsync_backup_usb_pool02.log.1–3 | Ältere Generationen |
Erzeugte Dateien im Betrieb
Datei | Inhalt |
|---|---|
/var/log/bashclub-zsync_backup_usb_pool01.log | Haupt-Log Platte 01 |
/var/log/bashclub-zsync_backup_usb_pool02.log | Haupt-Log Platte 02 |
/var/log/checkzfs_backup_usb_pool01_last.html | Letzter HTML-Report Platte 01 |
/var/log/checkzfs_backup_usb_pool02_last.html | Letzter HTML-Report Platte 02 |
/var/lib/check_mk_agent/spool/90000_checkzfs_backup_usb_pool01 | CheckMK Spool Platte 01 |
/var/lib/check_mk_agent/spool/90000_checkzfs_backup_usb_pool02 | CheckMK Spool Platte 02 |
Pool sauber exportieren (USB-Platte abziehen / wöchentlicher Tausch)
Niemals einfach abziehen!
zpool iostat backup_usb_pool01 1
Warten bis READ und WRITE bei 0 stehen, dann Strg+C.
synczpool export -f backup_usb_pool01
Für Platte 02 entsprechend backup_usb_pool02.
Fehlersuche
Pool-Import fehlgeschlagen
zpool import -f backup_usb_pool01
Mögliche Ergebnisse:
- ✅ Kein Fehler → Pool importiert
- ❌ no such pool available → USB-Platte nicht angesteckt oder nicht erkannt
Pool SUSPENDED (Platte bei laufendem Backup abgezogen)
Das Skript führt das automatisch aus. Manuell:
zpool clear backup_usb_pool01
zpool export -f backup_usb_pool01
zpool import -f backup_usb_pool01
Für Platte 02 entsprechend backup_usb_pool02.
Fehler im Log suchen
grep -i "error\|warn" /var/log/bashclub-zsync_backup_usb_pool01.log | tail -20
grep -i "error\|warn" /var/log/bashclub-zsync_backup_usb_pool02.log | tail -20
Bei einer Neukonfiguration müssen alte Snapshots entfernt werden und der Job neu durchlaufen:
zpool import backup_usb_pool01
zpool import backup_usb_pool02
zfs list
->Nur anzeigen durch das -rnv
zfs destroy -rnv backup_usb_pool01/repl/<Target pfad>
->Nun das löschen wenn die richtigen Datasets ausgewählt sind
zfs destroy -rv backup_usb_pool01/repl/<Target pfad>
->Nur anzeigen durch das -rnv
zfs destroy -rnv backup_usb_pool02/repl/<Target pfad>
->Nun das löschen wenn die richtigen Datasets ausgewählt sind
zfs destroy -rv backup_usb_pool02/repl/<Target pfad>
Prüfen wie Mail
checkzfs \
--source localhost \
--filter '#store01/|#rpool/pveconf/' \
--replica "backup_usb_pool02/repl" \
--threshold 75,90 \
--output text
checkzfs \
--source localhost \
--filter '#store01/|#rpool/pveconf/' \
--replica "backup_usb_pool01/repl" \
--threshold 75,90 \
--output text