syncova-backup/CHANGELOG.md
Jerrit Fritzsche b78a6fb51c
Some checks failed
CI / Backend (Go) (push) Failing after 32s
CI / Frontend (React/TypeScript) (push) Successful in 46s
CI / Sicherheitsprüfungen (push) Successful in 28s
Dokumentation und Aenderungsliste fuer rc8
Der Abschnitt "Wohin darf zurueckgeschrieben werden?" im Runbook ist der
wichtigste Zusatz: Dass ein Ziel an ProtectSystem=strict scheitert und nicht an
den Rechten des Verzeichnisses, sieht man dem Fehler nicht an. Die Tabelle nennt
die vier Faelle samt Grund.

Die Beispiel-Einheit in der Installationsanleitung fuehrte in denselben Fehler —
sie nannte nur das Repository in ReadWritePaths. Eine Anleitung, deren
Ergebnis keine Wiederherstellung zulaesst, ist schlimmer als keine.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-18 15:55:52 +02:00

17 KiB

Änderungen

V1 — Release Candidate 8, 18. August 2026

Wiederherstellung von Dateien und Ordnern mit Auswahl statt Textfeld — und die Erklärung, warum vorher gar keine Wiederherstellung funktionierte.

Warum keine Wiederherstellung ging

Nicht die Rechte des Zielverzeichnisses, sondern die Härtung des Dienstes: Er läuft mit ProtectSystem=strict und ReadWritePaths nur auf Repository und Sicherungsordner. Jedes Ziel außerhalb endete mit mkdir: permission denied — und zwar nach der Vorabprüfung, an der unangenehmsten Stelle. /tmp scheiterte anders: Mit PrivateTmp=yes hat der Dienst ein eigenes /tmp, und was dort landet, ist von außen unsichtbar.

setup.sh legt jetzt /srv/syncova-restore an und trägt es ein; --wiederherstellungsziel ergänzt weitere. Der Ort liegt unter /srv, weil /var/lib auf der Sperrliste des Zielschutzes steht — beide Regeln zugleich zu erfüllen lässt genau /srv übrig.

Auswahl statt Textfeld

  • Ordnerbaum für das Ziel. Er meldet je Verzeichnis, ob der Dienst dort schreiben darf — gemessen durch eine Probedatei, nicht aus den Rechtebits abgeleitet. Gesperrte Orte werden gezeigt, nicht versteckt: Sonst bliebe offen, warum ein Pfad fehlt.
  • Browser für den Backup-Inhalt. Ordner und einzelne Dateien lassen sich zurückholen. Der Baum entsteht aus den Pfaden, nicht aus Verzeichniseinträgen — ein Manifest kann eine Datei enthalten, deren Elternordner nicht als eigener Eintrag vorliegt.

Zwei neue Endpunkte, der eingefrorene Vertrag ist entsprechend erweitert: GET /filesystem/browse und GET /backups/{id}/contents.

Behoben

  • „can't access property toLocaleString, chunks_checked is undefined" beim Integritätslauf. Die Ergebnisse liegen unter details, und die Felder heißen missing_chunks/corrupted_chunks. Betrifft alle vier Prüfendpunkte — sie tragen dieselbe Hülle. Derselbe Fehler wie zuvor bei /retention-policies: die Antwortform angenommen statt geprüft. Alle konsumierten Endpunkte sind jetzt gegen den laufenden Dienst abgeglichen.

Geist Mono liegt im Paket

Drei Schnitte, 128 KB, OFL-Lizenz dabei. Ausgeliefert vom eigenen Ursprung — das verlangt die CSP, und ein Backup-Server, dessen Oberfläche von der Erreichbarkeit eines CDN abhängt, wäre auch ohne CSP falsch.

Bekannte Grenze

Eine Auswahl je Lauf, kein Mehrfachhaken. Eine Liste ausgewählter Pfade kennt die API nicht; mehrere Läufe hintereinander ergäben mehrere Ausgänge, und ein „teilweise fehlgeschlagen" ließe sich dann nicht mehr erklären.

V1 — Release Candidate 7, 18. August 2026

Behebt einen Absturz, macht die Sitzung brauchbar und stellt das Aussehen um.

Behoben

  • /retention zeigte einen schwarzen Bildschirm. GET /retention-policies liefert ein Objekt {policies, predefined} — als einziger von zehn geprüften Listenendpunkten. Die Oberfläche behandelte es als Array; map gibt es auf einem Objekt nicht, React hängte den ganzen Baum aus. Der Regressionstest füttert jetzt die echte Antwortform; ein Test mit einem Array hätte den Fehler nie gefunden, und genau das war passiert.
  • Jedes Neuladen führte zurück zur Anmeldung. Die Tokens lagen nur im Arbeitsspeicher.
  • Ein Fehler in einer Komponente schwärzte die ganze Konsole. Jetzt sitzt eine Fehlergrenze um den Seiteninhalt: Menü und Kopfzeile bleiben stehen, der Fehlertext ist lesbar und kopierbar.

Sitzung

Sie überlebt ein Neuladen und endet nach 30 Minuten — gerechnet als frühere von zwei Grenzen: einer harten Obergrenze ab Anmeldung, die keine Interaktion verschiebt, und einer Untätigkeitsgrenze. Die verbleibende Zeit läuft neben „Abmelden" und wird unter fünf Minuten auffällig.

Sechs Tests halten die Grenzen fest, zwei davon durch Mutation als fangend bestätigt: Wer beim Vermerken einer Interaktion die Obergrenze mitverschiebt, macht aus „30 Minuten" ein „unbegrenzt, solange die Maus wackelt".

Aussehen

Farben, Radien, Schatten und Schrift aus dem Preset b5vnF8SMi: violett als Handlungsfarbe, Radius 0, schattenlos, durchgehend Geist Mono. Die Statusfarben bleiben — das Preset kennt keine, und ohne sie ließe sich ein Teilfehler nicht von einem Erfolg unterscheiden.

Dazu Umlaute auf allen Seiten (vorher durchgehend ae/oe/ue/ss), 33 Erläuterungen von Absätzen auf einen Satz gekürzt und neue Module: acht Schnellzugriffe auf der Übersicht sowie sechs mitgelieferte Aufbewahrungsvorlagen als Kacheln — die lieferte der Server schon immer mit, die Oberfläche warf sie bisher weg.

Unverändert offen

Windows-Dienst, systemd-Einheit des Agenten und der Proxmox-Bootmeilenstein sind gebaut, aber nie auf echter Hardware gefahren. Geist Mono wird nicht mitgeliefert; ohne die Schrift auf dem Gerät greift die System-Monospace.

V1 — Release Candidate 6, 18. August 2026

Die Weboberfläche ist eine vollständige Verwaltungskonsole geworden.

Vorher erreichte sie 23 von 95 fachlichen Endpunkten; schreibend waren es neun, vier davon An- und Abmeldung. Real verwaltbar war: einen Auftrag anlegen, einen Bericht erzeugen, eine Meldung bestätigen. Das war ein Leseinstrument mit Assistent, keine Konsole. Jetzt sind es 89 von 95.

Neu bedienbar

  • Wiederherstellung als vierstufiger Assistent — vorher nur über curl. Die Vorabprüfung ist ein eigener Schritt, weil sie den Unterschied zwischen Hoffnung und Nachweis macht: Sie schreibt nichts und stellt fest, ob jeder benötigte Block noch da ist. Die drei Hürden vor dem Überschreiben sind sichtbar umgesetzt; läuft die dritte ins Leere, entfällt sie.
  • Wiederherstellungspunkte mit Bewertung, Legal Hold, Fristverlängerung, Löschung und Ransomware-Einschätzung.
  • Prüfung mit allen fünf Prüfarten. Zustand und Ergebnis stehen nebeneinander: Eine gescheiterte Prüfung ist kein Befund am Backup.
  • Repositories mit Integritätslauf, Katalog-Neuaufbau, Gesundheitsprüfung und gemessener Durchsetzungsstufe.
  • Aufbewahrung mit Regeln und Vorschau vor dem Löschen.
  • Proxmox — neun Endpunkte, die vorher gar keine Oberfläche hatten — und Agenten samt einmaliger Anzeige des Aufnahme-Tokens.
  • Benutzer, Rollen, Benachrichtigungswege, eigener zweiter Faktor.

Neues Design

Tailwind v4 und Radix-Primitive nach shadcn-Muster, alles gebündelt. Dark Mode, einklappbare Seitenleiste, Bedienung auf Tablets. Achtzehn Seiten in fünf Bereichen.

Die tragende Entscheidung ist keine Frage des Aussehens: Die Zuordnung der Fachbegriffe auf die fünf Statusfarben liegt an genau einer Stelle. Verteilt über die Seiten erschiene früher oder später irgendwo partial_failure grün — und ein Betreiber hält einen Teilfehler dann für einen Erfolg. Ein unbekannter Serverzustand wird neutral dargestellt, niemals grün.

Funde beim Nachweis

  • Die Einstufung heißt successful, nicht unverified. Das ist die gefährlichste Stelle der Oberfläche: successful bedeutet „der Lauf ist durchgelaufen" — nicht „wiederherstellbar". Es ist deshalb neutral, nicht grün. Regressionstest vorhanden.
  • describeApiError warf die genauere Servermeldung weg und ersetzte sie durch einen allgemeinen Satz. Ein SERVICE_UNAVAILABLE mit „Für diesen Bericht ist keine Sicherheitsprüfung eingerichtet" wurde zu „Der Dienst ist derzeit nicht vollständig verfügbar" — der Betreiber hätte den Fehler bei seiner Anlage gesucht. Jetzt hat die Servermeldung Vorrang.
  • Einem Fehler nach einer Handlung fehlte role="alert". Ein Screenreader hätte ihn nicht angesagt.
  • Der Geheimnis-Scanner griff korrekt beim Platzhaltertext des SSH-Schlüsselfelds. Gekennzeichnet, statt das Muster aufzuweichen.

Aufgeräumt

Ein Stylesheet statt sieben; das ausgelieferte CSS fällt von 54 auf 30 KB. Entfernt, weil ersetzt: JobsPanel, StatusIndicator, PageState.

Unverändert offen

Windows-Dienst, systemd-Einheit des Agenten und der Proxmox-Bootmeilenstein sind gebaut, aber nie auf echter Hardware gefahren. Dazu ohne Oberfläche: sechs Detail-Endpunkte (ihre Daten stehen in den Listen), Live-Fortschritt (/api/v1/events/stream ist auch serverseitig nicht umgesetzt) und der Simple Mode.

V1 — Release Candidate 5, 18. August 2026

Die Oberfläche richtet sich jetzt mit ein. Bisher endete setup.sh mit einer laufenden API auf 127.0.0.1:8080 und der Aufgabe, einen Webserver von Hand davorzusetzen — der häufigste Punkt, an dem eine Einrichtung liegen blieb.

  • setup.sh richtet nginx und ein selbst signiertes Zertifikat ein. Das Zertifikat gilt für den Rechnernamen, den vollständigen Namen und jede globale IPv4-Adresse des Servers (subjectAltName — moderne Browser lesen den CN nicht mehr), 3650 Tage. Der SHA-256-Fingerabdruck wird genannt, damit er sich beim ersten Aufruf im Browser vergleichen lässt.
  • Die API bleibt an 127.0.0.1:8080 gebunden. Erreichbar ist sie nur durch nginx hindurch. Sie stattdessen auf alle Schnittstellen zu legen wäre der kürzere Weg und der falsche: Die Verschlüsselung ließe sich dann umgehen, indem man Port 8080 direkt anspricht.
  • Die Firewall wird gemeldet, nicht geändert. ufw und firewalld werden erkannt und ihr Zustand ausgegeben; geöffnet wird nichts. Eine Einrichtung, die selbsttätig einen Port ins Netz öffnet, hebelt genau die Entscheidung aus, für die jemand die Firewall aufgesetzt hat.
  • Scheitert die Oberfläche, scheitert nicht die Einrichtung. Die Konfiguration wird mit nginx -t geprüft, bevor sie übernommen wird; hält sie nicht, wird sie entfernt, der Grund genannt und der Nachholweg gezeigt. Die Anlage läuft in jedem Fall.
  • Nachträglich einrichten: sudo /opt/syncova/setup.sh --weboberflaeche. Auslassen: --ohne-weboberflaeche.

Ein Fund beim Erproben:

  • http2 on; gibt es erst ab nginx 1.25.1. Debian 12 liefert 1.22, wo HTTP/2 ein Parameter von listen ist. Die neue Schreibweise ergibt dort „unknown directive http2", und nginx startet nicht. Die Fassung wird jetzt gelesen und die passende Schreibweise erzeugt.

V1 — Release Candidate 4, 18. August 2026

Behebt Issue #2: Die Einrichtung brach mit „Der Dienst meldet sich nicht als betriebsbereit" ab, obwohl der Dienst einwandfrei lief.

  • Die Bereitschaftsprüfung hängt nicht mehr an curl. Sie weicht auf wget aus und zuletzt auf die Bash selbst (/dev/tcp), die überall vorhanden ist. Auf einem schlanken Serverabbild ist curl nicht installiert — das ist der Normalfall, nicht die Ausnahme. Ein Einrichtungsskript darf nicht voraussetzen, was es nicht selbst mitbringt.
  • Betrifft setup.sh, update.sh und diagnose.sh. Der Diagnosebericht nennt jetzt zusätzlich, womit er gemessen hat.

V1 — Release Candidate 3, 17. August 2026

Behebt Issue #1: Die Einrichtung brach ab, wenn das Repository unter /tmp liegen sollte.

  • Ein flüchtiger Ablageort wird abgelehnt — /tmp, /var/tmp, /dev/shm, /run und jedes tmpfs. systemd-tmpfiles räumt dort auf, ein tmpfs ist nach einem Neustart leer: Die Sicherungen verschwänden von selbst, ohne Meldung, bis jemand sie braucht. Geprüft wird vor der Datenbankeinrichtung, damit ein unbeaufsichtigter Lauf in Sekunden scheitert statt nach Minuten. Für Wegwerf-Umgebungen: SYNCOVA_SETUP_ALLOW_VOLATILE_REPOSITORY=ja — dann weicht PrivateTmp, sonst könnte der Dienst nicht starten.
  • Der Abbruch zeigt jetzt den Grund. Kommt der Dienst nicht hoch, liefert setup.sh die letzten Journalzeilen gleich mit und erklärt 226/NAMESPACE. Vorher verwies er nur auf journalctl — und beim Rückbau war der Dienst dann schon weg.

V1 — Release Candidate 2, 17. August 2026

Ergänzt gegenüber rc1:

  • diagnose.sh liegt jetzt im Paket und wird von setup.sh und update.sh nach /opt/syncova/diagnose.sh gelegt. Es sammelt in einem Zug, was für eine Fehlersuche gebraucht wird — Fassungen, Dateisystem des Repositorys, Schemastand, letzte nicht erfolgreiche Läufe mit Fehlercode und Fehlerklasse, gemessene Durchsetzungsstufe. Es liest nur und entfernt Geheimnisse aus jeder Ausgabe.
  • Fehlervorlage unter .gitea/ISSUE_TEMPLATE/.

Zwei Korrekturen, beide beim Erproben gefunden:

  • PostgreSQL 15 genügt. Die Anleitung verlangte 17; Debian 12 liefert 15, und darauf lief alles bis zum echten Sicherungslauf. setup.sh prüft die vorgefundene Fassung jetzt und lehnt ältere als 15 ab, statt sie stillschweigend zu nehmen.
  • SYNCOVA_ADMIN_PASSWORD gibt es nicht. Die Anleitung nannte diese Umgebungsvariable; das Passwort kommt über die Standardeingabe. Korrigiert.

rc1 bleibt abrufbar, ist aber überholt.

V1 — 14. August 2026

Die erste Fassung. Sie sichert Dateisysteme unter Linux und Windows sowie Gäste eines Proxmox-VE-Verbunds, prüft die Wiederherstellbarkeit und weist sie nach.

Was sie kann

Sichern und Wiederherstellen. Inhaltsabhängige Blockfindung, Deduplizierung auch über verschlüsselte Bestände hinweg, zstd, AES-256-GCM, Streaming-Pipeline mit Gegendruck. Zusatzsicherungen tragen ein vollständiges Manifest — ein Restore liest genau eine Datei, es gibt keine Kette aufzulösen. Wiederherstellung mit Vorabprüfung, Prüfpunkt und Fortsetzung nach Abbruch.

Ein Repository, das ohne die Anlage auskommt. Inhaltsadressierte Blöcke, atomares Commit-Protokoll, Katalogaufbau allein aus den Manifesten. Fällt der Control-Server samt Datenbank aus, lässt sich beides aus dem Repository zurückholen.

Vertrauen wird nachgewiesen, nicht behauptet. Fünf Prüfarten bis zum tatsächlichen Wiederherstellungstest, eine Einstufung, die nur mit durchgeführtem Test auf recoverable steigt, und eine Bewertung, in die Unbekanntes niemals als gut eingeht.

Löschschutz mit gemessener Durchsetzungsstufe. Was das Betriebssystem nachweislich verhindert, wird gemeldet — nicht, was die Einstellung verspricht. Dazu Legal Hold, Fristverlängerung ohne Verkürzungsmöglichkeit und Aufbewahrungsregeln.

Oberfläche, Kennzahlen, Meldungen, Berichte, Security Center und eine Ransomware-Heuristik, die meldet und niemals selbst handelt.

Was sie ausdrücklich nicht kann

  • Kapazitätsprognose. Die Kennzahl erscheint mit Begründung statt mit einer Null.
  • Kopie an einen zweiten Ort (Backup Copy). Nicht umgesetzt; das Security Center führt den Bereich als ungeprüft und rechnet ihn nicht ein.
  • Changed Block Tracking bei Proxmox. Proxmox gibt geänderte Blöcke nicht über die REST-API heraus. Eine Zusatzsicherung eines Gasts spart deshalb Platz, aber keine Lesezeit.
  • Erweiterte Attribute, POSIX-ACLs und SELinux-Kontexte. Gehen bei einer Sicherung verloren.
  • Harte Verknüpfungen werden aufgelöst: Der Inhalt kommt vollständig zurück, die Verknüpfung nicht.
  • VMware, Hyper-V, Kubernetes, M365, Object Storage, Synthetic Full. Nicht Teil dieser Fassung.

Was gebaut, aber nicht auf echter Hardware gefahren wurde

Diese Punkte sind vollständig umgesetzt und gegen Nachbauten geprüft. Was fehlt, ist die Ausführung auf der jeweiligen Plattform — und bis dahin gelten sie nicht als freigegeben:

  • Der Windows-Dienst. Er übersetzt für Windows und ist vet-sauber, wurde aber nie geladen. Der Kommandozeilenweg und die gesamte Auftragsausführung sind plattformunabhängig nachgewiesen.
  • Die systemd-Einheit. Inhaltlich korrigiert, nie auf einem Linux-System geladen.
  • Proxmox. Entdecken, Sichern, Prüfen und bitgenaues Zurückschreiben laufen durch — gegen einen Nachbau der API. Ob eine wiederhergestellte Maschine startet, ist ungeprüft.
  • Der SSH-Zugriffsweg auf Proxmox-Knoten. Die Fingerabdruckprüfung ist getestet, eine echte Verbindung gab es nie.

Einrichtung, Aktualisierung, Entfernung

Das Linux-Paket bringt drei Skripte mit:

  • setup.sh richtet eine Anlage vollständig ein — PostgreSQL auf Wunsch mit, Dienstkonto, Schlüssel, Schema, erster Administrator, gehärtetes Repository, systemd-Einheit. Bricht ein Schritt ab, wird zurückgebaut, was dieser Lauf angelegt hat; Vorgefundenes bleibt unangetastet.
  • update.sh sichert zuerst Datenbank und Konfiguration, hält den Dienst an, tauscht die Programme, migriert mit der neuen Fassung und startet. Kommt der Dienst danach nicht hoch, holt es die vorige Fassung zurück. Repository und Verschlüsselungsschlüssel werden nie angefasst.
  • uninstall.sh entfernt standardmäßig nur Dienst und Programme. Datenbank, Repository und Konfiguration bleiben liegen; jede dieser drei Löschungen verlangt ein wörtlich getipptes Bestätigungswort an einem Terminal.

Eingefrorene Verträge

Ab dieser Fassung sind API (102 Endpunkte), Migrationen, Backup-Format und Repository-Protokoll festgeschrieben. Jede Abweichung schlägt in einer Prüfung an; Einzelheiten in docs/release-candidate.md.

Bekannte Grenzen

  • Das Manifest liegt vollständig im Speicher — rund 200 Byte je Blockverweis, also etwa 1,5 GiB bei 10 TB Quelldaten.
  • Bei vielen kleinen Dateien begrenzt fsync den Durchsatz auf rund 100 Dateien je Sekunde. Das ist der Preis des Commit-Protokolls und kein Fehler.
  • Weitergeleitete IP-Header werden ignoriert; hinter einem Reverse Proxy steht im Auditprotokoll dessen Adresse.