Eine Vorlage allein bringt wenig — sie stellt Fragen, die der Meldende meist nicht beantworten kann. Deshalb zwei Teile: diagnose.sh sammelt in einem Zug, was zur Analyse gebraucht wird: Fassungen aller acht Programme, Betriebssystem, Container ja/nein, Dateisystem des Repositorys, PostgreSQL-Fassung, Schemastand, Dienstzustand, Gesundheitsbericht (der auch bei 503 den vollstaendigen Bericht traegt), Bestand, die letzten nicht erfolgreichen Laeufe mit Fehlercode UND Fehlerklasse, die gemessene Durchsetzungsstufe und die letzten Fehlerzeilen. Es liest nur. Geheimnisse kommen nicht hinein, und der Weg dahin ist umgekehrt: Es gibt eine Liste der Werte, die gezeigt werden duerfen. Eine Sperrliste vergaesse den naechsten neuen Wert. Zusaetzlich werden die tatsaechlichen Geheimnisse gelesen und aus JEDER Ausgabe entfernt — auch aus Protokollzeilen, in die sie auf einem unvorhergesehenen Weg geraten sind. Real geprueft: weder Datenbankpasswort noch Schluessel noch Administratorpasswort stehen im Bericht. Die Vorlage beginnt mit sieben Faellen, die wie ein Fehler aussehen und gewolltes Verhalten sind — "advisory" statt "filesystem", ein Teilfehler, "geloescht aber nichts frei", 503 mit vollstaendigem Bericht. Das ist keine Abwehr, sondern spart beiden Seiten einen halben Tag. Pflichtfelder sind Beobachtung, Erwartung, Schritte, Bereich, Datenrisiko, Haeufigkeit und der Diagnosebericht; Fehlercode und request_id stehen eigens da, weil sie die beiden wertvollsten Angaben sind. Beim Erproben zwei Funde: - Die Installationsanleitung verlangte PostgreSQL 17. setup.sh installiert auf Debian 12 aber 15 — und alles lief, bis hin zu einem echten Sicherungslauf. Die Anforderung lautet jetzt 15 (geprueft gegen 17 in CI und Entwicklung, gegen 15 auf Debian 12), und setup.sh lehnt aeltere Fassungen ab statt sie stillschweigend zu nehmen. - Ein Repository auf der Platte, das nicht in der Control Plane eingetragen ist, faellt niemandem auf: Die Sicherung laeuft nie, weil der Server das Ziel nicht kennt. Der Bericht benennt diesen Fall jetzt ausdruecklich. Gegen das echte v1.0.0-rc1-Paket gefahren: Installation, erzeugte Stoerung (ALL_SOURCES_FAILED / source), Bericht zeigt Code, Klasse, "overlayfs" und "nie gemessen". Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
293 lines
12 KiB
Markdown
293 lines
12 KiB
Markdown
# 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 <request-id>
|
|
```
|
|
|
|
---
|
|
|
|
## 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.
|
|
|
|
---
|
|
|
|
## 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 <name>
|
|
```
|
|
|
|
**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 <token>" https://<server>/api/v1/jobs/<id>/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 <token>" \
|
|
https://<server>/api/v1/jobs/<id>/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 <token>" https://<server>/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".**
|