26 Kapitel in vier Teilen, in der Reihenfolge, in der man sie braucht: erst sichern, dann Dateien holen, dann ganze Maschinen wiederherstellen, dahinter der Nachschlagteil. Gebaut wird mit MkDocs + Material. Bewusst ohne Netzabhaengigkeiten: keine Schriften vom CDN (font: false), Volltextsuche mit deutschem Stemming liegt neben den Seiten. Im Notfall steht vielleicht das halbe Netz - dann nuetzt eine Doku im Internet nichts. handbuch/bauen.sh baut handbuch/site/ handbuch/bauen.sh ansehen Vorschau auf 127.0.0.1:8000 install.sh nimmt das gebaute Handbuch mit nach /usr/share/doc/pvesnap/handbuch/ - falls es vorliegt. Auf dem Host selbst wird nichts gebaut, mkdocs gehoert nicht auf einen Hypervisor. Die 28 Bildschirmfotos sind nicht abfotografiert, sondern erzeugt: Der echte Programmcode laeuft in einem Pseudo-Terminal gegen einen erfundenen Proxmox-Host (Attrappen fuer pvesh, perl und rbd), pyte baut den Bildschirm nach, heraus faellt ein SVG. Damit stimmen sie garantiert mit dem Programm ueberein, sind reproduzierbar und enthalten keine echten Daten. Die Werkstatt dafuer liegt unter handbuch/werkstatt/ samt LIESMICH.md. Nebenbei: die Schlussmeldung von install.sh warb noch mit --exchange, das mit dem eingebauten Austauschlaufwerk weggefallen ist. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
1105 lines
46 KiB
Markdown
1105 lines
46 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
|
||
|
||
---
|
||
|
||
## Handbuch
|
||
|
||
Diese Datei ist die Kurzfassung. Ausführlich, mit Bildschirmfotos und
|
||
Volltextsuche, steht alles im **Handbuch** unter [`handbuch/`](handbuch/):
|
||
|
||
```bash
|
||
handbuch/bauen.sh # baut handbuch/site/ (reines HTML, ohne Netz nutzbar)
|
||
handbuch/bauen.sh ansehen # Vorschau auf http://127.0.0.1:8000/
|
||
```
|
||
|
||
`install.sh` nimmt das gebaute Handbuch mit auf den Host, nach
|
||
`/usr/share/doc/pvesnap/handbuch/index.html` — genau dort, wo man es im Notfall
|
||
braucht, ohne Netz und ohne Suchmaschine.
|
||
|
||
Die Bildschirmfotos werden aus dem echten Programmcode erzeugt, gegen einen
|
||
erfundenen Proxmox-Host; siehe [`handbuch/werkstatt/`](handbuch/werkstatt/).
|
||
|
||
---
|
||
|
||
## 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 |
|
||
| `--no-install-deps` | fehlende Werkzeuge (`parted`, `exfatprogs`) nicht nachinstallieren |
|
||
| `--force` | auch ohne erkanntes Proxmox VE installieren |
|
||
|
||
Läuft die Web-Oberfläche bereits, wird sie vor dem Austausch des Codes sauber
|
||
angehalten und danach wieder gestartet — sie könnte noch Snapshots eingebunden
|
||
haben. Nur wenn ein **fremder** Prozess auf dem Port sitzt, gibt es eine
|
||
Warnung samt PID.
|
||
|
||
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 |
|
||
| `/var/lib/pvesnap/transfer/` | Transfer-Laufwerke (Abbilddateien) |
|
||
| `/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 (auch aus Optionsmaske und Detailansicht)
|
||
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://172.0.4.1:8006/?console=kvm&novnc=1&vmid=9802&node=pvetest01&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>`.
|
||
|
||
> Vorne steht bewusst die **IP-Adresse**, nicht der Node-Name: Auf dem
|
||
> Proxmox-Host löst der Name auf, am Arbeitsplatz meist nicht. Sie kommt aus
|
||
> `/etc/pve/.members`. Der Node hinter `node=` bleibt der Name — so erwartet
|
||
> Proxmox ihn.
|
||
|
||
### Dongle und andere USB-Geräte — SPICE
|
||
|
||
Eine abgeschottete Maschine hat kein Netzwerk. Ein Software-Schutzmodul hängt
|
||
sonst an einem USB-Server im Netz — der ist damit unerreichbar.
|
||
|
||
SPICE löst das: Die USB-Weiterleitung kommt **vom Rechner des Bedieners**, nicht
|
||
über das Gastnetz. Die Maschine bleibt also abgeschottet und hat trotzdem ihren
|
||
Dongle.
|
||
|
||
```bash
|
||
pvesnap-recovery live 802 --usb 2 --no-resume
|
||
pvesnap-recovery spice 9802 -o vm.vv
|
||
scp root@172.0.4.1:vm.vv . && remote-viewer vm.vv
|
||
```
|
||
|
||
Im remote-viewer dann unter **USB-Geräteauswahl** das Gerät anhaken. In der
|
||
Oberfläche liegt das alles auf Taste `p` — auch nachträglich bei einer schon
|
||
laufenden Maschine.
|
||
|
||
**Guest-Tools braucht es dafür nicht.** Der Dongle taucht im Gast als
|
||
gewöhnliches USB-Gerät auf; QEMU und der SPICE-Client machen die Arbeit. Die
|
||
Tools (`tools/get-guest-tools.sh` holt virtio-win) sind nur für Zwischenablage,
|
||
automatische Auflösung und Mauszeiger.
|
||
|
||
Zwei Dinge, die man vorher wissen sollte:
|
||
|
||
**USB braucht SPICE.** Ohne `vga: qxl` legt QEMU die Weiterleitungen zwar an,
|
||
aber es gibt keinen Kanal, der sie transportiert (`no spice port`). `--usb`
|
||
schaltet die Anzeige deshalb automatisch mit ein.
|
||
|
||
**SPICE und geladener Arbeitsspeicher schließen sich aus** — je nachdem, was im
|
||
Original steht:
|
||
|
||
| Original | warmer RAM-Zustand | SPICE + Dongle |
|
||
|---|---|---|
|
||
| `vga: std` (Vorgabe) | ✅ | nur mit `--no-resume` |
|
||
| `vga: qxl` | ✅ | ✅ gleichzeitig |
|
||
|
||
`qxl` hat 64 MB Grafikspeicher, die Vorgabe 16. Der gespeicherte Zustand passt
|
||
dann nicht mehr, das Laden bricht mit `Size mismatch: vga.vram` ab — und die
|
||
Maschine bleibt angehalten stehen, während Proxmox `TASK OK` meldet.
|
||
`pvesnap-recovery` lehnt die Kombination deshalb ab und nennt die Auswege.
|
||
|
||
> **Für Produktivmaschinen:** Setz dort einmal `vga: qxl`. Dann tragen alle
|
||
> künftigen Snapshots es mit, und im Ernstfall gibt es warmen RAM-Zustand
|
||
> **und** Dongle gleichzeitig. Nachträglich lässt sich das bei einem
|
||
> vorhandenen Snapshot nicht mehr reparieren.
|
||
|
||
### Nachträglich umstellen
|
||
|
||
Taste `p` in der Detailansicht ändert SPICE und USB auch an einer bestehenden
|
||
Maschine:
|
||
|
||
| | |
|
||
|---|---|
|
||
| SPICE ein/aus | **Neustart nötig** — die Grafikkarte lässt sich im Betrieb nicht wechseln |
|
||
| USB dazu oder weg | sofort, solange der SPICE-Kanal schon steht |
|
||
|
||
Für den Neustart gibt es die Wahl — und zwar aus gutem Grund:
|
||
|
||
```
|
||
Wie soll VM 9802 neu starten?
|
||
Ich fahre im Gast herunter - pvesnap wartet und startet dann
|
||
Proxmox herunterfahren lassen (ACPI) - Windows blockt das oft
|
||
Gar nicht - spaeter selbst
|
||
```
|
||
|
||
**Der erste Weg ist der verlässliche.** ACPI klappt bei Linux, bei Windows
|
||
häufig nicht: Dort blockiert gern eine Anwendung den Vorgang, oder der Shutdown
|
||
Event Tracker fragt nach einem Grund. Wer im Gast selbst herunterfährt, umgeht
|
||
das. pvesnap zeigt dabei, was zu tun ist, verfolgt den Zustand und startet die
|
||
Maschine von selbst wieder, sobald sie aus ist:
|
||
|
||
```
|
||
Bitte jetzt IM GAST herunterfahren.
|
||
|
||
Windows Start -> Ein/Aus -> Herunterfahren
|
||
Linux poweroff bzw. shutdown -h now
|
||
|
||
Zustand: running seit 1:23
|
||
```
|
||
|
||
Abbrechen geht jederzeit mit `q` — die Maschine läuft dann weiter, und die
|
||
Änderung greift beim nächsten Start.
|
||
|
||
Ein Neustart **im Gast allein** hilft dagegen nicht: Dabei setzt sich nur die
|
||
Maschine zurück, der QEMU-Prozess läuft mit der alten Grafikkarte weiter. Es
|
||
braucht den Umweg über „aus und wieder an".
|
||
|
||
> Bei einer Maschine mit geladenem Arbeitsspeicher ist der nach einem Neustart
|
||
> **endgültig weg** — Proxmox gibt ihn schon beim ersten Start frei. Offene
|
||
> Programme und ungespeicherte Daten sind dann verloren.
|
||
|
||
### Herunterfahren
|
||
|
||
Taste `h` fährt sauber herunter und schaltet **nicht** von selbst hart ab.
|
||
Weigert sich der Gast — der Windows-Fall von oben —, kommt dieselbe Wahl:
|
||
|
||
| | |
|
||
|---|---|
|
||
| Im Gast selbst herunterfahren | pvesnap wartet und meldet, wenn sie aus ist |
|
||
| Hart ausschalten | wie Stecker ziehen, mit ausdrücklicher Bestätigung |
|
||
| Abbrechen | läuft weiter |
|
||
|
||
Ein stilles Abschalten nach Zeitablauf wäre ein Stromausfall mit Ansage — und
|
||
genau der Grund, warum ein Dateisystem hinterher unsauber ist.
|
||
|
||
### 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) |
|
||
| `--spice` | SPICE-Anzeige (`vga: qxl`), zusätzlich zu noVNC |
|
||
| `--usb <n>` | so viele USB-Weiterleitungen über SPICE (schaltet `--spice` mit ein) |
|
||
| `--iso <volid>` | Abbild als CD einlegen, z. B. `local:iso/virtio-win.iso` |
|
||
| `--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 |
|
||
| `spice <VMID>` | Verbindungsdatei für remote-viewer (`-o datei.vv`) |
|
||
| `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 (Taste v in pvesnap-recovery)
|
||
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 systemd/pvesnap-web.service
|
||
tools/get-guest-tools.sh holt virtio-win auf einen ISO-Storage
|
||
install.sh uninstall.sh
|
||
```
|
||
|
||
Alle vier Werkzeuge teilen sich `proxmox.py`. `snapfs.py` liefert Explorer und
|
||
Web-Oberfläche einen ganz gewöhnlichen Pfad, sodass sie nichts über Ceph, ZFS
|
||
oder LVM wissen müssen; `recovery.py` geht den anderen Weg und überlässt das
|
||
Klonen der Storage-Schicht von Proxmox selbst.
|