📄 Zsync Einrichtung - 1 oder 2 Platten

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:

  1. Alte Platte sauber exportieren (siehe Abschnitt unten)
  2. 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)

  1. Pool importieren – backup_usb_pool01 bzw. 02 wird gesucht und importiert
  2. Disk-Info loggen – Gerät, Interface, Größe, SMART-Werte (Temperatur, Laufzeit, Reallocated Sectors)
  3. Zsync Replikation – bashclub-zsync -d -c /etc/bashclub/push_usb01.conf bzw. 02
  4. Pool-Status loggen – nach der Replikation
  5. CheckZFS (CheckMK) – Ergebnis nach /var/lib/check_mk_agent/spool/90000_checkzfs_backup_usb_pool01 bzw. 02
  6. CheckZFS (HTML + Mail) – Report gespeichert, Mail an wartung@dimait.de
  7. 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