syncova-backup/docs/troubleshooting.md
Jerrit Fritzsche b6668c600d
Some checks failed
CI / Backend (Go) (push) Failing after 29s
CI / Frontend (React/TypeScript) (push) Successful in 33s
CI / Sicherheitsprüfungen (push) Successful in 24s
Weboberflaeche richtet sich mit ein (rc5)
Bisher endete setup.sh mit einer laufenden API auf 127.0.0.1:8080 und der
Aufgabe, einen Webserver von Hand davorzusetzen. Das war der haeufigste Punkt,
an dem eine Einrichtung liegen blieb.

setup.sh richtet jetzt nginx ein und stellt ein selbst signiertes Zertifikat
aus. Es gilt fuer Rechnernamen, vollstaendigen Namen und jede globale
IPv4-Adresse (subjectAltName — moderne Browser lesen den CN nicht mehr), 3650
Tage; der SHA-256-Fingerabdruck wird genannt.

Drei Entscheidungen:

- Die API bleibt an 127.0.0.1:8080 gebunden. Sie auf alle Schnittstellen zu
  legen waere der kuerzere Weg und der falsche: Die Verschluesselung liesse
  sich dann umgehen, indem man Port 8080 direkt anspricht.
- Die Firewall wird gemeldet, nicht geaendert. Eine Einrichtung, die
  selbsttaetig einen Port ins Netz oeffnet, hebelt genau die Entscheidung aus,
  fuer die jemand die Firewall aufgesetzt hat.
- Scheitert die Oberflaeche, scheitert nicht die Einrichtung. Geprueft wird mit
  nginx -t, bevor die Konfiguration uebernommen wird; haelt sie nicht, wird sie
  entfernt und der Nachholweg gezeigt.

Zwei Funde 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.
- setup.sh kopierte nur diagnose.sh neben die Programme. Der eigene Hinweis
  "Spaeter nachholen: /opt/syncova/setup.sh --weboberflaeche" verwies damit auf
  eine Datei, die es nicht gab; schwerer wiegt uninstall.sh — wer das
  ausgepackte Paket aufraeumte, haette die Anlage nie wieder entfernen koennen.
  Jetzt kommen alle vier Skripte mit.

Nachgewiesen im Container gegen Debian 12 mit nginx 1.22: Neuinstallation von
Grund auf, Oberflaeche und /api/ von aussen ueber HTTPS erreichbar (200),
SPA-Fallback traegt, Anmeldung und Repository-Anlage durch nginx hindurch,
Durchsetzungsstufe gemessen, HTTP leitet mit 301 auf HTTPS, Fingerabdruck
stimmt mit dem genannten ueberein, Neuausstellung des Zertifikats geprueft.

Regressionstests fuer beide Funde, beide durch Mutation als fangend bestaetigt.

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

15 KiB

Störungen

Nach Symptom geordnet — danach sucht man, wenn etwas nicht geht.

Alles auf einmal: diagnose.sh

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

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:

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.

„Der Dienst meldet sich nicht als betriebsbereit", aber das Protokoll zeigt einen sauberen Start — dann kam die Prüfung nicht an den Dienst heran, nicht umgekehrt. Bis rc3 prüfte setup.sh ausschließlich mit curl; auf einem schlanken Serverabbild ist der nicht installiert. Seit rc4 weicht die Prüfung auf wget und zuletzt auf die Bash selbst aus (/dev/tcp).

Erkennungsmerkmal im Diagnosebericht: Abgefragt mit: Bash /dev/tcp oder, in älteren Fassungen, curl ist nicht vorhanden. Ein zweites: Der Dienst wird genau 15 Sekunden nach dem Start wieder beendet — das ist der Rückbau nach 15 vergeblichen Prüfversuchen.

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.

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:

./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.

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.

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:

./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:

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).

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

Die Oberfläche ist gar nicht erreichbar — prüfen Sie zuerst, ob sie überhaupt eingerichtet wurde:

sudo /opt/syncova/diagnose.sh | sed -n '/## Weboberflaeche/,/^## /p'

Steht dort „nginx ist nicht vorhanden", holen Sie es nach:

sudo /opt/syncova/setup.sh --weboberflaeche

Die Verbindung wird abgewiesen, aber nginx läuft — die Firewall. setup.sh meldet sie nur und öffnet nichts:

sudo ufw allow 443/tcp                              # ufw
sudo firewall-cmd --permanent --add-service=https && sudo firewall-cmd --reload

nginx: unknown directive "http2" — die Konfiguration nutzt http2 on;, das es erst ab nginx 1.25.1 gibt. Debian 12 liefert 1.22, wo HTTP/2 ein Parameter von listen ist. Ab rc5 wird die Fassung gelesen und die passende Schreibweise erzeugt; bei einer von Hand geschriebenen Konfiguration:

listen 443 ssl http2;    # nginx < 1.25.1

Der Browser warnt vor dem Zertifikat — es ist selbst ausgestellt, die Warnung ist berechtigt. Vergleichen Sie den Fingerabdruck einmal:

sudo openssl x509 -in /etc/syncova/tls/server.crt -noout -fingerprint -sha256

Stimmt er mit dem im Browser überein, ist die Warnung unbedenklich. Stimmt er nicht, brechen Sie ab — dann sitzt jemand dazwischen.

„Ihre Verbindung ist nicht privat" trotz richtigem Fingerabdruck, und der Browser lässt Sie nicht weiter — meist fehlt die verwendete Adresse im Zertifikat. Es gilt für die IP-Adressen, die der Server beim Einrichten hatte; eine später hinzugekommene ist nicht dabei:

sudo openssl x509 -in /etc/syncova/tls/server.crt -noout -ext subjectAltName

Neu ausstellen: sudo rm /etc/syncova/tls/server.crt && sudo /opt/syncova/setup.sh --weboberflaeche

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

# 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".