Backup ohne Restore-Test ist kein Backup
Die Frage „Haben Sie ein Backup?" wird fast immer mit Ja beantwortet. Die Frage „Wann haben Sie es zuletzt zurückgespielt?" fast nie. Dazwischen liegt der Unterschied zwischen einem Backup und einer Hoffnung. Ich habe in 25 Jahren Betrieb von Geschäftsanwendungen mehr Backups gesehen, die im Ernstfall nicht funktionierten, als Server, die nie ausgefallen sind. Die Sicherung war da. Sie war nur unvollständig, veraltet, verschlüsselt mit einem Schlüssel, den niemand mehr hatte, oder sie lag auf derselben Maschine, die gerade gestorben war.
Dieser Beitrag beschreibt, wie ich Backups für Webapps und die dazugehörigen Server aufbaue, und warum der Restore-Test der Teil ist, an dem sich alles entscheidet. Nichts davon ist teuer. Das meiste ist Disziplin.
TL;DR - Die Kurzfassung
- Ein Backup ist erst dann eines, wenn Sie es zurückgespielt haben und wissen, wie lange das dauert.
- Zwei Fragen vor jeder Technik: Wie viel Datenverlust ist tragbar (Stunden? ein Tag?), und wie lange darf die Wiederherstellung dauern?
- Datenbank und Dateien getrennt sichern, aber zeitlich gekoppelt. Ein Dump ist etwas anderes als eine Kopie der Datenbankdateien.
- Der Backup-Server holt die Daten (Pull). Der Produktivserver darf das Backup nicht löschen können, sonst löscht ein Angreifer beides.
- Backups enthalten personenbezogene Daten. Aufbewahrung begrenzen, dokumentieren, und ein Restore darf Gelöschtes nicht unbemerkt zurückbringen.
- Einmal im Quartal einen echten Restore machen, mit Stoppuhr, und das Ergebnis aufschreiben.
Zwei Fragen, bevor es um Technik geht
Bevor Sie über Werkzeuge nachdenken, brauchen Sie zwei Zahlen. Sie kommen aus der Fachwelt der Notfallplanung, sind aber auch für einen Zehn-Personen-Betrieb die richtigen Fragen.
Wie viel dürfen Sie verlieren? Wenn der Server um 15 Uhr stirbt und das letzte Backup von 2 Uhr nachts stammt, sind dreizehn Stunden Arbeit weg. Bei einem Blog ist das egal. Bei einem Kundenportal, in dem den ganzen Tag Aufträge angelegt werden, ist es ein Tag Nacharbeit mit dem Telefon in der Hand. Die Fachwelt nennt diese Zahl RPO, ich nenne sie „tragbarer Verlust". Sie bestimmt, wie oft gesichert wird.
Wie lange dürfen Sie stehen? Ein Backup auf einem Band im Tresor ist sicher, aber wenn die Wiederherstellung zwei Tage dauert, weil erst ein neuer Server bestellt werden muss, sind das zwei Tage ohne Auftragsannahme. Die Fachwelt nennt das RTO, ich nenne es „tragbarer Stillstand". Diese Zahl bestimmt, wie das Backup aufgebaut sein muss und ob ein Ersatzsystem bereitstehen sollte.
Mit diesen zwei Zahlen ist das meiste entschieden. Ein Betrieb, der einen Tag Verlust und drei Tage Stillstand verkraftet, kommt mit einem nächtlichen Backup und einem guten Restore-Plan aus. Ein Betrieb, der nach vier Stunden Stillstand Geld verliert, braucht stündliche Datenbanksicherungen und einen Server, der bereitsteht.
Was gesichert werden muss, und warum getrennt
Eine Webapp besteht aus vier Dingen, die unterschiedlich behandelt werden wollen:
| Bestandteil | Wie sichern | Typischer Fehler |
|---|---|---|
| Datenbank | Logischer Dump (pg_dump, mariadb-dump), täglich oder öfter | Nur die Dateien des Datenbankverzeichnisses kopieren. Die sind im laufenden Betrieb inkonsistent und oft nicht einlesbar. |
| Hochgeladene Dateien | Dateisystem-Backup mit Deduplizierung | Vergessen, weil sie außerhalb des Codeverzeichnisses liegen. |
| Code und Konfiguration | Versionsverwaltung plus Sicherung von /etc und den geheimen Konfigurationsdateien | Der Code ist im Git, die Zugangsdaten zur Datenbank waren nur auf dem Server. |
| Das System selbst | Dokumentierte Einrichtung, die man in einer Stunde nachspielen kann | Ein fünf Jahre gewachsener Server, den niemand mehr neu aufsetzen kann. |
Der wichtigste Punkt ist der erste. Ein Datenbank-Dump ist eine Datei, die alle Befehle enthält, um die Datenbank neu aufzubauen. Er ist konsistent, weil die Datenbank ihn selbst erzeugt, und er lässt sich in der Regel auch für einen Versionswechsel der Datenbank verwenden. Bei mir läuft er täglich um Mitternacht für MariaDB und um halb eins für PostgreSQL, mit vierzehn Tagen Aufbewahrung auf dem Server selbst, bevor das eigentliche Backup die Dumps abholt. So ein Skript sieht in vielen Betrieben ungefähr so aus:
# Nächtlicher PostgreSQL-Dump, alle Datenbanken, komprimiert, 14 Tage
DAY=$(date +%F)
sudo -u postgres pg_dumpall | gzip > /var/backups/pgsql/all-$DAY.sql.gz
find /var/backups/pgsql -name 'all-*.sql.gz' -mtime +14 -delete
Dieses Skript enthält eine Falle. Sehen Sie sie? Wenn pg_dumpall scheitert, etwa weil Authentifizierung oder Verbindungskonfiguration geändert wurden, läuft gzip trotzdem sauber durch und schreibt eine winzige, leere Datei. Die Shell meldet Erfolg, weil in einer Pipeline nur der Rückgabewert des letzten Befehls zählt. Der Cron-Job ist zufrieden, die Datei ist da, und niemand merkt vier Monate lang, dass sie drei Kilobyte groß ist. Ich habe genau diesen Fall bei einer Übernahme gefunden. Die korrigierte Version prüft beides, den Rückgabewert der ganzen Pipeline und die Plausibilität der Datei:
#!/bin/bash
set -o pipefail # Pipeline scheitert, wenn irgendein Glied scheitert
DAY=$(date +%F)
OUT=/var/backups/pgsql/all-$DAY.sql.gz
if ! sudo -u postgres pg_dumpall | gzip > "$OUT"; then
rm -f "$OUT"; chat-notify "ALARM: pg_dumpall fehlgeschlagen ($DAY)"; exit 1
fi
# Plausibilität: kleiner als 100 kB ist kein Dump, sondern ein Fehler
if [ "$(stat -c %s "$OUT")" -lt 100000 ]; then
chat-notify "ALARM: Dump verdächtig klein: $(du -h "$OUT")"; rm -f "$OUT"; exit 1
fi
find /var/backups/pgsql -name 'all-*.sql.gz' -mtime +14 -delete
Die Größenprüfung ist bewusst grob. Es geht nicht darum, den Dump zu verifizieren, sondern darum, den offensichtlichen Fehlschlag am nächsten Morgen zu sehen statt in vier Monaten. Und die kaputte Datei wird gelöscht, damit sie nicht nachts vom Backup abgeholt wird und im Restore-Fall für Verwirrung sorgt. Der Alarm geht in den Chat, nicht ins Postfach. Warum, steht im Beitrag über Logging, Monitoring und Alerts.
Das Dump-Format ist ein Hebel für die Wiederherstellungszeit
Ein Klartext-Dump wie oben lässt sich nur seriell einspielen, Befehl für Befehl. Bei zwei Gigabyte ist das eine Viertelstunde und egal. Bei fünfzig Gigabyte können es Stunden sein, je nach Schema, Indizes, Platten und Zielsystem. PostgreSQL bietet dafür mit pg_dump -Fc ein eigenes Format, das sich mit pg_restore -j 4 auf mehreren Prozessorkernen parallel wiederherstellen lässt. Wie viel das bringt, hängt von Hardware und Datenbankstruktur ab, aber bei großen Datenbanken ist der Unterschied erheblich. Eine Falle dabei: pg_dumpall kennt dieses Format nicht. Der Umstieg heißt konkret pro Datenbank pg_dump -Fc, und dazu einmal pg_dumpall --globals-only für Rollen und Rechte, die sonst im Restore fehlen. Wer stündlich sichern muss, nimmt zusätzlich die eingebaute Archivierung der Transaktionsprotokolle dazu. Damit lässt sich die Datenbank auf jede beliebige Minute zurücksetzen, nicht nur auf den letzten Dump.
Pull statt Push: Der Produktivserver darf das Backup nicht erreichen
Das übliche Bild ist: Der Server schiebt nachts seine Daten auf einen Backup-Speicher. Das ist bequem und hat einen Konstruktionsfehler. Wenn der Server die Zugangsdaten zum Backup hat, hat sie auch jeder, der den Server übernimmt. Verschlüsselungstrojaner suchen als Erstes nach genau diesen Zugängen und löschen das Backup, bevor sie die Produktivdaten verschlüsseln. Dann ist die Sicherung genau dann weg, wenn man sie braucht.
Die bessere Konstruktion dreht die Richtung um: Der Backup-Server holt. Er hat einen eingeschränkten Zugang zum Produktivserver, mit dem er nur lesen kann. Der Produktivserver kennt den Backup-Server gar nicht. Selbst wenn er vollständig übernommen wird, kann der Angreifer die Sicherung weder lesen noch löschen.
Technisch geht das mit einem eigenen Benutzer auf dem Produktivserver, dessen SSH-Schlüssel auf ein einziges Kommando beschränkt ist: einen lesenden rsync. Die Zeile in authorized_keys sieht dann so aus:
command="/usr/bin/rrsync -ro /",from="10.0.0.6",no-agent-forwarding,no-port-forwarding,no-pty,no-X11-forwarding ssh-ed25519 AAAA... backup@backupserver
Der Backup-Server darf mit diesem Schlüssel genau eines: Dateien lesen. Kein Schreiben, keine Shell, nur von seiner eigenen Adresse aus. Der Ablauf bei mir ist zweistufig: Der Backup-Server holt per rsync eine aktuelle Kopie des Produktivservers in ein Arbeitsverzeichnis, und anschließend archiviert BorgBackup dieses lokale Verzeichnis. Borg spricht sein eigenes Protokoll und läuft nicht durch den rsync-Tunnel, es sieht nur die fertige Kopie. Dafür dedupliziert es (gleiche Datenblöcke werden nur einmal gespeichert), verschlüsselt und hält eine Historie über Monate, ohne dass der Platz explodiert. Restic ist die gleichwertige Alternative. Beide sind frei, seit Jahren stabil und gut dokumentiert.
Zwei Dinge gehören zu dieser Konstruktion dazu. Erstens die Reihenfolge: Erst läuft der Dump, dann holt der Pull. Dumps und hochgeladene Dateien werden im selben Lauf abgeholt, damit Datenbank und Dateien zum selben Stand gehören. Ein Dump von Mitternacht mit Dateien von sechs Uhr morgens ergibt nach dem Restore Aufträge, deren Anhänge fehlen, oder Anhänge, zu denen es keinen Auftrag gibt. Zweitens die Konsequenz aus rrsync -ro /: Der Schlüssel liest alles, worauf der Backup-Benutzer Rechte hat, und bei einem vollständigen Systembackup ist das potenziell auch sehr Sensibles, von Systemdateien mit Passwort-Hashes bis zu den Zugangsdaten der Anwendung. Für ein Vollbackup ist das gewollt. Aber damit ist der Backup-Server mindestens so schützenswert wie der Produktivserver, nicht die alte Kiste im Keller, an der noch ein Standardpasswort hängt. Er bekommt dieselbe Härtung, dieselben Updates und dieselbe Überwachung.
Wenn Pull nicht geht: Push mit Anhängen-only (Append-only)
Nicht jeder kann einen Backup-Server betreiben, der selbst holt. Wer schieben muss, etwa auf eine gemietete Storage-Box, hat mit Borg trotzdem eine Antwort auf das Löschproblem: Das Ziel wird mit borg serve --append-only betrieben. Der Produktivserver kann dann neue Sicherungen hinzufügen, aber bestehende weder löschen noch überschreiben. Das Aufräumen alter Archive geschieht getrennt, mit einem anderen Schlüssel, von einer anderen Maschine. Ein Angreifer mit dem Push-Schlüssel kann also Müll anhängen, aber nicht die Historie vernichten.
Die 3-2-1-Regel, in Kurzform
Drei Kopien der Daten, auf zwei verschiedenen Medien, eine davon an einem anderen Ort. Für einen KMU-Server heißt das praktisch: die Produktivdaten, das Borg-Archiv auf dem Backup-Server, und eine Kopie dieses Archivs auf einem Speicher außer Haus, etwa einer Storage-Box bei einem anderen Anbieter oder einer Festplatte, die einmal im Monat mit nach Hause genommen wird. Verschlüsselt, versteht sich, sonst ist die Festplatte auf dem Fahrradgepäckträger ein Datenschutzvorfall auf Rädern. Ein Brand, ein Diebstahl oder eine Insolvenz des Hosters treffen dann nie alle drei Kopien.
Backups und Datenschutz: Der gelöschte Kunde lebt im Archiv weiter
Ein Punkt, der in technischen Anleitungen meist fehlt: Ein Backup enthält personenbezogene Daten, und zwar auch die, die in der Anwendung längst gelöscht sind. Wer im März einen Kunden auf dessen Wunsch löscht, hat ihn im Februar-Archiv noch. Das lässt sich datenschutzkonform abbilden, wenn drei Dinge stimmen, und die sind vor allem organisatorisch, nicht technisch:
- Die Aufbewahrung ist begrenzt und dokumentiert. Ein Backup wird nicht ewig gehalten, sondern nach einem festen Schema rotiert, etwa täglich für zwei Wochen, wöchentlich für drei Monate, monatlich für ein Jahr. Damit „läuft die Löschung nach": Mit der Rotation verschwindet der gelöschte Kunde auch aus dem Archiv. Das Schema gehört dokumentiert, je nach Aufbau ins Backup-Konzept, ins Löschkonzept oder zu den technisch-organisatorischen Maßnahmen.
- Ein Restore bringt Gelöschtes nicht unbemerkt zurück. Wenn nach einem Ausfall das Backup von gestern eingespielt wird, sind die Löschungen von heute rückgängig gemacht. Eine Möglichkeit: Die Anwendung protokolliert Löschanfragen getrennt vom Datenbestand, und nach einem Restore werden sie erneut ausgeführt. Andere Systeme lösen das über einen Abgleich nach dem Restore. Wichtig ist nur, dass es ein Punkt auf der Restore-Checkliste ist, kein Zufall.
- Das Archiv ist verschlüsselt und der Zugang beschränkt. Siehe oben: Der Backup-Server ist ein sensibles System.
Mehr dazu, was bei Webapps wirklich nötig ist und was Panikmache, steht im Beitrag über DSGVO für Webapplikationen.
Der Restore-Test: Der Teil, den alle auslassen
Jetzt zum Kern. Alles bis hierher kann perfekt eingerichtet sein und trotzdem versagen, weil niemand je geprüft hat, ob aus dem Backup wieder ein laufendes System wird. Die Gründe, aus denen Restores in der Praxis scheitern, sind immer dieselben, und keiner davon fällt auf, solange man nur sichert:
- Der Dump ist leer oder abgebrochen, weil die Anmeldung an der Datenbank nicht mehr funktioniert. Die Datei existiert, sie ist nur drei Kilobyte groß. Seit vier Monaten. Die Falle von oben.
- Das Backup enthält die Datenbank, aber nicht die hochgeladenen Dateien, weil die in einem anderen Verzeichnis liegen.
- Der Verschlüsselungsschlüssel des Archivs lag nur auf dem Server, der gerade weg ist.
- Der Restore funktioniert, dauert aber neun Stunden, weil niemand wusste, dass 400 Gigabyte Dateien darin sind, und der Dump seriell eingespielt wird.
- Die Anwendung startet, aber die Konfigurationsdatei mit den Zugangsdaten zur Zahlungsschnittstelle fehlt, und die Kollegin, die sie kannte, ist im Urlaub.
Deshalb gibt es bei mir einen Kalendereintrag: am ersten Tag jedes Quartals ein echter Restore. Nicht „mal ins Archiv schauen", sondern: eine leere virtuelle Maschine, das Backup einspielen, die Anwendung starten, sich anmelden, einen Datensatz öffnen. Mit Stoppuhr. Das Ergebnis wird in wenigen Zeilen festgehalten: Datum, Dauer, was gefehlt hat.
2026-07-01 Restore-Test kundenportal
Dump eingespielt: 11 min (2,3 GB, Klartext, seriell)
Dateien zurück: 38 min (112 GB, Borg extract)
App gestartet, Login: ok
Löschanfragen seit Backup-Stand nachgezogen: 2
Gefehlt: /etc/cron.d/portal-import nicht im Backup -> aufgenommen
Gesamt: 58 min
Die vorletzte Zeile ist der Grund, warum man den Test überhaupt macht: Jedes Quartal fällt eine Kleinigkeit auf, die im Ernstfall eine Nacht gekostet hätte. Und die letzte Zeile ist die, die zählt. Aus „wir haben ein Backup" wird „wir sind in einer Stunde wieder da, und wir wissen es, weil wir es gemessen haben".
Warum das Protokoll Geschäftswert hat
Diese Zeilen sind mehr als Disziplin. Wer eine Cyberversicherung abschließt, wird im Antrag nach Backup-Verfahren gefragt, oft konkret nach Trennung vom Produktivsystem, Verschlüsselung und danach, ob Wiederherstellungen getestet werden. Im Schadensfall prüft der Versicherer, ob die angegebenen Maßnahmen tatsächlich umgesetzt waren. Ein Quartalsprotokoll mit Datum, Dauer und Ergebnis ist ein Nachweis, der eine solche Diskussion erheblich vereinfacht. Dasselbe gilt bei einer Übernahme oder einer Prüfung durch einen großen Kunden: „Wir sichern täglich" ist eine Behauptung, „letzter Restore am 1. Juli, 58 Minuten, vollständig" ist ein Beleg. Der Test kostet eine Stunde im Quartal und verwandelt das Backup von einer Hoffnung in eine belegbare Aussage.
Den Test automatisieren, aber nicht ganz
Den technischen Teil kann ein Skript übernehmen: Archiv auf ein Testsystem entpacken, Dump einspielen, prüfen, ob die Zeilenzahlen der wichtigsten Tabellen plausibel sind, Dauer messen, Ergebnis in den Chat melden. Das läuft bei mir vierteljährlich von selbst und meldet sich, ob es gut oder schlecht ausging. Was ein Skript nicht kann: sich anmelden, einen Auftrag öffnen und beurteilen, ob die Anwendung sich richtig anfühlt. Diese zehn Minuten macht ein Mensch. Beides zusammen ist der Test.
Die häufigsten Fehler
- Backup auf demselben Server. Ein zweites Verzeichnis auf derselben Platte schützt vor versehentlichem Löschen, sonst vor nichts.
- Push mit vollen Rechten. Der Server kann sein Backup löschen. Ein Angreifer damit auch. Wenn Push, dann Anhängen-only.
- Pipeline ohne Fehlerprüfung. Der Dump scheitert, die Datei entsteht trotzdem, der Cron meldet Erfolg.
- Nur Datenbank oder nur Dateien. Eine Webapp besteht aus beidem, und sie passen nur zusammen, wenn sie im selben Lauf gesichert wurden.
- Kein Alarm bei ausbleibendem Backup. Das Backup-Skript ist seit Wochen fehlgeschlagen, und niemand hat es gemerkt, weil ein Fehlschlag keine Meldung erzeugt. Das Alter des letzten Backups gehört in die tägliche Statusmeldung.
- Schlüssel und Passwörter nur an einem Ort. Der Schlüssel zum Archiv gehört ausgedruckt in einen Umschlag und in einen Passwort-Manager, nicht nur auf den Server.
- Backup-Server als Nebensache. Er enthält alles, was der Produktivserver enthält. Er wird genauso gehärtet.
- Nie zurückgespielt. Der Fehler, um den es hier geht.
Ein pragmatischer Einstieg
- Die zwei Zahlen festlegen: tragbarer Verlust, tragbarer Stillstand. Zehn Minuten Gespräch, keine Technik.
- Nächtliche Datenbank-Dumps einrichten, mit
pipefail, Größenprüfung, Alarm und Aufbewahrung. Bei großen Datenbanken im Custom-Format. - Einen Backup-Server oder -Speicher einrichten, der die Daten holt, mit BorgBackup oder Restic, verschlüsselt, Schlüssel an zwei Orten. Wenn Push, dann Anhängen-only.
- Eine Kopie außer Haus, verschlüsselt, automatisch oder von Hand, aber regelmäßig.
- Rotationsschema festlegen und dokumentieren, auch für den Datenschutz.
- Backup-Alter in die tägliche Statusmeldung aufnehmen, damit ein ausbleibendes Backup auffällt.
- Kalendereintrag: Restore-Test, vierteljährlich, mit Stoppuhr und Protokoll.
Checkliste: Haben Sie ein Backup oder eine Hoffnung?
- Wissen Sie, wie viele Stunden Daten Sie im schlimmsten Fall verlieren?
- Wissen Sie, wie lange die Wiederherstellung dauert, weil Sie es gemessen haben?
- Meldet sich Ihr Dump-Skript, wenn der Dump scheitert oder verdächtig klein ist?
- Liegt das Backup auf einem anderen System, das der Produktivserver nicht löschen kann?
- Ist der Backup-Server so gehärtet wie der Produktivserver?
- Gibt es eine verschlüsselte Kopie außer Haus?
- Sind Datenbank, hochgeladene Dateien und Konfiguration alle enthalten und aus demselben Lauf?
- Ist das Rotationsschema dokumentiert, und wissen Sie, wie Löschanfragen nach einem Restore behandelt werden?
- Liegt der Schlüssel zum Archiv an mindestens zwei Orten?
- Wann war der letzte echte Restore, und steht er im Protokoll?
Fazit: Die Wiederherstellung ist das Produkt, nicht die Sicherung
Niemand braucht ein Backup. Was man braucht, ist die Fähigkeit, nach einem Ausfall in bekannter Zeit weiterzuarbeiten. Das Backup ist nur das Mittel dazu, und es ist so gut wie der letzte Restore, den Sie gemacht haben. Die Technik dafür ist frei verfügbar, für ein kleines System an einem Nachmittag eingerichtet, für mehrere Systeme mit großen Datenbanken ein eigenes Projekt. Der Restore-Test kostet eine Stunde im Quartal, und das Protokoll dazu ist der Nachweis, den Versicherer, Käufer und große Kunden sehen wollen. Beides zusammen ist die günstigste Versicherung, die ein Betrieb mit einer Webapp abschließen kann.
Sie haben ein Backup, aber die Frage nach dem letzten Restore macht Sie unsicher? Schreiben Sie mir kurz, was gesichert wird und wohin. Ich sehe mir den Aufbau an, sage Ihnen, wo die Lücken sind, und wie ein Restore-Test aussieht, den Sie danach selbst wiederholen können.
Weitere interessante Artikel
Debian Server Setup: Von der Installation bis zum Production-Ready
Debian-Server aufsetzen: von der Installation bis zum Production-Ready-System mit Härtung, Updates, Monitoring und Backup, Schritt für …
Webapp-Wartung & Support: Kosten, SLA & was wirklich nötig ist
Webapp-Wartung und Support: was laufende Pflege kostet, welche SLA sinnvoll sind und was Sie wirklich brauchen, um sicher zu betreiben.
VPN-Standortvernetzung: tinc vs. StrongSwan
VPN-Standortvernetzung im Vergleich: tinc oder StrongSwan für mehrere Standorte, mit Erfahrungen aus dem eigenen Betrieb und klarer …