# Störungen Nach Symptom geordnet — danach sucht man, wenn etwas nicht geht. ## Alles auf einmal: diagnose.sh ```bash sudo /opt/syncova/diagnose.sh ``` Sammelt in einem Zug, was für eine Fehlersuche gebraucht wird: Fassungen aller Programme, Betriebssystem, Container ja/nein, **Dateisystem des Repositorys**, PostgreSQL-Fassung, Schemastand, Dienstzustand, Gesundheitsbericht, Bestand, die letzten nicht erfolgreichen Läufe mit Fehlercode und Fehlerklasse, die gemessene Durchsetzungsstufe und die letzten Fehlerzeilen. Es **liest nur** und verändert nichts. Geheimnisse entfernt es selbsttätig — sehen Sie den Bericht trotzdem durch, bevor Sie ihn weitergeben. Für eine Fehlermeldung gehört seine Ausgabe vollständig ins Issue; ohne sie folgen als Erstes Rückfragen nach genau diesen Werten. ## Zuerst: die drei Auskünfte ```bash curl -s http://127.0.0.1:8080/health/ready | jq journalctl -u syncova-api -n 50 --no-pager ./bin/syncova-api --version ``` `/health/live` bleibt auch dann `200`, wenn die Datenbank weg ist — sonst löste eine kurz nicht erreichbare Datenbank einen Prozessneustart aus und verschlimmerte den Ausfall. Nur `/health/ready` bewertet die Abhängigkeiten. Jede Fehlermeldung der API trägt eine `request_id`. Damit findet sich die Anfrage in den Protokollen: ```bash journalctl -u syncova-api --no-pager | grep ``` --- ## Der Dienst startet nicht **„SYNCOVA_… erforderlich"** — eine Pflichtvariable fehlt. Die Meldung nennt sie. Bei `SYNCOVA_ENCRYPTION_KEYS` steht das erwartete Format dabei. **„Das Schema passt nicht zur Programmversion"** — `syncova-migrate up` wurde nach dem Austausch der Programme vergessen. Der Dienst ändert das Schema niemals selbst; das ist Absicht. **Start bricht ab, TLS erwähnt** — es ist nur `SYNCOVA_HTTP_TLS_CERT_FILE` **oder** nur `_KEY_FILE` gesetzt. Eine halbe Konfiguration wird abgelehnt, statt im Klartext zu lauschen. **Nichts im Protokoll, Prozess weg** — meist die Datenbank. Der Start wartet 30 Sekunden auf sie und endet dann mit einer Meldung. **`status=226/NAMESPACE`, „Failed to set up mount namespacing"** — ein Pfad in `ReadWritePaths` der Diensteinheit existiert **aus Sicht des Dienstes** nicht. Der häufigste Fall ist ein Repository unterhalb von `/tmp`: Die Einheit setzt `PrivateTmp=yes`, der Dienst bekommt damit ein eigenes `/tmp`, und der Ablageort ist dort nicht vorhanden. ```text syncova-api.service: Failed to set up mount namespacing: /tmp/… : No such file or directory syncova-api.service: Failed at step NAMESPACE spawning /opt/syncova/bin/syncova-api ``` **Ein Repository gehört ohnehin nicht nach `/tmp`.** `systemd-tmpfiles` räumt dort regelmäßig auf, und auf vielen Systemen ist es ein tmpfs — nach einem Neustart leer. Ein Backupsystem, das jede Nacht Erfolg meldet und keine Daten hat, ist schlimmer als gar keines. `setup.sh` lehnt solche Orte seit `rc3` ab. Abhilfe: Repository auf ein dauerhaftes Verzeichnis legen (etwa `/srv/syncova-repository`) und `ReadWritePaths` in `/etc/systemd/system/syncova-api.service` anpassen. --- ## Anmeldung schlägt fehl **Alle Anmeldungen scheitern gleichzeitig** — sehr wahrscheinlich die Datenbank, nicht die Anmeldung. Die Tokenprüfung braucht sie; fällt sie aus, scheitert jede Prüfung. Der Dienst meldet dann ausdrücklich `SERVICE_UNAVAILABLE` mit dem Zusatz *„Das ist kein Problem Ihrer Sitzung."* — genau, damit niemand den Fehler bei der Anmeldung sucht. **Ein Konto scheitert, andere nicht** — Sperre nach zu vielen Fehlversuchen. Vorgabe: 5 Versuche, dann 15 Minuten. Abwarten oder: ```bash ./bin/syncova-admin reset-password --username ``` **Zweiter Faktor wird abgelehnt** — die Uhr des Servers oder des Geräts geht falsch. TOTP erlaubt ein Fenster von ±30 Sekunden. Prüfen: `timedatectl`. Wurde derselbe Code eben schon verwendet, wird er abgelehnt — das ist der Replay-Schutz. Eine halbe Minute warten. **Ausgesperrt, niemand kommt mehr rein** — `syncova-admin reset-password` auf dem Server. Es setzt auch den zweiten Faktor zurück. --- ## Sicherungen laufen nicht **Der Auftrag steht auf „fällig", nichts passiert.** ```bash curl -s -H "Authorization: Bearer " https:///api/v1/jobs//runs | jq '.data[0]' ``` Häufigste Ursachen, in dieser Reihenfolge: 1. Der Auftrag ist **angehalten** (`status: paused`). 2. Ein **Wartungsfenster** verhindert ihn. Er wird dann verschoben, nicht übersprungen — dass ein Lauf verspätet ist, sieht man; dass er fehlt, nicht. 3. Ein **vorausgesetzter Auftrag** ist nicht erfolgreich gelaufen. Ein Teilfehler erfüllt keine Abhängigkeit. 4. Die Ausführungsschleife läuft nicht — dann steht auch in den Protokollen nichts von einem Übernahmeversuch. **Ein Lauf hängt auf `running`.** Stirbt ein Server mitten im Lauf, blockiert dessen Zeile den Auftrag. Nach fünf Minuten ohne Lebendmeldung wird sie freigegeben und als `SCHEDULER_LOST` vermerkt — Klasse `transient`, damit die Wiederholung greift. Warten Sie diese fünf Minuten ab, bevor Sie eingreifen. **`EXECUTOR_NOT_CONFIGURED`** — es ist kein Schlüsselmaterial eingerichtet. Der Executor verweigert den Dienst, statt unverschlüsselt zu sichern. Setzen Sie `SYNCOVA_ENCRYPTION_KEYS`. **`ALL_SOURCES_FAILED`** — keine einzige Quelle war erreichbar. Bei nur teilweise gescheiterten Quellen läuft der Auftrag weiter und endet als Teilfehler. --- ## „PARTIAL FAILURE" — Teilfehler Ein Teilfehler ist **kein** Erfolg und wird **nicht** wiederholt: Die übergangenen Objekte wären beim nächsten Versuch dieselben. Er verlangt einen Blick, keine Wiederholung. ```bash curl -s -H "Authorization: Bearer " \ https:///api/v1/jobs//runs | jq '.data[0].skip_reasons' ``` | Grund | Bedeutung | | --- | --- | | Rechtefehler | das Dienstkonto darf die Datei nicht lesen — **echter Datenverlust** | | Datei nicht lesbar | dort waren Daten, und sie fehlen | | Platte in Proxmox ausgenommen | `backup=0`; die Maschine kommt unvollständig zurück | **Sockets, benannte Pipes und Gerätedateien sind kein Teilfehler.** Sie werden vermerkt und übergangen — sie *gehören* nicht ins Backup. Auf einem Linux-System sind sie ein Dauerzustand; jeder Lauf über `/var` ergäbe sonst einen Teilfehler, und nach einer Woche klickt niemand mehr einen an. --- ## Repository **`REPOSITORY_FULL`** — der Datenträger ist voll. **Klasse `configuration`, wird nicht wiederholt**: Jeder Wiederholungslauf legte weitere Blöcke ab und verschärfte die Lage. Platz schaffen, dann von Hand anstoßen. **„Gelöscht, aber nichts frei geworden"** — kein Fehler, sondern Deduplizierung: Die Blöcke werden von einem anderen Backup noch gebraucht. `syncova-repo prune` entfernt nur die tatsächlich verwaisten. **`REPOSITORY_UNREACHABLE` bei einem Agenten** — der Agent schreibt selbst ins Repository. Auf einem anderen Rechner muss es dort **eingehängt** sein, und das Dienstkonto braucht Schreibrechte. **Sperre bleibt liegen** — Sperren werden nie automatisch gelöst. Nach einem Absturz: ```bash ./bin/syncova-repo break-lock --path /srv/syncova-repository ``` Das Kommando nennt zuerst, **wer** die Sperre hält — Prozess, Rechner und Zeitpunkt — und verlangt dann eine ausdrückliche Bestätigung: ```bash SYNCOVA_REPO_CONFIRM_BREAK_LOCK=ja ./bin/syncova-repo break-lock --path /srv/syncova-repository ``` Vergewissern Sie sich vorher, dass wirklich kein Vorgang mehr läuft. Bricht man die Sperre eines **laufenden** Vorgangs, arbeiten zwei Schreiber gleichzeitig am selben Repository — das Ergebnis ist keine Fehlermeldung, sondern ein beschädigter Bestand, und der fällt erst bei einer Wiederherstellung auf. **Löschen im gehärteten Repository schlägt fehl** — der Schutz greift. Auch für root, auch für `rm -rf`. Das ist der Zweck. --- ## Wiederherstellung **`ErrTargetNotEmpty`** — das Ziel ist nicht leer. Überschreiben verlangt drei Dinge: das Kennzeichen, die Berechtigung `restores.overwrite` und `confirm_overwrite` mit dem **wörtlich wiederholten** Zielpfad. **`RESTORE_TARGET_FORBIDDEN`** — das Ziel liegt in einem Systemverzeichnis. Der Agent prüft gegen die Systempfade **seines** Systems; der Server kennt sie nicht. **Wiederherstellung abgebrochen** — sie wird nicht selbsttätig wiederholt. Ein zweiter Lauf in ein halb gefülltes Ziel kann Daten beschädigen, die der erste bereits am Platz hatte. Stattdessen `POST /restores/{id}/resume`. **Vorabprüfung meldet fehlende Blöcke** — das Backup ist unvollständig. Die Befunde nennen die betroffene Datei. Nehmen Sie einen anderen Wiederherstellungspunkt; da Manifeste vollständig sind, ist jeder für sich wiederherstellbar. --- ## Agenten | Meldung | Ursache | | --- | --- | | Agent meldet sich nicht | Netzweg zum Server prüfen. Der Agent baut **ausgehend** auf; eine eingehende Freigabe ist nie nötig | | `ENCRYPTION_KEY_MISSING` | der Auftrag verlangt Verschlüsselung, dem Agenten fehlt das Schlüsselmaterial. Er lehnt ab, statt unverschlüsselt zu sichern | | `AGENT_LOST` | der Agent meldete sich während eines Auftrags nicht mehr. **Wird nicht wiederholt** — er könnte bereits Blöcke geschrieben haben | | `UNKNOWN_TASK_TYPE` | der Server kennt eine Auftragsart, die dieser Agent nicht hat. Agent aktualisieren | | Dienst startet und endet sofort | Zustandsdatei fehlt oder ist unlesbar. `syncova-agent register` erneut ausführen | **Der Agent beendet sich bei abgelehntem Token.** Das behebt sich nicht durch Warten — anders als eine Netzunterbrechung, bei der die Wartezeit von 5 Sekunden auf höchstens 5 Minuten wächst. --- ## Proxmox > Der Provider ist **nicht auf echter Hardware freigegeben**. Rechnen Sie mit > Abweichungen (siehe [proxmox.md](proxmox.md)). | Meldung | Ursache | | --- | --- | | „kein zugriffsweg auf die sicherungsarchive" | `archive_transport` fehlt oder die Speicherzuordnung ist leer. Proxmox gibt Archivdateien nicht über die REST-API heraus | | „fuer den knoten ist kein fingerabdruck hinterlegt" | beim SSH-Weg gehört je Knoten der Wirtsschlüssel eingetragen. Einen Schalter „egal" gibt es nicht | | „das zertifikat weicht vom hinterlegten fingerabdruck ab" | Proxmox hat ein neues Zertifikat. Fingerabdruck aktualisieren — **nicht** die Prüfung abschalten | | „meldete erfolg, auf dem speicher liegt aber kein archiv" | vzdump lief, das Archiv fehlt. Speicherplatz auf dem Knoten prüfen | | `ErrNotSupported` bei geänderten Blöcken | erwartet. Proxmox gibt sie nicht über REST heraus; es wird vollständig gelesen | --- ## Meldungen und Benachrichtigungen **Keine Meldungen, obwohl etwas kaputt ist** — jeder Kanal hat eine Schwelle (Vorgabe `high`). Ohne sie schaltet der Bereitschaftsdienst nach einer Woche die Benachrichtigungen ab, und dann kommt auch die kritische nicht mehr an. **Nur neue Meldungen werden zugestellt**, aktualisierte nicht. Der wiederholte Befund erhöht einen Zähler — einmal ist ein Zwischenfall, zwanzigmal ein Zustand. **Meldung bleibt stehen, obwohl behoben** — Meldungen lösen sich selbst auf, sobald die Regel den Befund nicht mehr liefert. Bleibt sie, besteht der Zustand weiter. **Bestätigen ist nicht Erledigen**: Eine bestätigte Meldung bleibt offen und in der Liste. **Webhook wird abgelehnt** — HTTPS ist Pflicht, und interne Ziele sind gesperrt (Metadatendienste, Rückschleife, private Netze). Für eine Testumgebung: `SYNCOVA_ALLOW_INTERNAL_NOTIFICATION_TARGETS=true`. --- ## Oberfläche **404 nach dem Neuladen einer Unterseite** — der SPA-Fallback fehlt im Webserver: `try_files $uri /index.html`. **„noch nicht verfügbar"** — die Seite ist bewusst gekennzeichnet. Sie sagt, *was* fehlt und *wo dieselbe Auskunft heute steht*. Kein Fehler. **Eine Kennzahl zeigt keine Zahl, sondern einen Satz** — sie hat keine Datengrundlage. Eine `0` stünde für „geprüft und in Ordnung"; genau das wäre falsch. **Erfolgsquote meldet `warning` bei 100 %** — es gab keine Läufe in sieben Tagen. Ohne Lauf gibt es keine Quote. Ein Dashboard, das bei ausgefallener Sicherung grün zeigt, ist schlimmer als keines. --- ## Wenn nichts davon passt ```bash # Was hat der Dienst zuletzt getan? journalctl -u syncova-api -n 200 --no-pager | grep -v '"level":"DEBUG"' # Stimmt der Schemastand? ./bin/syncova-migrate status # Ist das Repository in Ordnung? ./bin/syncova-repo health --path /srv/syncova-repository ./bin/syncova-repo scan --path /srv/syncova-repository --deep # Wie sieht die Anlage sich selbst? curl -s -H "Authorization: Bearer " https:///api/v1/security | jq '.data.assessment' ``` Für eine Rückfrage nützlich: Version (`--version`), Schemastand, die `request_id` der fehlgeschlagenen Anfrage und die Protokollzeilen dazu. **Ohne die `request_id` bleibt „es hat nicht funktioniert".**