first commit
This commit is contained in:
@@ -0,0 +1,268 @@
|
||||
# pvesnap — automatische Snapshots für Proxmox VE
|
||||
|
||||
Ein systemd-Dienst, der nach frei definierbaren Zeitplänen Snapshots von VMs und
|
||||
Containern anlegt und alte Snapshots nach einer einstellbaren Vorhaltezeit wieder
|
||||
löscht. Alles wird über **eine INI-Datei** gesteuert, die sich auch bequem in einem
|
||||
**ncurses-Editor** bearbeiten lässt.
|
||||
|
||||
* Beliebig viele **Gruppen** — z. B. „diese VMs stündlich, jene täglich, der Rest monatlich“
|
||||
* **VM-Auswahl** nach VMID, Name (mit `*`-Mustern), Tag, Pool oder einfach „alle“
|
||||
* **Vorhaltezeit** je Gruppe nach Anzahl *und/oder* Alter
|
||||
* Jeder Snapshot bekommt eine **Beschreibung**, an der er sich wiedererkennen lässt
|
||||
* Läuft cluster-weit (alle Nodes) über `pvesh`
|
||||
* Nur Python-Standardbibliothek — keine zusätzlichen Pakete nötig
|
||||
|
||||
---
|
||||
|
||||
## Installation
|
||||
|
||||
Auf dem Proxmox-Host als root:
|
||||
|
||||
```bash
|
||||
git clone <dieses-repo> pvesnap && cd pvesnap
|
||||
./install.sh
|
||||
```
|
||||
|
||||
Das Skript legt an:
|
||||
|
||||
| Pfad | Inhalt |
|
||||
|---|---|
|
||||
| `/usr/lib/pvesnap/` | Programmcode |
|
||||
| `/usr/local/bin/pvesnap` | Startbefehl |
|
||||
| `/etc/pvesnap/pvesnap.conf` | Konfiguration (wird bei Updates **nicht** überschrieben) |
|
||||
| `/var/lib/pvesnap/state.json` | merkt sich die letzten Läufe |
|
||||
| `/etc/systemd/system/pvesnap.service` | systemd-Unit |
|
||||
|
||||
In der mitgelieferten Beispielkonfiguration sind alle Gruppen auf `enabled = no`
|
||||
gesetzt — es passiert also erst etwas, wenn du eine Gruppe aktivierst.
|
||||
|
||||
**Deinstallation:**
|
||||
|
||||
```bash
|
||||
./uninstall.sh # Programm und Dienst entfernen, Konfiguration bleibt
|
||||
./uninstall.sh --purge # zusätzlich /etc/pvesnap und /var/lib/pvesnap löschen
|
||||
```
|
||||
|
||||
Bereits angelegte Snapshots werden dabei **nie** angerührt.
|
||||
|
||||
---
|
||||
|
||||
## Konfiguration im ncurses-Editor
|
||||
|
||||
```bash
|
||||
pvesnap config
|
||||
```
|
||||
|
||||
* **Gruppenliste** — `Enter` bearbeiten, `n` neu, `c` kopieren, `d` löschen,
|
||||
`Leertaste` an/aus, `g` globale Einstellungen, `v` Übersicht welche VM in
|
||||
welcher Gruppe landet, `s` speichern, `q` Ende
|
||||
* **Gruppe bearbeiten** — Feld auswählen, `Enter` ändern, `Leertaste` umschalten.
|
||||
Ganz unten steht live, auf wie viele Gäste die Auswahl gerade zutrifft.
|
||||
* **VM-Auswahl** (`v`) — Liste aller VMs und Container mit Node, Status und Tags;
|
||||
`Leertaste` auswählen, `a` alle, `n` keine, `i` umkehren, `/` filtern,
|
||||
`Enter` übernehmen.
|
||||
|
||||
> Beim Speichern wird die INI-Datei neu geschrieben. Eigene Kommentare und ein
|
||||
> `[defaults]`-Abschnitt gehen dabei verloren (die Werte bleiben inhaltlich
|
||||
> erhalten, sie stehen danach in jeder Gruppe einzeln). Eine Sicherung wird als
|
||||
> `pvesnap.conf.bak` abgelegt.
|
||||
|
||||
---
|
||||
|
||||
## Konfiguration von Hand
|
||||
|
||||
```ini
|
||||
[global]
|
||||
prefix = auto # Namenspräfix aller pvesnap-Snapshots
|
||||
check_interval = 60s # wie oft der Dienst nach Fälligem schaut
|
||||
state_file = /var/lib/pvesnap/state.json
|
||||
log_level = INFO
|
||||
task_timeout = 15m
|
||||
run_on_start = no # beim Start sofort einen Durchlauf machen?
|
||||
dry_run = no # yes = nichts wirklich tun, nur protokollieren
|
||||
description = pvesnap | Gruppe: {group} | erstellt: {datetime} | Vorhaltezeit: {keep_time}
|
||||
|
||||
[defaults] # Vorgaben für alle Gruppen (optional)
|
||||
skip_stopped = no
|
||||
|
||||
[group:stündlich]
|
||||
interval = 1h
|
||||
align = yes # an der Uhr ausrichten: 00:00, 01:00, ...
|
||||
keep_count = 24 # höchstens 24 Snapshots je VM
|
||||
keep_time = 2d # nichts älter als 2 Tage
|
||||
tags = stuendlich # alle VMs mit diesem Tag
|
||||
skip_stopped = yes
|
||||
|
||||
[group:täglich]
|
||||
schedule = daily
|
||||
at = 02:30
|
||||
keep_count = 14
|
||||
keep_time = 21d
|
||||
names = web-*, db-*
|
||||
|
||||
[group:monatlich]
|
||||
schedule = monthly
|
||||
day_of_month = 1
|
||||
at = 04:00
|
||||
keep_count = 6
|
||||
all = yes
|
||||
exclude_tags = nosnap
|
||||
```
|
||||
|
||||
Nach jeder Änderung:
|
||||
|
||||
```bash
|
||||
pvesnap check # Konfiguration prüfen
|
||||
systemctl reload pvesnap # Dienst übernimmt die Änderung ohne Neustart
|
||||
```
|
||||
|
||||
### Zeitplan
|
||||
|
||||
Entweder ein Intervall …
|
||||
|
||||
```ini
|
||||
interval = 30m # 30m, 1h, 6h, 2d12h, 1w ...
|
||||
align = yes # yes: an der Uhr ausgerichtet (00:00, 00:30, 01:00, ...)
|
||||
# no: 30 Minuten nach dem letzten Lauf
|
||||
```
|
||||
|
||||
… oder ein fester Termin:
|
||||
|
||||
| `schedule` | zusätzliche Angaben | Beispiel |
|
||||
|---|---|---|
|
||||
| `hourly` | `minute = 15` | jede Stunde um :15 |
|
||||
| `daily` | `at = 02:30` | täglich um 02:30 |
|
||||
| `weekly` | `at`, `day_of_week = so` | sonntags um 03:00 |
|
||||
| `monthly` | `at`, `day_of_month = 1` | am 1. jedes Monats |
|
||||
| `yearly` | `at`, `day_of_month`, `month` | einmal jährlich |
|
||||
|
||||
`day_of_month = 31` wird in kürzeren Monaten automatisch auf den letzten Tag
|
||||
gezogen. Läuft der Host zum Termin nicht, wird der Lauf beim nächsten Start
|
||||
nachgeholt.
|
||||
|
||||
### Vorhaltezeit
|
||||
|
||||
```ini
|
||||
keep_count = 24 # höchstens 24 Snapshots je VM und Gruppe (0 = unbegrenzt)
|
||||
keep_time = 7d # nichts älter als 7 Tage (0 = unbegrenzt)
|
||||
keep_min = 1 # so viele bleiben in jedem Fall stehen
|
||||
```
|
||||
|
||||
Beides ist kombinierbar — gelöscht wird, was *eine* der beiden Grenzen reißt.
|
||||
Mindestens eine der beiden Angaben muss gesetzt sein, sonst würde die Zahl der
|
||||
Snapshots unbegrenzt wachsen (`pvesnap check` weist darauf hin).
|
||||
|
||||
### Welche VMs?
|
||||
|
||||
Alle Angaben wirken als **ODER**, Ausschlüsse gewinnen immer:
|
||||
|
||||
```ini
|
||||
all = yes # alle VMs und Container
|
||||
vmids = 100,101,105-110 # nach ID, auch Bereiche
|
||||
names = web-*, db-0? # nach Name, mit Platzhaltern
|
||||
tags = prod, wichtig # nach Proxmox-Tag
|
||||
pools = Kunden # nach Proxmox-Pool
|
||||
types = qemu # nur VMs (bzw. lxc = nur Container; leer = beides)
|
||||
|
||||
exclude_vmids = 999
|
||||
exclude_names = *-test
|
||||
exclude_tags = nosnap
|
||||
```
|
||||
|
||||
### Snapshot-Optionen
|
||||
|
||||
```ini
|
||||
vmstate = yes # RAM mitsichern (nur QEMU und nur bei laufender VM)
|
||||
skip_stopped = yes # gestoppte Gäste überspringen
|
||||
description = Sicherung von {name} ({vmid}) vom {date}
|
||||
```
|
||||
|
||||
Platzhalter der Beschreibung: `{group}` `{group_slug}` `{vmid}` `{name}` `{node}`
|
||||
`{type}` `{pool}` `{tags}` `{date}` `{time}` `{datetime}` `{timestamp}`
|
||||
`{keep_time}` `{keep_count}` `{schedule}`
|
||||
|
||||
---
|
||||
|
||||
## Namensschema und Sicherheit
|
||||
|
||||
```
|
||||
auto-taeglich-20260730-023000
|
||||
│ │ │ └── Uhrzeit
|
||||
│ │ └────────── Datum
|
||||
│ └──────────────────── Kurzname der Gruppe
|
||||
└─────────────────────────── prefix aus [global]
|
||||
```
|
||||
|
||||
pvesnap löscht **ausschließlich** Snapshots, deren Name exakt auf dieses Muster
|
||||
passt und deren Gruppen-Kurzname zur jeweiligen Gruppe gehört. Von Hand oder von
|
||||
anderen Werkzeugen angelegte Snapshots bleiben garantiert unangetastet.
|
||||
|
||||
Umlaute und Sonderzeichen im Gruppennamen werden für den Kurznamen umgeschrieben
|
||||
(`täglich` → `taeglich`). Wenn zwei Gruppen denselben Kurznamen ergäben, meldet
|
||||
das `pvesnap check`.
|
||||
|
||||
---
|
||||
|
||||
## Befehle
|
||||
|
||||
```bash
|
||||
pvesnap status # Übersicht: Gruppen, letzte und nächste Läufe
|
||||
pvesnap vms # alle VMs und die Gruppen, in denen sie stecken
|
||||
pvesnap list # vorhandene pvesnap-Snapshots (-a = auch fremde)
|
||||
pvesnap check # Konfiguration prüfen
|
||||
pvesnap config # ncurses-Editor
|
||||
|
||||
pvesnap run # jetzt fällige Gruppen ausführen
|
||||
pvesnap run --force -g täglich # eine Gruppe sofort ausführen
|
||||
pvesnap run --force --dry-run # Probelauf, ändert nichts
|
||||
pvesnap prune -g stündlich # nur aufräumen, keine neuen Snapshots
|
||||
|
||||
systemctl status pvesnap
|
||||
systemctl reload pvesnap # Konfiguration neu einlesen (SIGHUP)
|
||||
journalctl -u pvesnap -f # Protokoll mitlesen
|
||||
```
|
||||
|
||||
Ein manueller `pvesnap run` ist auch möglich, während der Dienst läuft — beide
|
||||
teilen sich eine Sperre und kommen sich nicht in die Quere.
|
||||
|
||||
Mit `-c /pfad/zur.conf` lässt sich jederzeit eine andere Konfiguration verwenden,
|
||||
z. B. zum Ausprobieren.
|
||||
|
||||
---
|
||||
|
||||
## Hinweise aus der Praxis
|
||||
|
||||
* **Snapshot ist kein Backup.** Snapshots liegen auf demselben Storage wie die VM.
|
||||
Für echte Sicherungen zusätzlich `vzdump` / Proxmox Backup Server verwenden.
|
||||
* **Speicherplatz:** Jeder Snapshot hält alte Blöcke fest. Bei schreibfreudigen
|
||||
VMs lieber kurze Vorhaltezeiten wählen und den Storage im Auge behalten.
|
||||
* **Nicht jedes Storage kann Snapshots** — LVM-thick und Verzeichnis-Storage mit
|
||||
`raw`-Images können es nicht. Solche VMs melden einen Fehler im Protokoll; die
|
||||
übrigen laufen normal weiter.
|
||||
* **`vmstate = yes`** friert die VM kurz ein und braucht Platz in Höhe des
|
||||
zugewiesenen RAM. Für regelmäßige Läufe meist unnötig.
|
||||
* **Gruppe umbenennen:** Der neue Name bekommt einen eigenen Kurznamen. Snapshots
|
||||
unter dem alten Namen werden dann nicht mehr automatisch aufgeräumt — vorher
|
||||
aufräumen lassen oder die alten Snapshots von Hand entfernen.
|
||||
* **Zeitumstellung:** Es wird mit lokaler Zeit gerechnet. Ein täglicher Termin um
|
||||
02:30 kann in der Umstellungsnacht ausfallen oder doppelt anstehen.
|
||||
|
||||
---
|
||||
|
||||
## Aufbau
|
||||
|
||||
```
|
||||
pvesnap/
|
||||
config.py INI lesen und schreiben, Gruppen- und Globaleinstellungen
|
||||
schedule.py Berechnung des nächsten Termins
|
||||
naming.py Namensschema und Beschreibungs-Vorlagen
|
||||
proxmox.py pvesh-Anbindung (Inventar, Snapshots anlegen/löschen)
|
||||
engine.py Auswahl der Gäste, Anlegen, Aufräumen
|
||||
daemon.py Hauptschleife, Signale, Sperren
|
||||
state.py merkt sich die letzten Läufe
|
||||
tui.py ncurses-Editor
|
||||
cli.py Kommandozeile
|
||||
config/pvesnap.conf.example
|
||||
systemd/pvesnap.service
|
||||
install.sh uninstall.sh
|
||||
```
|
||||
Reference in New Issue
Block a user