Proxmox-Backup nach restic: ResticBackup.sh und ResticRestore.sh
Zwei Bash-Skripte, eine gemeinsame config.cfg, ein restic-Repository auf einer externen Platte. Dedupliziert, verschlüsselt, ohne Umweg zurückspielbar – und einzelne Dateien erreichbar, ohne vorher hunderte Gigabyte auszupacken.Voraussetzung: bestehende Snapshots
Das Backupskript legt selbst keine ZFS-Snapshots an. Für ZFS-Volumes - VM-Disks wieLXC-rootfs - nimmt es immer den neuesten vorhandenen Snapshot des Datasets, sowohl für zfs send als auch als Lesequelle für RAW. Fehlt einer, wird die Platte übersprungen,statt ein verschmiertes Image zu schreiben (RAW_REQUIRE_SNAPSHOT). Ist er älter als 24Stunden, gibt es eine Warnung - gesichert wird genau dieser Stand.
Die Aktualität der Sicherung hängt damit am Snapshot-Mechanismus des Hosts: ein Cronjob mit cv4pve-autosnap oder die Snapshots von Proxmox selbst -Hauptsache, kurz vor dem Backuplauf entsteht einer.
Ausnahmen: auf LVM und LVM-thin legt das Skript selbst einen temporären Snapshot an und räumt ihn wieder ab, auf Directory-Storage wird live gelesen, ohne Konsistenzgarantie.
Sicherungsmedium
- Ziel wird über die UUID gesucht, nicht über einen festen Pfad; mehrere UUIDs = rotierende Medien
- Log hält fest, welche Platte lief, und warnt, wenn 30 Läufe lang immer dieselbe steckte
- nach dem Lauf fstrim, Standby (hdparm -y), unmount
Formate
- RAW (Standard): Volume blockweise als Image, aus ZFS- oder temporärem LVM-Snapshot. Jedes Backup steht für sich – keine Kette, Restore in einem Schritt
- zfs send (optional): pro Platte (ZFS_SEND_DISKS="100:scsi1") oder für alles. Full + Diffs; neues Full bei zu altem Full, fehlender Basis oder zu großem Diff. Spart Lese-I/O auf großen Datenplatten, braucht aber Platz für zwei Generationen – lohnende Kandidaten meldet der Lauf selbst
- Dateibasiert: LXC-rootfs über ro-Snapshot, LOCAL_DIRS, Maschinenconfigs
- Ein config-id-Tag klammert alles zusammen, was zu einem Lauf gehört – der Restore nimmt genau diese Platten
Platz
- Bedarf wird exakt gerechnet, nicht geschätzt: neues Backup = volle Quellgröße, vorhandenes = Aufschlag in Prozent; bei RAW zählt die echte Belegung
- reicht es nicht, werden ganze Backup-Tage freigegeben, alt nach neu: ein Full nimmt Diffs, Configs und immer-full-Volumes mit; neuestes Backup einer Gruppe und ZFS_SEND_DISKS bleiben
- Aufbewahrung über KEEP_DAILY/WEEKLY/MONTHLY plus prune
Integrität und Warnungen
- restic liest gespeicherte Chunks nie wieder – ein verrottetes Pack fiele nicht auf. Deshalb rotierendes Zurücklesen: nach RESTIC_CHECK_ROTATE_RUNS Läufen ist das Repo einmal komplett geprüft, Zähler pro Medium
- Warnungen ohne Abbruch: volle Host-Dateisysteme, lange Uptime, knapper Platz am Ziel
- Übersicht aller Backups samt Wiederherstellungsgröße am Ende, auch in der Mail
Restore
- --list mit Filtern (Maschine, Typ, Name, Lauf), optional mit Größe; --list-disks <VMID> für den Stand einer Maschine
- Restore nur mit explizitem --target auf eine freie ID – bestehende Maschinen werden nie überschrieben, bewusst ohne Override
- --machine = letzter Lauf, --date = letzter vor Stichtag, --snap = genau einer; Zielvolumes per pvesm alloc, Diffs ziehen ihr Full mit
Einzelne Dateien
- --mount <SNAP-ID>: Repo per FUSE, RAW-Image als ro-Loop-Device mit gemounteten Partitionen (LVM darin wird aktiviert), LXC/LOCAL direkt als Dateibaum. Kein zusätzlicher Plattenplatz
- --attach-raw <SNAP-ID> --vm <VMID>: für alles, was der Host nicht lesen kann (Windows, Storage Spaces, LUKS mit Schlüssel im Gast) – Image als SCSI-Platte in die laufende VM
- --rw schiebt einen qcow2-Overlay davor, den qemu-nbd als /dev/nbdN bereitstellt; Schreibvorgänge landen dort und werden verworfen, das Backup bleibt unberührt
- dieselbe VM geht mit: Windows hält die Kopie wegen doppelter Signatur offline, Rechtsklick auf den Datenträger → "Online" schreibt die neue Signatur in den Overlay
- Strg+C räumt vollständig auf; nach einem harten Abbruch holt --detach-raw das nach (VM-Config, Loop/nbd, FUSE-Mount, Overlay, Temp) – erkannt wird nur, was die Skripte selbst angelegt haben
Installation und Konfiguration
Abhängigkeiten:
Code:
apt install restic jq pv
Alle drei Dateien nach /usr/local/bin/ kopieren und .txt Endung entfernen.
Code:
chmod +x ResticBackup.sh
chmod +x ResticRestore.sh
UUID der ext. Festplatte herausfinden und in die /usr/local/bin/config.cfg eintragen.
Code:
blkid
Alle auskommentierten Parameter in der Restic Restore entsprechen dem optionalen Default.
Sicherung aller VMs, LXC Container und den optionalen zu sichernden LOCAL_DIRS durchführen:
Code:
./ResticBackup.sh
Sicherung von Maschine 115 durchführen:
Code:
./ResticBackup.sh 115
Restore
Code:
./ResticRestore.sh --help
# z.B.
./ResticRestore.sh --machine 115 --target 9115
Laufzeiten:
Code:
VM:
600 GB machine storage
300 GB used
5 GB diff per day
Backup-Storage: 930 GB
| Read I/O VM | Write I/O Backup | max Backup count | runtime
| 500 MB/s | 100 MB/s | on disk |
------------------------------------------------------------------------------------
VZDump | 600 GB | 250 GB * | | 42 min
------------------------------------------------------------------------------------
20-backup-sum | 12 TB | 5 TB | 2 ** | 840 min
RAW first time | 600 GB | 250 GB * | | 42 min
RAW following | 600 GB | 5 GB | | 20 min
------------------------------------------------------------------------------------
20-backup-sum | 12 TB | 345 GB | > 100 *** | 422 min
zfs_s 1. full | 300 GB | 300 GB * | | 50 min
zfs_s 1. diff | 5 GB | 5 GB | | 1 min
zfs_s 2. diff | 10 GB | 10 GB | | 2 min
zfs_s 3. diff | 15 GB | 15 GB | | 2.5 min
...
zfs_s 9. diff | 45 GB | 45 GB | | 7.5 min
zfs_s 2. full | 300 GB | 300 GB | | 50 min
zfs_s 10. diff | 5 GB | 5 GB | | 1 min
...
------------------------------------------------------------------------------------
20-backup-sum | 1.1 TB | 1.1 TB | 13 **** | 175 min
* 300 GB used storage can compress to approx 250 GB; if you store via zfs_send, further reduction is not possible
** I you use the prune process of VZdump, which only prune after backup your total number is 2.
You can increment this to 3 if you use your own prune process, which prune directly before creation
*** (930 - 250)/5 = 137, but you would not conserve 137 dailys,
so the difference between individual backups eventually become larger than 5 GB
****Initial you can add 17 backups, but worst case would be: 300+40+45+300+5+10+15+20+25+30+35+40+45 = 910 => 13 backups
Attachments
Last edited: