Enterprise-Backup-, Recovery-, Verification-, Security- und Monitoring-Plattform fuer Proxmox VE, Windows, Linux und Dateisysteme. Der Leitsatz, der fast jede Entscheidung erklaert: Ein Backup gilt erst als vertrauenswuerdig, wenn Integritaet geprueft und Wiederherstellbarkeit nachgewiesen wurde. Deshalb steigt ein Wiederherstellungspunkt erst nach einem tatsaechlich durchgefuehrten Restore-Test auf "recoverable", und Unbekanntes geht in keine Bewertung als "gut" ein. Umfang (Phasen 0-23): - Repository Engine: inhaltsadressierte Bloecke, atomares Commit-Protokoll, Katalogaufbau allein aus den Manifesten — ohne Datenbank - Backup Engine: inhaltsabhaengiges Chunking, Deduplizierung trotz Verschluesselung, zstd, AES-256-GCM, Streaming mit Gegendruck - Agenten fuer Windows und Linux mit Auftragsabholung (Pull-Modell) - Proxmox-Provider mit beiden Zugriffswegen auf die Sicherungsarchive - Scheduler, Recovery Engine mit Pruefpunkt, Verification, Unveraenderlichkeit - Weboberflaeche, Kennzahlen, Meldungen, Berichte, Security Center, Ransomware-Heuristik (meldet, handelt nie) - Disaster Recovery, Haertung, Leistungsmessung, Chaos Testing - Eingefrorene Vertraege fuer API, Migrationen, Backup-Format und Repository - Auslieferungspaket fuer linux/amd64, linux/arm64 und windows/amd64 Nicht enthalten und als solches gekennzeichnet: Kapazitaetsprognose, Backup Copy, Changed Block Tracking bei Proxmox, erweiterte Attribute und ACLs. Gebaut, aber nie auf echter Hardware gefahren: der Windows-Dienst, die systemd-Einheit und der verpflichtende Proxmox-Meilenstein — ob eine wiederhergestellte VM startet, ist ungeprueft. Einzelheiten in CHANGELOG.md und docs/release-candidate.md. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
9.0 KiB
Repository Engine
Dieses Dokument beschreibt den aktuell implementierten Stand nach Phase 2.
Leitgedanke
Ein Repository ist selbstbeschreibend. Es enthält alles, was zur Wiederherstellung nötig ist — PostgreSQL hält davon nur eine Kopie zur schnellen Abfrage.
Daraus folgt die Prüffrage für jede Designentscheidung: Bliebe das Repository nutzbar, wenn der Control Server und seine Datenbank ersatzlos verschwinden? Alles, was diese Frage mit Nein beantwortet, ist falsch — auch wenn es bequemer wäre.
Aufbau
repository/
format/ repository.json — Descriptor: Format, Verfahren, Betriebsart
manifests/ <backup-id>.manifest.json — die maßgebliche Beschreibung je Backup
chunks/ aa/bb/<sha256> — inhaltsadressierte Datenblöcke
indexes/ catalog.json — Übersicht (nur Beschleuniger, jederzeit neu erzeugbar)
journals/ <session>.journal.json — Fortschritt laufender Schreibvorgänge
verification/ scan-<zeit>.json — Ergebnisse der Integritätsläufe
metadata/ ergänzende Angaben
staging/ unfertige Daten bis zum Commit
repository.lock Schreibsperre
Chunk-Ablage
Die Kennung eines Chunks ist sein SHA-256-Inhaltshash. Daraus folgt unmittelbar:
- Deduplizierung ohne Index — gleicher Inhalt ergibt dieselbe Kennung und damit denselben Ablageort. Ein bereits vorhandener Chunk wird schlicht nicht erneut geschrieben.
- Integritätsprüfung ohne Zusatzdaten — beim Lesen wird neu gehasht und mit der Kennung verglichen. Eine separate Prüfsummenliste, die selbst beschädigt werden könnte, gibt es nicht.
Warum SHA-256: kryptografisch sicher (PROMPT.md §9), Teil der Standardbibliothek, auf allen Zielplattformen hardwarebeschleunigt. Eine Fremdbibliothek brächte hier keinen Vorteil, aber eine zusätzliche Abhängigkeit im sicherheitskritischsten Pfad des Produkts.
Fanout: chunks/aa/bb/<hash> — zwei Ebenen à zwei Hex-Zeichen ergeben 65 536 Verzeichnisse. Ohne diese Aufteilung lägen Millionen Dateien in einem einzigen Verzeichnis, was jede Suche unbrauchbar langsam macht.
Kennungen werden vor jeder Pfadbildung geprüft. Sie stammen aus Manifesten, die auch aus einem fremden Repository kommen können. Ohne Prüfung liesse sich über einen Wert wie ../../etc/passwd auf beliebige Pfade zugreifen.
Crash-sicheres Schreiben
Jede Datei entsteht in vier Schritten:
- In eine temporäre Datei im Zielverzeichnis schreiben (damit
renamekeine Dateisystemgrenze überschreitet und atomar bleibt). fsyncauf die Datei — erst danach liegen die Daten wirklich auf dem Datenträger.renameauf den Zielnamen — unter POSIX atomar.fsyncauf das Verzeichnis — erst danach überlebt auch der Namenseintrag einen Stromausfall.
Ohne Schritt 2 und 4 könnte nach einem Absturz eine Datei existieren, deren Inhalt leer oder unvollständig ist — ein beschädigtes Backup, das sich als vollständig ausgibt.
Commit-Protokoll
Sieben Schritte laut SYNCOVA_ARCHITECTURE.md §10:
| Schritt | Vorgang |
|---|---|
| 1 | Session öffnen, Journal anlegen |
| 2 | Chunks schreiben |
| 3 | Manifest erzeugen, Kennzahlen aus der Session übernehmen |
| 4 | Prüfsumme bilden und sofort gegenprüfen |
| 5 | Manifest atomar an seinen Platz bringen — hier wird das Backup sichtbar |
| 6 | Katalog fortschreiben |
| 7 | Erfolg melden |
Vor Schritt 5 existiert das Backup für keinen Leser. Bricht der Vorgang vorher ab, bleiben nur Chunks liegen — die ein späterer Lauf wiederverwendet. Es entsteht nie ein halbes, scheinbar gültiges Backup.
Schlägt Schritt 6 fehl, ist das Backup dennoch vollständig: der Katalog lässt sich jederzeit neu aufbauen. Das wird protokolliert, nicht als Fehler gemeldet.
Die Kennzahlen im Manifest stammen immer aus der Session, nie vom Aufrufer — erfundene Statistiken wären eine Falschaussage über gesicherte Daten.
Abschlussvermerk
Ein Manifest gilt nur mit complete: true und gültigem content_hash. Der Hash deckt alle Felder außer diesen beiden ab.
Fehlt der Vermerk oder passt der Hash nicht, liefert ReadManifest einen Fehler und der Katalog-Wiederaufbau überspringt das Backup. Ein unvollständiges Backup als wiederherstellbar auszuweisen wäre der schwerste denkbare Fehler dieses Produkts.
Katalog und Wiederaufbau
Der Katalog ist ausschließlich ein Beschleuniger. Er wird automatisch neu erzeugt, wenn er fehlt, unlesbar ist oder zu einem fremden Repository gehört (erkennbar an der Repository-Kennung).
Der Wiederaufbau liest ausschließlich die Manifeste — keine Datenbank, keine externe Quelle:
syncova-repo rebuild --path /backup/repository-01
Das ist der Kern der Repository-Wiederherstellung (PROMPT.md §46): Repository anhängen, Katalog aufbauen, wiederherstellen.
Integritätsprüfung
syncova-repo scan --path <pfad> # nur Anwesenheit prüfen (schnell)
syncova-repo scan --path <pfad> --deep # jeden Chunk neu hashen (vollständig)
Geprüft wird von den Manifesten aus, nicht von der Chunk-Ablage: nur so zeigt sich, ob ein Backup tatsächlich wiederherstellbar ist. Ein von mehreren Backups genutzter Chunk wird dabei nur einmal gelesen.
Der Bericht benennt betroffene Backups namentlich und liefert einen Exit-Status ungleich 0, damit ein Überwachungssystem anschlägt. Die Zusammenfassung beschönigt nichts: „n von m Backups sind NICHT vollständig wiederherstellbar."
Verwaiste Chunks sind eine Warnung, kein Datenverlust — sie belegen nur Speicherplatz.
Bereinigung
syncova-repo prune --path <pfad> # Simulation
syncova-repo prune --path <pfad> --apply # tatsächlich ausführen
Bewusst getrennt vom Scan, da potenziell datenzerstörend. Zwei Schutzmaßnahmen:
- Ist ein Manifest unlesbar, bricht die Bereinigung ab. Die Menge der benötigten Chunks wäre unbekannt; ein Löschen auf unvollständiger Grundlage könnte Daten vernichten.
- Sie verlangt die Schreibsperre. Liefe sie während eines Backups, hätte ein gerade abgelegter Chunk noch kein Manifest und würde als verwaist gelöscht.
Sperren
Eine Sperrdatei (O_CREATE|O_EXCL, damit das Anlegen unteilbar ist) verhindert gleichzeitige Schreibzugriffe. Sie enthält PID, Hostname und Zeitpunkt, damit eine hängengebliebene Sperre einzuordnen ist.
Lesender Zugriff ist parallel möglich (OpenOptions{ReadOnly: true}) — eine Wiederherstellung muss auch während eines laufenden Backups funktionieren.
Nach einem Absturz bleibt die Sperre liegen. Sie wird nicht automatisch gelöst — das wäre gefährlich, falls der Vorgang doch noch läuft. Der Eingriff ist ausdrücklich manuell (repository.BreakLock).
Abgebrochene Sessions
FindStaleSessions findet Journale, die ein früherer Lauf offen gelassen hat, und meldet, ob trotzdem ein Manifest vorliegt (dann war der Abschluss vollzogen und nur das Aufräumen unterbrochen). CleanupStaleSession räumt Journal und Arbeitsverzeichnis weg — ein bereits geschriebenes Manifest bleibt unangetastet.
Die Chunks eines abgebrochenen Laufs bleiben liegen und werden vom nächsten Versuch wiederverwendet. Das ist das Resume-Verhalten aus PROMPT.md §81: ein bei 70 % abgebrochenes Backup beginnt nicht bei null.
Gehärteter Modus
--hardened setzt immutable: true. Wirkung:
- Jedes Backup erhält eine Aufbewahrungsfrist (Standard 30 Tage).
DeleteBackupscheitert, solange die Frist läuft — unabhängig davon, wer löschen möchte.- Manifeste werden schreibgeschützt abgelegt (
0400).
Grenze, die nicht verschwiegen wird: Der Schreibschutz ist eine zusätzliche Hürde, keine Garantie. Wer Eigentümer der Datei ist, kann die Rechte ändern. Echte Unveränderlichkeit muss die Speicherebene durchsetzen — S3 Object Lock, WORM-Medien oder ein gehärtetes Linux-System mit getrenntem Konto. PROMPT.md §15 verlangt ausdrücklich, keine Unveränderlichkeit zu behaupten, die die Speicherebene nicht hergibt.
Statistiken
DeduplicationRatio() liefert zwei Werte: das Verhältnis und ob es überhaupt existiert. Wurde jeder Block bereits vorgefunden, ist nichts abgelegt worden und eine Division nicht definiert. Ein stillschweigend geliefertes 0 würde den besten aller Fälle als den schlechtesten darstellen.
Für Anzeigen ist SavingsPercentage() die verlässlichere Angabe — sie ist immer bestimmbar; 100 % bedeutet vollständige Deduplizierung.
Noch nicht umgesetzt
- Kompression und Verschlüsselung der Chunks (Phase 3/4). Die Felder
encryption_key_versionundcompression_algorithmsind bereits Teil des Manifestformats — eine spätere Ergänzung wäre ein Formatbruch. - Variables Chunking (Content-Defined Chunking). Derzeit bestimmt der Aufrufer die Blockgrenzen; feste Grenzen erkennen Einfügungen mitten in einer Datei nicht als Verschiebung.
- S3-kompatibler Objektspeicher. Die
Repository-Schnittstelle ist dafür geschnitten, umgesetzt ist bislang nur das Dateisystem. - Synthetic Full und Forever Forward Incremental. Kettenverwaltung und -prüfung stehen, das Zusammenführen fehlt.