Wer merkt, dass ihm ein Laufwerk fehlt, merkt es genau dort - beim Blick auf "Transfer-Laufwerke: keine". Bisher schickte der Hinweistext ihn dafuer zwei Ebenen zurueck in die Uebersicht. Jetzt oeffnet v die Verwaltung direkt aus der Maske, und beim Zurueckkommen steht der Balken auf der Auswahlzeile - also da, wo man das eben Angelegte gleich anhaken will. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
961 lines
40 KiB
Markdown
961 lines
40 KiB
Markdown
# 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
|
||
|
||
Dazu drei Werkzeuge, um wieder **an die Daten im Snapshot** zu kommen:
|
||
|
||
* `pvesnap-explorer` — zwei Fenster im Terminal wie im Midnight Commander
|
||
* `pvesnap-web` — im Browser durchsehen und herunterladen, auch vom anderen Rechner
|
||
* `pvesnap-recovery` — den Snapshot als **laufende Maschine** starten, abgeschottet
|
||
ohne Netzwerk oder als vollwertige Wiederherstellung mit gleicher Identität
|
||
|
||
---
|
||
|
||
## Installation
|
||
|
||
Auf dem Proxmox-Host als root:
|
||
|
||
```bash
|
||
git clone <dieses-repo> pvesnap && cd pvesnap
|
||
./install.sh # nur der Snapshot-Dienst
|
||
./install.sh --with-webexplorer --port 8823 # zusätzlich die Web-Oberfläche
|
||
./install.sh --help # alle Optionen
|
||
```
|
||
|
||
| Option | |
|
||
|---|---|
|
||
| `--with-webexplorer` | Web-Oberfläche als Dienst einrichten (**erfordert `--port`**) |
|
||
| `--port <nummer>` | Port der Web-Oberfläche |
|
||
| `--bind <adresse>` | Adresse, auf der sie lauscht (Vorgabe `0.0.0.0`) |
|
||
| `--no-start` | installieren, aber Dienste nicht starten |
|
||
| `--force` | auch ohne erkanntes Proxmox VE installieren |
|
||
|
||
Das Skript legt an:
|
||
|
||
| Pfad | Inhalt |
|
||
|---|---|
|
||
| `/usr/lib/pvesnap/` | Programmcode |
|
||
| `/usr/local/bin/pvesnap` | Dienst und Konfiguration |
|
||
| `/usr/local/bin/pvesnap-explorer` | Zwei-Fenster-Explorer |
|
||
| `/usr/local/bin/pvesnap-web` | Web-Oberfläche |
|
||
| `/usr/local/bin/pvesnap-recovery` | Snapshot als Maschine starten |
|
||
| `/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 des Snapshot-Dienstes |
|
||
| `/etc/systemd/system/pvesnap-web.service` | Unit der Web-Oberfläche (nur mit `--with-webexplorer`) |
|
||
| `/etc/pvesnap/web.conf` | Port und Anmeldeart der Web-Oberfläche |
|
||
|
||
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, `r` Dienst neu laden, `q` Ende
|
||
* **`r` — Dienst neu laden**, ohne den Editor zu verlassen: entspricht
|
||
`systemctl reload pvesnap`. Ungespeicherte Änderungen werden vorher zum
|
||
Speichern angeboten, ein gestoppter Dienst zum Starten, und wenn das Neuladen
|
||
scheitert, wird ein Neustart angeboten. Nach `s` fragt der Editor ohnehin
|
||
gleich, ob neu geladen werden soll. Oben in der Kopfzeile steht jederzeit, ob
|
||
der Dienst läuft. (Braucht root — also `sudo pvesnap config`.)
|
||
* **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
|
||
retries = 2 # Wiederholungen, wenn eine Sperre belegt ist
|
||
retry_delay = 60s
|
||
pause_between = 0s # Pause zwischen zwei Gästen
|
||
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.
|
||
|
||
---
|
||
|
||
## Wenn Snapshots am Storage-Lock scheitern
|
||
|
||
```
|
||
trying to acquire cfs lock 'storage-data' ...
|
||
TASK ERROR: cfs-lock 'storage-data' error: got lock request timeout
|
||
```
|
||
|
||
`storage-data` ist dabei kein falsch gelesener Name — in pmxcfs heißen
|
||
Storage-Sperren immer `storage-<name>`, gemeint ist also das Storage `data`.
|
||
Proxmox nimmt diese Sperre beim Anlegen eines Snapshots und gibt nach 60 s auf,
|
||
wenn sie jemand anderes hält.
|
||
|
||
pvesnap geht damit so um:
|
||
|
||
* Der Aufruf wartet, bis der Snapshot-Task in Proxmox **wirklich fertig** ist,
|
||
bevor die nächste VM drankommt — sonst würden sich die Läufe gegenseitig
|
||
aussperren.
|
||
* Sperr-Fehler gelten als vorübergehend und werden `retries`-mal mit
|
||
`retry_delay` Abstand wiederholt. Echte Fehler (etwa „storage does not support
|
||
snapshots") werden **nicht** wiederholt.
|
||
* Mit `pause_between = 10s` lässt sich zusätzlich Druck vom Storage nehmen, wenn
|
||
viele VMs auf demselben Storage liegen.
|
||
|
||
### Der Dienst scheitert, von Hand geht es
|
||
|
||
Scheitert **jeder** Lauf des Dienstes am Storage-Lock, während derselbe Befehl
|
||
in der Shell funktioniert, liegt es an der Umgebung des Dienstes — nicht am
|
||
Storage. `pvesh` führt die Proxmox-API im eigenen Prozess aus, der Snapshot-Task
|
||
ist also ein *Kindprozess von pvesnap* und erbt alles, was in der systemd-Unit
|
||
eingeschränkt wurde.
|
||
|
||
Der Klassiker ist `ProtectSystem=` in der Unit: das hängt `/etc` schreibgeschützt
|
||
ein, und pmxcfs legt seine Sperren als Verzeichnisse unter `/etc/pve/priv/lock/`
|
||
an. Das `mkdir` scheitert, Proxmox wiederholt es erfolglos — und meldet am Ende
|
||
einen Lock-Timeout statt eines Rechtefehlers. Prüfen:
|
||
|
||
```bash
|
||
systemctl show pvesnap -p ProtectSystem -p ProtectHome -p PrivateTmp -p ReadOnlyPaths
|
||
pvesnap check # meldet so etwas von sich aus
|
||
```
|
||
|
||
Alle drei müssen leer bzw. `no` sein. Die mitgelieferte Unit enthält deshalb
|
||
bewusst **keine** Sandbox-Optionen.
|
||
|
||
### Wenn die Sperre wirklich belegt ist
|
||
|
||
Diese Kommandos helfen beim Eingrenzen:
|
||
|
||
```bash
|
||
pvesm status # ist das Storage online und erreichbar?
|
||
grep -A6 "^[a-z]*: data" /etc/pve/storage.cfg
|
||
pvesh get /cluster/tasks --output-format json | head # hängt noch ein Task?
|
||
systemctl status pvestatd pve-cluster
|
||
journalctl -u pvestatd -n 50
|
||
```
|
||
|
||
Häufigste Ursachen: ein hängender Backup- oder Replikationsjob auf demselben
|
||
Storage, ein nicht erreichbares NFS/CIFS-Storage (dann blockiert `pvestatd`),
|
||
oder ein abgebrochener Task, der die Sperre nicht freigegeben hat.
|
||
|
||
---
|
||
|
||
## Dateien aus einem Snapshot holen
|
||
|
||
Ein Snapshot ist kein Verzeichnis. Damit man hineinschauen kann, wird er
|
||
**schreibgeschützt** als Blockgerät eingebunden und gemountet — je nach Storage
|
||
unterschiedlich:
|
||
|
||
| Storage | Weg hinein |
|
||
|---|---|
|
||
| `rbd` (Ceph) | `rbd map pool/image@snap`, bei nicht unterstützten Image-Features `rbd-nbd` |
|
||
| `zfspool` | Container direkt über `.zfs/snapshot/…`, VMs über einen temporären Klon |
|
||
| `lvmthin`, `lvm` | die Snapshot-LV `snap_<volume>_<snapname>` aktivieren |
|
||
| `dir`, `nfs`, `cifs` | `qemu-nbd --load-snapshot` (nur qcow2) |
|
||
|
||
Danach werden Partitionen erkannt und mit `ro,noload` bzw. `ro,norecovery,nouuid`
|
||
gemountet — Snapshots laufender Gäste haben fast immer ein unsauberes Journal,
|
||
ohne diese Optionen würde der Kernel hineinschreiben wollen.
|
||
|
||
Aufgeräumt wird beim Beenden automatisch. Bleibt nach einem Absturz etwas
|
||
hängen:
|
||
|
||
```bash
|
||
pvesnap-explorer --cleanup
|
||
```
|
||
|
||
### `pvesnap-explorer` — zwei Fenster im Terminal
|
||
|
||
```bash
|
||
pvesnap-explorer # Gast und Snapshot auswählen
|
||
pvesnap-explorer 802 # Snapshot von VM 802 auswählen
|
||
pvesnap-explorer 802 <snapname> # direkt öffnen
|
||
pvesnap-explorer --local /srv/restore # rechtes Fenster startet dort
|
||
pvesnap-explorer --path /mnt/x # beliebiges Verzeichnis (zum Ausprobieren)
|
||
pvesnap-explorer --cleanup # hängengebliebene Einbindungen lösen
|
||
```
|
||
|
||
| Parameter | Vorgabe | Bedeutung |
|
||
|---|---|---|
|
||
| `vmid` | — | Gast direkt vorwählen |
|
||
| `snapshot` | — | Snapshot direkt vorwählen |
|
||
| `-l`, `--local <pfad>` | aktuelles Verzeichnis | Startverzeichnis im rechten Fenster |
|
||
| `-p`, `--path <pfad>` | — | beliebiges Verzeichnis öffnen, ohne Proxmox zu fragen |
|
||
| `--cleanup` | — | hängengebliebene Einbindungen lösen und beenden |
|
||
| `-v`, `--verbose` | — | ausführliches Protokoll |
|
||
|
||
Links der Snapshot, rechts der lokale Rechner:
|
||
|
||
| Taste | |
|
||
|---|---|
|
||
| `Tab` | Fenster wechseln |
|
||
| `Pfeiltasten`, `Enter` | bewegen, Verzeichnis öffnen oder Datei ansehen |
|
||
| `Backspace` | ein Verzeichnis hoch |
|
||
| `Leertaste` | markieren; `*` umkehren, `a` alle, `u` keine |
|
||
| `F5` / `c` | Markiertes ins andere Fenster kopieren |
|
||
| `F3` / `v` | Datei ansehen (Text oder Hex) |
|
||
| `F7` / `n` | neues Verzeichnis (nur lokal) |
|
||
| `F6` / `g` | Verzeichnis direkt eingeben |
|
||
| `F2` / `m` | anderes Dateisystem des Snapshots wählen |
|
||
| `F10` / `q` | eine Ebene zurück (Snapshot wird ausgehängt) |
|
||
|
||
Der Explorer hat drei Ebenen: **Gastauswahl → Snapshot-Auswahl → Dateien**. Mit
|
||
`q` geht es jeweils eine Ebene zurück; beim Verlassen des Dateibrowsers wird der
|
||
Snapshot wieder ausgehängt, sodass man gleich den nächsten öffnen kann. Das
|
||
rechte Fenster behält dabei sein Verzeichnis — praktisch, wenn man aus mehreren
|
||
Snapshots ins selbe Zielverzeichnis sammelt.
|
||
|
||
Kopiert wird immer vom aktiven ins andere Fenster — in den Snapshot hinein geht
|
||
nichts, er ist schreibgeschützt. Beim Kopieren gibt es einen Fortschrittsbalken,
|
||
`ESC` bricht ab; vorhandene Dateien werden abgefragt (`ja` / `nein` / `alle` /
|
||
`keine`). Gerätedateien und Sockets werden übersprungen, symbolische Verweise
|
||
bleiben Verweise.
|
||
|
||
### `pvesnap-web` — im Browser herunterladen
|
||
|
||
#### Als Dienst einrichten
|
||
|
||
```bash
|
||
./install.sh --with-webexplorer --port 8823
|
||
```
|
||
|
||
Danach läuft die Oberfläche dauerhaft auf `http://<host>:8823/` und startet mit
|
||
dem System. Ohne `--port` bricht das Skript ab — der Port hat keine sinnvolle
|
||
Vorgabe, die zu jedem Host passt.
|
||
|
||
```bash
|
||
./install.sh --with-webexplorer --port 8443 --bind 10.0.0.5 # nur auf einer IP
|
||
./install.sh --with-webexplorer --port 8823 --no-start # erst später starten
|
||
```
|
||
|
||
Alle Aufrufparameter des Dienstes stehen in **`/etc/pvesnap/web.conf`**:
|
||
|
||
```
|
||
PVESNAP_WEB_ARGS=--bind 0.0.0.0 --port 8823 --auth pve
|
||
```
|
||
|
||
Dort lässt sich alles nachträglich ändern — Port, Adresse, Anmeldeart, Rechte:
|
||
|
||
```bash
|
||
nano /etc/pvesnap/web.conf
|
||
systemctl restart pvesnap-web
|
||
```
|
||
|
||
Dienst verwalten:
|
||
|
||
```bash
|
||
systemctl status pvesnap-web # läuft er?
|
||
systemctl restart pvesnap-web # nach Änderungen in web.conf
|
||
systemctl stop pvesnap-web # anhalten (hängt offene Snapshots aus)
|
||
systemctl disable pvesnap-web # nicht mehr automatisch starten
|
||
journalctl -u pvesnap-web -f # Protokoll, auch fehlgeschlagene Anmeldungen
|
||
```
|
||
|
||
#### Von Hand starten
|
||
|
||
Für einen einmaligen Einsatz, ohne etwas zu installieren:
|
||
|
||
```bash
|
||
pvesnap-web # Gast und Snapshot im Browser wählen
|
||
pvesnap-web 802 # nur diesen Gast anbieten
|
||
pvesnap-web 802 autosnap-taeglich-20260731-023000 # Snapshot gleich öffnen
|
||
```
|
||
|
||
| Parameter | Vorgabe | Bedeutung |
|
||
|---|---|---|
|
||
| `-P`, `--port <nummer>` | `8823` | Port, auf dem gelauscht wird |
|
||
| `-b`, `--bind <adresse>` | `0.0.0.0` | Netzwerkadresse; `127.0.0.1` = nur lokal |
|
||
| `-a`, `--auth pve\|token\|none` | `pve` | Anmeldeart, siehe unten |
|
||
| `--require-privilege <recht>` | `VM.Snapshot` | nötiges Recht auf dem Gast |
|
||
| `--allow-user <user@realm>` | — | dieser Benutzer darf alles (mehrfach möglich) |
|
||
| `-t`, `--token <schlüssel>` | zufällig | Zugangsschlüssel selbst vorgeben |
|
||
| `--no-token` | — | Kurzform für `--auth none` |
|
||
| `-p`, `--path <verzeichnis>` | — | beliebiges Verzeichnis statt eines Snapshots |
|
||
| `--cleanup` | — | hängengebliebene Einbindungen lösen und beenden |
|
||
| `-v`, `--verbose` | — | ausführliches Protokoll |
|
||
| `-V`, `--version` | — | Version anzeigen |
|
||
|
||
Beispiele:
|
||
|
||
```bash
|
||
# Nur lokal lauschen, dazu vom Arbeitsplatz einen SSH-Tunnel legen
|
||
pvesnap-web --bind 127.0.0.1 --port 8823
|
||
# am eigenen Rechner: ssh -L 8823:localhost:8823 root@pve
|
||
# dann im Browser: http://localhost:8823/
|
||
|
||
# Ein Backup-Team soll ran, ohne Snapshot-Rechte zu haben
|
||
pvesnap-web --port 8823 --require-privilege VM.Backup
|
||
|
||
# Ein einzelner Dienstleister, unabhängig von den Proxmox-Rechten
|
||
pvesnap-web --port 8823 --allow-user dienstleister@pve
|
||
|
||
# Schnell etwas herausgeben, ohne Proxmox-Benutzer (Schlüssel in der Adresse)
|
||
pvesnap-web --port 8823 --auth token
|
||
|
||
# Ein beliebiges Verzeichnis freigeben, z. B. ein bereits gemountetes Backup
|
||
pvesnap-web --path /mnt/restore --port 8823
|
||
|
||
# Nach einem Absturz aufräumen
|
||
pvesnap-web --cleanup
|
||
```
|
||
|
||
Mit `pvesnap-web --help` gibt es dieselbe Übersicht im Terminal.
|
||
|
||
**Anmeldung mit den Proxmox-Benutzern.** Die Oberfläche zeigt dieselbe
|
||
Anmeldemaske wie Proxmox — Benutzername, Passwort, Realm-Auswahl. Geprüft wird
|
||
über `POST /access/ticket` auf der lokalen Proxmox-API, also genau den Weg, den
|
||
auch das Proxmox-Webinterface geht. Alle Realms (`pam`, `pve`, LDAP, AD …)
|
||
funktionieren damit automatisch. Zwei-Faktor-Anmeldungen werden abgewiesen statt
|
||
halb durchgewinkt.
|
||
|
||
**Wer darf was sehen?** Ein gültiges Passwort allein reicht nicht — sonst könnte
|
||
jeder Proxmox-Benutzer sämtliche Dateien aller Gäste lesen. Zusätzlich muss der
|
||
Benutzer auf dem jeweiligen Gast das Recht **`VM.Snapshot`** besitzen (geprüft
|
||
auf `/`, `/vms`, `/vms/<id>` und dem Pool des Gastes). In der Gastliste tauchen
|
||
nur Gäste auf, für die das zutrifft; `root@pam` sieht wie in Proxmox alles.
|
||
Anpassen mit:
|
||
|
||
```
|
||
--require-privilege VM.Backup # anderes Recht verlangen
|
||
--allow-user backup@pve # einzelne Benutzer generell zulassen
|
||
--auth token # stattdessen Schlüssel in der Adresse
|
||
--auth none # ohne Anmeldung (nur im vertrauten Netz)
|
||
```
|
||
|
||
Ohne Proxmox (`--path`) gibt es keine Benutzer — dort wird automatisch ein
|
||
Zugangsschlüssel erzeugt und beim Start als Adresse ausgegeben.
|
||
|
||
**Bedienung:** Snapshot anklicken, durchklicken; **einzelne Dateien** werden
|
||
direkt heruntergeladen, **Verzeichnisse und Mehrfachauswahl** als ZIP (im Strom
|
||
erzeugt, es wird nichts zwischengespeichert).
|
||
|
||
Zur Sicherheit:
|
||
|
||
* Es wird ausschließlich **gelesen**. Die Oberfläche kann nichts ändern oder
|
||
löschen.
|
||
* Pfade außerhalb des eingebundenen Snapshots werden abgewiesen — über die
|
||
Adresszeile kommt man nicht an den Rest des Hosts.
|
||
* Fehlgeschlagene Anmeldungen landen mit Absender-IP im Journal
|
||
(`journalctl -u pvesnap-web`).
|
||
* Die Verbindung ist unverschlüsseltes HTTP — Passwörter gehen im Klartext über
|
||
das Netz. Über unsichere Netze deshalb besser einen SSH-Tunnel legen:
|
||
`ssh -L 8823:localhost:8823 root@pve`, dazu in `web.conf`
|
||
`--bind 127.0.0.1` setzen.
|
||
|
||
Beim Beenden (`Strg-C` oder `systemctl stop pvesnap-web`) wird ein offener
|
||
Snapshot wieder ausgehängt.
|
||
|
||
---
|
||
|
||
## Einen Snapshot als Maschine starten — `pvesnap-recovery`
|
||
|
||
Manchmal reicht es nicht, einzelne Dateien herauszukopieren. Eine Datenbank zum
|
||
Beispiel liegt im Snapshot als Haufen halbfertiger Dateien — brauchbar wird sie
|
||
erst, wenn der Datenbankserver läuft und selbst einen Dump schreibt. Genau dafür
|
||
ist `pvesnap-recovery` da: Es startet den Snapshot als **eigenständige Maschine**,
|
||
ohne das Original anzufassen.
|
||
|
||
Zwei Betriebsarten:
|
||
|
||
| | **live** | **recovery** |
|
||
|---|---|---|
|
||
| Netzwerk | keins | volles Netz |
|
||
| Identität | bleibt (UUID, MACs, Hostname) | bleibt (UUID, MACs, Hostname) |
|
||
| Wofür | hineinschauen, Dump ziehen, Daten holen | die Maschine wirklich wieder in Betrieb nehmen |
|
||
| Risiko | keins — sie kann nichts erreichen | hoch, solange das Original läuft |
|
||
|
||
Bedient wird das Ganze mit `pvesnap-recovery` (ncurses-Oberfläche mit Übersicht
|
||
und Assistent) oder direkt über Parameter.
|
||
|
||
### Warum das schnell geht
|
||
|
||
Die Datenträger werden nicht kopiert, sondern **geklont**. Auf Ceph/RBD, ZFS und
|
||
LVM-thin ist das ein Copy-on-Write-Klon: Er ist in Sekunden fertig, egal wie groß
|
||
die Platte ist, und belegt anfangs keinen zusätzlichen Platz. Eine 32-GB-Platte
|
||
war im Test nach **0,8 Sekunden** geklont.
|
||
|
||
Dafür wird `PVE::Storage::vdisk_clone` benutzt — dieselbe Funktion, die auch
|
||
Proxmox selbst für Klone verwendet, samt Cluster-Sperre auf dem Storage. Es wird
|
||
also nichts nachgebaut, was Proxmox schon kann.
|
||
|
||
> Auf Datei-Storages (`dir`, `nfs`, `cifs`) geht das nicht — dort lässt sich aus
|
||
> einem qcow2-internen Snapshot kein Klon ziehen. Für diese Storages bleibt der
|
||
> Weg über `pvesnap-explorer`.
|
||
|
||
**Beide Betriebsarten klonen gleich.** `live` und `recovery` unterscheiden sich
|
||
ausschließlich im Netzwerk und in den Sicherheitsabfragen — an den Datenträgern
|
||
ändert der Modus nichts. Es gibt keinen Vollkopie-Pfad.
|
||
|
||
Nachsehen lässt sich das jederzeit auf dem Host:
|
||
|
||
```bash
|
||
rbd -p <pool> ls -l | grep -E 'NAME|vm-<neue-id>' # Spalte PARENT
|
||
rbd -p <pool> du | grep -E 'NAME|vm-<neue-id>' # PROVISIONED gegen USED
|
||
```
|
||
|
||
Eine frisch geklonte 32-GB-Platte steht dort mit `PROVISIONED 32 GiB` und
|
||
`USED 80 MiB` — die 80 MiB sind alles, was der laufende Gast seither geschrieben
|
||
hat.
|
||
|
||
### Eigenständig machen — `flatten`
|
||
|
||
Ein Linked Clone hängt für immer am Quell-Snapshot. Für „mal reinschauen" ist
|
||
das ideal, für eine **dauerhaft übernommene** Maschine nicht:
|
||
|
||
* der Quell-Snapshot lässt sich nicht mehr löschen (die Vorhaltezeit scheitert
|
||
mit `snapshot is protected`)
|
||
* die Original-VM muss mitsamt ihrer Platte bestehen bleiben
|
||
* der Klon wächst mit jedem Schreibvorgang
|
||
|
||
Soll die Wiederherstellung bleiben, wird sie gelöst:
|
||
|
||
```bash
|
||
pvesnap-recovery flatten 9802
|
||
```
|
||
|
||
Dahinter steckt `rbd flatten` — die Daten aus dem Elternteil werden jetzt
|
||
wirklich in den Klon kopiert. Das dauert und belegt Platz, läuft aber im
|
||
laufenden Betrieb. Danach hängt die Maschine an nichts mehr, und der Schutz der
|
||
Quell-Snapshots wird automatisch aufgehoben, sodass die Vorhaltezeit wieder
|
||
durchkommt. In der Oberfläche liegt das auf der Taste `f`; die Detailansicht
|
||
zeigt an, ob eine Maschine noch am Snapshot hängt.
|
||
|
||
> **Nicht von `rbd du` täuschen lassen.** Die Zeile eines Snapshots zeigt nur
|
||
> dessen *Zuwachs*, nicht seinen Inhalt. Im Test stand `@handtest01` mit
|
||
> `USED 56 MiB` da — kopiert werden beim Flatten trotzdem über 8 GB, denn
|
||
> sichtbar ist an dieser Stelle der gesamte Inhalt der Kette
|
||
> (`<TOTAL> 14 GiB`). `pvesnap-recovery flatten` misst das deshalb vorher und
|
||
> nennt die Größe, bevor es losgeht.
|
||
|
||
**Vorher wird geprüft, ob der Platz reicht.** Läuft ein Ceph-Pool während des
|
||
Kopierens voll, blockiert er *alle* Schreibvorgänge — dann steht nicht nur das
|
||
Flatten, sondern jede VM auf diesem Storage, und selbst das Aufräumen wird
|
||
schwierig, weil Löschen ebenfalls ein Schreibvorgang ist. `flatten` bricht
|
||
deshalb ab, wenn weniger als das 1,15-fache des Bedarfs frei ist; `--force`
|
||
setzt sich darüber hinweg.
|
||
|
||
Schnell ist es, solange Platz da ist: 13 GB waren im Test in rund 70 Sekunden
|
||
kopiert.
|
||
|
||
**Die Maschine läuft dabei weiter — und bleibt voll beschreibbar.** `rbd flatten`
|
||
ist eine Online-Operation. Im Test blieb die VM über den gesamten Vorgang auf
|
||
`qmpstatus: running`, der QEMU-Monitor antwortete durchgehend, und die Uhr auf
|
||
der Konsole lief weiter (10:38 → 10:39, mit sichtbarer Bildschirmanimation) —
|
||
inklusive geladenem RAM-Zustand.
|
||
|
||
Auch Daten, die **während** des Abkoppelns geschrieben werden, überleben es.
|
||
Gemessen an einem Container, der durchgehend schrieb:
|
||
|
||
| | |
|
||
|---|---|
|
||
| vor dem Flatten geschrieben | 64 MB Zufallsdaten, SHA-256 danach **OK** |
|
||
| während des Flatten geschrieben | 192 MB Zufallsdaten, SHA-256 danach **OK** |
|
||
| Schreibvorgänge im Zeitfenster | 12, von 19:35:48 bis 19:36:10 (Flatten: 19:35:48–19:36:11) |
|
||
| Zustand des Gastes | durchgehend `running` |
|
||
|
||
Der Grund: `rbd flatten` füllt nur die Blöcke auf, die der Klon noch **nicht**
|
||
selbst besitzt. Was der Gast bereits geschrieben hat, gehört ihm — und wird
|
||
nicht überschrieben.
|
||
|
||
### Warum das kein „Live-Restore" ist, sondern besser
|
||
|
||
Beim Live-Restore des Proxmox Backup Servers liegt das Backup auf einem anderen
|
||
Medium: Die VM startet sofort, holt die Blöcke aber im Hintergrund übers Netz
|
||
nach und läuft bis dahin gebremst.
|
||
|
||
Hier wird **gar nichts nachgeladen**. Der Klon liegt im selben Pool und ist aus
|
||
Sicht des Gastes von Sekunde eins an vollständig — bei voller Geschwindigkeit.
|
||
Und weil Copy-on-Write nichts kopiert, ist er **unabhängig von der Größe** in
|
||
etwa einer Sekunde fertig:
|
||
|
||
```
|
||
Klon ~1 s egal ob 32 GB oder 2 TB
|
||
Start Sekunden mit RAM-Zustand sofort im laufenden Zustand
|
||
Arbeiten ab jetzt voll beschreibbar
|
||
flatten nebenher optional, im laufenden Betrieb
|
||
```
|
||
|
||
Bei einer 2-TB-VM wird also nicht stundenlang kopiert und dann gestartet —
|
||
gearbeitet wird ab der ersten Sekunde, das Abkoppeln läuft im Hintergrund mit.
|
||
`flatten` betrifft ausschließlich die *Abhängigkeit* vom Quell-Snapshot, nie
|
||
die Verfügbarkeit.
|
||
|
||
### Wenn außerhalb von pvesnap gelöscht wurde — `cleanup`
|
||
|
||
Wird eine Wiederherstellung in der Proxmox-Oberfläche entfernt statt mit
|
||
`destroy`, bleibt etwas liegen: der Klon selbst kann übrigbleiben, und der
|
||
Quell-Snapshot bleibt geschützt — die Vorhaltezeit scheitert dann dauerhaft
|
||
mit `snapshot is protected`.
|
||
|
||
```bash
|
||
pvesnap-recovery cleanup # zeigt Gefundenes, fragt, räumt auf
|
||
pvesnap-recovery cleanup --all # auch Datenträger ohne Elternteil
|
||
```
|
||
|
||
Gesucht wird nach Datenträgern der Form `vm-<id>-disk-N`, zu deren VMID es
|
||
**keine Konfigurationsdatei** unter `/etc/pve/nodes/*/` mehr gibt. Bewusst
|
||
nicht über `/cluster/resources`: Ein Gast auf einem abgemeldeten Node taucht
|
||
dort unter Umständen nicht auf — und dann würden die Platten einer lebenden
|
||
Maschine als verwaist gelten. Ohne Elternteil wird nichts von selbst entfernt,
|
||
und der Schutz eines Snapshots wird nur gelöst, wenn wirklich kein Klon mehr
|
||
daran hängt.
|
||
|
||
### Und wenn die Maschine nicht auf Ceph liegt?
|
||
|
||
Das ganze Thema „Abhängigkeit vom Quell-Snapshot" ist eine **Ceph-Eigenheit**.
|
||
Andere Storages verhalten sich anders:
|
||
|
||
| Storage | Klon aus Snapshot | Hängt am Quell-Snapshot? | `flatten` |
|
||
|---|---|---|---|
|
||
| `rbd` (Ceph) | `rbd clone`, sofort | **ja** — Snapshot wird geschützt und unlöschbar | nötig für den Dauerbetrieb |
|
||
| `lvmthin` | `lvcreate -s`, sofort | **nein** | nicht nötig |
|
||
| `zfspool` | `zfs clone`, sofort | ja | nicht möglich (nur `zfs send \| zfs recv`) |
|
||
| `lvm` (dick) | — | — | PVE kann dort gar keine Snapshots |
|
||
| `dir`, `nfs`, `cifs` | — | — | kein Klon aus qcow2-Snapshots möglich |
|
||
|
||
**LVM-thin ist in diesem Punkt sogar angenehmer als Ceph.** Ein Thin-Snapshot
|
||
ist ein eigenständiges Volume, das sich mit anderen nur die Blöcke im Pool
|
||
teilt — nachgemessen:
|
||
|
||
```
|
||
Belegung im Thin-Pool nach dem Klonen (256 MB Nutzdaten):
|
||
data <19.84g 1.26 % ← Pool hält die Daten nur EINMAL
|
||
snap_..._wdhtest 1.00g
|
||
vm-9998-disk-0 1.00g 25.00 % Klon
|
||
vm-9999-disk-0 1.00g 25.00 % Original
|
||
|
||
Quell-Snapshot löschen, während der Klon existiert → erlaubt
|
||
Original löschen → erlaubt
|
||
Prüfsumme des Klons danach → unverändert
|
||
```
|
||
|
||
Also: platzsparend geteilt **und** trotzdem frei löschbar. Es gibt dort weder
|
||
das Problem mit geschützten Snapshots noch etwas zu flatten — `flatten` meldet
|
||
solche Datenträger entsprechend als „nicht nötig".
|
||
|
||
Der Preis ist ein anderer: `lvmthin` ist **lokaler** Speicher. Die
|
||
Wiederherstellung muss auf demselben Node laufen wie das Original;
|
||
`pvesnap-recovery` prüft das und lehnt einen anderen Node ab. Mit Ceph ist sie
|
||
dagegen auf jedem Node des Clusters startbar.
|
||
|
||
Und ein Warnhinweis, der für Thin-Pools genauso gilt wie für Ceph: Läuft der
|
||
**Thin-Pool** voll, stehen alle Volumes darin. Überprovisionierung im Blick
|
||
behalten.
|
||
|
||
Bei **ZFS** hängt der Klon wie bei Ceph am Snapshot, aber `zfs promote` würde
|
||
die Abhängigkeit nur umdrehen statt auflösen. Echte Unabhängigkeit ginge dort
|
||
nur über eine Vollkopie per `zfs send | zfs recv` — das macht `flatten` nicht
|
||
und sagt es auch so.
|
||
|
||
### Der Arbeitsspeicher kommt mit
|
||
|
||
Enthält der Snapshot den Arbeitsspeicher (`vmstate`, in der Konfiguration
|
||
`snapshot_vmstate = yes`), wird der mitgenommen. Die Maschine **bootet dann
|
||
nicht**, sondern läuft genau dort weiter, wo sie beim Snapshot stand:
|
||
|
||
* kein Crash-Recovery, kein `fsck`, kein Journal-Rollback
|
||
* Datenbanken sind bereits offen und konsistent
|
||
* die Uhr im Gast steht auf dem Snapshot-Zeitpunkt
|
||
|
||
Im Test war das nachweisbar: Die Konsole zeigte 10:38 — die Uhrzeit des
|
||
Snapshots — während auf dem Host längst 11:24 war.
|
||
|
||
Damit das klappt, muss die Geräteausstattung exakt zum gespeicherten Zustand
|
||
passen. `pvesnap-recovery` sorgt selbst dafür:
|
||
|
||
* `vmgenid` und `smbios1` bleiben erhalten (fehlen sie, bricht das Laden mit
|
||
`Unknown savevm section or instance 'vmgenid'` ab)
|
||
* `runningmachine` und `runningcpu` aus dem Snapshot werden übernommen
|
||
* die Netzwerkkarte bleibt **vorhanden**, wird aber abgeklemmt (`link_down=1`)
|
||
statt entfernt — herausnehmen würde den Zustand unbrauchbar machen
|
||
* Transfer-Laufwerke werden erst **nach** dem Fortsetzen angesteckt (Hotplug),
|
||
weil der Gast in einem Zustand aufwacht, in dem es die Platte noch nicht gab
|
||
|
||
Ein Detail, das Proxmox nicht selbst meldet: Schlägt das Laden des
|
||
Arbeitsspeichers fehl, quittiert Proxmox den Start trotzdem mit `TASK OK` und
|
||
lässt die Maschine angehalten stehen. `pvesnap-recovery` liest das Task-Protokoll
|
||
mit, setzt die Maschine fort und sagt deutlich, wenn statt des RAM-Standes kalt
|
||
gebootet wurde.
|
||
|
||
Mit `--no-resume` lässt sich der Arbeitsspeicher bewusst weglassen.
|
||
|
||
### Daten hinein und wieder heraus — Transfer-Laufwerke
|
||
|
||
Ein wiederhergestellter Snapshot hat kein Netzwerk. Dafür gibt es
|
||
**Transfer-Laufwerke**: benannte Abbilddateien unter
|
||
`/var/lib/pvesnap/transfer/`, die du **in Ruhe vorher** anlegst und befüllst
|
||
und im Notfall nur noch aus einer Liste auswählst.
|
||
|
||
```
|
||
pvesnap-recovery
|
||
v Übersicht der Laufwerke (geht auch aus der Optionsmaske heraus)
|
||
n "dumps", 20G ← einmalig
|
||
Enter Commander: Werkzeuge hineinkopieren
|
||
q q
|
||
n Wiederherstellung, Snapshot wählen
|
||
Transfer-Laufwerke: [dumps] ← Leertaste
|
||
F10 läuft
|
||
...arbeiten... im Gast: Datenträger DUMPS
|
||
e auswerfen, am Host auslesen, wieder einklinken
|
||
h herunterfahren
|
||
v Enter Commander: Ergebnis abholen
|
||
```
|
||
|
||
Kein einziger Parameter. Auf der Kommandozeile ginge es auch:
|
||
`--transfer dumps`, mehrfach möglich.
|
||
|
||
| Eigenschaft | |
|
||
|---|---|
|
||
| Dateisystem | **exFAT** — Windows und Linux nativ, keine 4-GB-Grenze je Datei |
|
||
| Partition | GPT mit `msftdata`, damit Windows sofort einen Laufwerksbuchstaben vergibt |
|
||
| Bezeichnung | der Name in Großbuchstaben, z. B. `DUMPS` (max. 11 Zeichen) |
|
||
| Lebensdauer | überlebt jede Wiederherstellung — auch das Löschen der VM in der Weboberfläche |
|
||
|
||
**Warum eine Datei und kein Proxmox-Volume?** Ein Volume würde beim Entfernen
|
||
der Maschine mitgelöscht, auch aus der Weboberfläche heraus — die mühsam
|
||
vorbereitete Werkzeugsammlung wäre weg. Pfade überspringt PVE beim Zerstören
|
||
ausdrücklich (`return if $volid =~ m|^/|`). Angehängt wird über ein
|
||
Loop-Gerät, weil Proxmox als Pfad nur `/dev/…` akzeptiert.
|
||
|
||
**Host oder Gast, nie beides.** Zwei unabhängige Einhängungen desselben
|
||
Blockgeräts zerlegen das Dateisystem. Die Verwaltung lässt das nicht zu:
|
||
Anhängen wird abgelehnt, solange der Host es hält; Aushängen, solange ein Gast
|
||
darauf arbeitet; Löschen, solange es überhaupt in Benutzung ist.
|
||
|
||
**Bei Containern** ist es kein Blockgerät, sondern ein durchgereichtes
|
||
Verzeichnis. Host und Container sehen dieselben Dateien **gleichzeitig** —
|
||
dort gibt es nichts auszuwerfen und nichts zu warten.
|
||
|
||
### Im laufenden Betrieb wechseln
|
||
|
||
Taste `e` in der Detailansicht zieht das Laufwerk bei laufender Maschine ab
|
||
und gibt es wieder hinein — beliebig oft:
|
||
|
||
```
|
||
auswerfen → gehört wieder dem Host, einhängen und befüllen
|
||
einklinken → zurück in denselben Steckplatz, VM läuft durchgehend
|
||
```
|
||
|
||
> **Im Gast vorher aushängen.** Unter Linux `umount`, unter Windows
|
||
> „Auswerfen" im Explorer. Proxmox meldet das Gerät zwar ordentlich ab, aber
|
||
> ein Dateisystem, auf das gerade geschrieben wird, nimmt das übel. Hält der
|
||
> Gast es fest, schlägt das Auswerfen mit einer entsprechenden Meldung fehl.
|
||
|
||
### An die Konsole kommen
|
||
|
||
```
|
||
https://<node>:8006/?console=kvm&novnc=1&vmid=9802&node=<node>&resize=off&cmd=
|
||
```
|
||
|
||
Diese Adresse gibt `pvesnap-recovery` nach dem Anlegen aus, ebenso
|
||
`pvesnap-recovery console <VMID>`. Es ist die ganz normale noVNC-Konsole von
|
||
Proxmox — die Maschine taucht auch in der Weboberfläche auf, markiert mit dem Tag
|
||
`pvesnap-recovery`. Bei Containern geht zusätzlich `pct enter <VMID>`.
|
||
|
||
### Wiederherstellung mit Netzwerk
|
||
|
||
```bash
|
||
pvesnap-recovery recover 802 autosnap-g5min-20260731-103800 --newid 9802
|
||
```
|
||
|
||
Hier bleibt alles erhalten, was die Maschine ausmacht: SMBIOS-UUID, `vmgenid`,
|
||
MAC-Adressen, bei Containern der Hostname. Für alles im Netz ist sie dieselbe
|
||
Maschine — inklusive Lizenzbindungen, AD-Mitgliedschaft und DHCP-Reservierungen.
|
||
|
||
**Genau deshalb ist sie gefährlich.** Zwei Maschinen mit derselben MAC und
|
||
derselben IP im selben Netz geben Chaos. `pvesnap-recovery` prüft deshalb
|
||
vorher, ob das Original läuft, und lässt sich in dem Fall nicht beiläufig
|
||
durchwinken:
|
||
|
||
| Situation | Verhalten |
|
||
|---|---|
|
||
| ncurses-Oberfläche | Zusammenfassung nur mit `j`, danach eine zweite Rückfrage, die den Grund beim Namen nennt |
|
||
| `recover …` im Terminal | das Wort **`ja`** muss ausgeschrieben werden — `j` reicht nicht |
|
||
| `recover … -y` | **wird abgewiesen** (Exit-Code 2). `-y` überspringt Routinefragen, nicht diese |
|
||
| `recover … --force` | läuft durch — die bewusste Entscheidung |
|
||
|
||
Das Original also **vorher stoppen** — oder mit `--net down` starten und die
|
||
Karte erst zuschalten, wenn klar ist, dass die Luft rein ist.
|
||
|
||
### Parameter
|
||
|
||
| Parameter | Bedeutung |
|
||
|---|---|
|
||
| `live <VMID> [snapshot]` | abgeschottet starten (ohne Snapshot: der neueste) |
|
||
| `recover <VMID> [snapshot]` | mit Netzwerk und gleicher Identität starten |
|
||
| `--newid <ID>` | VMID der neuen Maschine (Vorgabe: nächste freie) |
|
||
| `--node <name>` | auf welchem Node sie laufen soll |
|
||
| `--net none\|down\|on` | keine Karte / Karte ohne Leitung / voll am Netz |
|
||
| `--resume` / `--no-resume` | Arbeitsspeicher laden bzw. bewusst kalt starten |
|
||
| `--transfer <name>` | vorbereitetes Transfer-Laufwerk anhängen (mehrfach möglich) |
|
||
| `--memory <MB>`, `--cores <n>` | abweichende Ausstattung (nicht mit `--resume`) |
|
||
| `--name <name>` | Name der neuen Maschine |
|
||
| `--keep-binds` | durchgereichte Host-Verzeichnisse des Originals übernehmen |
|
||
| `--no-start` | nur einrichten, nicht starten |
|
||
| `-y`, `--yes` | Routinefragen überspringen (deckt `--force` **nicht** ab) |
|
||
| `--force` | auch anlegen, wenn das Original noch läuft |
|
||
|
||
| Befehl | Bedeutung |
|
||
|---|---|
|
||
| `pvesnap-recovery` | ncurses-Oberfläche mit Übersicht und Assistent |
|
||
| `list` | vorhandene Wiederherstellungen anzeigen |
|
||
| `start` / `stop` | hoch- bzw. herunterfahren |
|
||
| `console <VMID>` | noVNC-Adresse ausgeben |
|
||
| `flatten <VMID>` | vom Quell-Snapshot lösen (für den Dauerbetrieb) |
|
||
| `cleanup` | Klone entfernen, zu denen es keinen Gast mehr gibt |
|
||
| `destroy <VMID>` | restlos verwerfen |
|
||
|
||
### Was beim Verwerfen passiert
|
||
|
||
`destroy` räumt vollständig auf: Maschine stoppen, Gast samt aller Klone
|
||
entfernen, Austauschverzeichnis löschen — und den **Schutz der Quell-Snapshots
|
||
wieder aufheben**.
|
||
|
||
Dieser letzte Punkt ist wichtig: Ceph verlangt für einen Klon, dass der
|
||
Quell-Snapshot geschützt ist (`rbd snap protect`), und Proxmox setzt das beim
|
||
Klonen selbst. Bliebe der Schutz stehen, könnte die Vorhaltezeit diesen Snapshot
|
||
später nicht mehr löschen — im Protokoll stünde dann immer wieder
|
||
`snapshot is protected`. Solange eine Wiederherstellung existiert, ist ihr
|
||
Quell-Snapshot also bewusst unlöschbar; danach nicht mehr.
|
||
|
||
Zur Sicherheit fasst `destroy` nur Maschinen an, die den Tag `pvesnap-recovery`
|
||
tragen. Eine von Hand angelegte VM lässt sich damit nicht versehentlich löschen.
|
||
`uninstall.sh` warnt ebenfalls, wenn noch Wiederherstellungen offen sind.
|
||
|
||
---
|
||
|
||
## 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
|
||
preflight.py prüft die Umgebung (root, /etc/pve beschreibbar, /root)
|
||
cli.py Kommandozeile
|
||
curses_util.py gemeinsame curses-Bausteine
|
||
tui.py ncurses-Konfigurationseditor
|
||
snapfs.py Snapshots einbinden und mounten (rbd/zfs/lvm/qcow2)
|
||
explorer.py Zwei-Fenster-Explorer im Terminal
|
||
recovery.py Snapshot als Maschine starten (Klone, Konfiguration, Aufräumen)
|
||
recovery_ui.py ncurses-Oberfläche und Kommandozeile dazu
|
||
transfer.py Transfer-Laufwerke: anlegen, ein-/aushängen, Verriegelung
|
||
transfer_ui.py deren Bildschirm, auch aus dem Explorer erreichbar
|
||
web/ Web-Oberfläche zum Herunterladen
|
||
server.py HTTP-Server, ZIP im Strom, Zugangsschlüssel
|
||
assets.py Stylesheet und HTML-Gerüst
|
||
config/pvesnap.conf.example
|
||
systemd/pvesnap.service
|
||
install.sh uninstall.sh
|
||
```
|
||
|
||
Der Dienst (`pvesnap`) und die beiden Explorer teilen sich `proxmox.py`;
|
||
`snapfs.py` liefert beiden Oberflächen einen ganz gewöhnlichen Pfad, sodass
|
||
Explorer und Web-Oberfläche nichts über Ceph, ZFS oder LVM wissen müssen.
|