SSD Nodes Learn Hosting plans →
Anleitungen Matt ConnorVon Matt Connor · Aktualisiert 2026-08-25

Vaultwarden-Backup und Restore auf einem VPS

Sichern Sie eine laufende Vaultwarden-Datenbank mit sqlite3 .backup, bewahren Sie Anhänge, config.json und rsa_key-Dateien auf und testen Sie den Restore.

Verified Every command ran end-to-end on a fresh Ubuntu 24.04 server, August 5, 2026.

Was ein Vaultwarden-Backup enthalten muss

Ein Vaultwarden-Backup ist eine Kopie des gesamten Datenverzeichnisses. Die darin enthaltene Datenbank muss auf die richtige Weise kopiert werden. Verwenden Sie sqlite3 db.sqlite3 ".backup out.sqlite3" statt cp, weil eine einfache Kopie einer Datenbank, in die gerade geschrieben wird, eine Datei erzeugen kann, die sich nicht öffnen lässt. Sichern Sie anschließend auch die Dateien, die daneben liegen. Dieser Teil wird häufig vergessen.

Bei einer Docker-Installation ist das Datenverzeichnis der Pfad, den Sie auf /data eingebunden haben. Dabei handelt es sich entweder um einen Pfad auf dem Host oder um ein benanntes Volume. Der Unterschied zwischen Bind Mounts und benannten Volumes bestimmt, wo Ihr Tresor tatsächlich auf der Festplatte liegt. Das Verzeichnis enthält Folgendes.

  • db.sqlite3: jedes Konto, jedes Tresorelement, jeden Ordner und jede Organisation. Wenn diese Datei verloren geht, ist der Tresor verloren.
  • db.sqlite3-wal und db.sqlite3-shm: das Write-Ahead-Log (WAL) und seinen Shared-Memory-Index. Kürzlich vorgenommene Schreibvorgänge werden hier gespeichert, bis SQLite sie in die Hauptdatei übernimmt.
  • attachments/: die Dateien, die Benutzer an Tresorelemente angehängt haben, verschlüsselt und in jeweils einem Verzeichnis pro Element.
  • sends/: die Dateien hinter Bitwarden-Send-Links.
  • config.json: jede Einstellung, die Sie auf der Administrationsseite gespeichert haben.
  • rsa_key.pem sowie bei älteren Installationen rsa_key.der und rsa_key.pub.der: der Schlüssel zum Signieren von Anmeldetokens.
  • icon_cache/: heruntergeladene Website-Symbole. Dieses eine Verzeichnis können Sie auslassen, weil Vaultwarden die Symbole bei Bedarf erneut abruft.

Ist meine Vaultwarden-Datenbank sicher? Was die Datei tatsächlich enthält

Zwei Befehle beantworten diese Frage. Sie können beide sofort ausführen.

sudo apt update && sudo apt install -y sqlite3
sudo sqlite3 /opt/vaultwarden/data/db.sqlite3 "select email from users;"
sudo sqlite3 /opt/vaultwarden/data/db.sqlite3 "select name from ciphers limit 1;"

Der erste gibt die E-Mail-Adressen Ihrer Benutzer im Klartext aus. Der zweite gibt einen Elementnamen aus. Er sieht so aus:

2.k9Qw1nQ0y7Yy2Xw==|E1r0J3l5s7d9f1g3h5j7k9==|Lm4nOp6qRs8tUv0wXy2zAb4cDe6fGh8i=

Elementnamen, Benutzernamen, Passwörter und Notizen werden vom Client verschlüsselt, bevor sie gesendet werden. Der Server speichert daher Chiffretext, den er nicht lesen kann. Das Präfix 2. bezeichnet den Verschlüsselungstyp von Bitwarden. Darauf folgen ein Initialisierungsvektor (IV), der Chiffretext und ein MAC (Message Authentication Code), jeweils in base64 und durch | getrennt. Der Schlüssel für die Entschlüsselung wird aus dem Master-Passwort des Kontos abgeleitet. Dieses erreicht den Server nie in einer nutzbaren Form. Dieser Teil ist identisch, unabhängig davon, ob Sie Vaultwarden oder den offiziellen Server betreiben, wie der Vergleich von Vaultwarden und selbst gehostetem Bitwarden ausführlich erläutert.

Der restliche Teil der Datenbank ist nicht verschlüsselt. E-Mail-Adressen, Kontonamen, Passworthinweise und Wiederherstellungscodes für die Zwei-Faktor-Authentifizierung werden im Klartext gespeichert, zusammen mit Metadaten wie Erstellungszeitpunkten und der Organisation, der ein Element gehört. Daher ist die Sicherungskopie selbst ein Geheimnis. Jeder, der sie besitzt, erfährt, wer Ihre Benutzer sind, und kann die verschlüsselten Datenblöcke offline mit der von seiner Hardware erlaubten Geschwindigkeit angreifen. Diese eine Tatsache bestimmt die weiter unten beschriebenen Regeln für die Speicherung: Die Kopie wird verschlüsselt, bevor sie den Server verlässt. Das Admin-Token ist die andere Hälfte desselben Problems. Die Härtung eines selbst gehosteten Vaultwarden behandelt beide Aspekte.

Warum das Kopieren von db.sqlite3 während des Betriebs von Vaultwarden kein Backup ist

Vaultwarden verwendet SQLite standardmäßig im WAL-Modus (ENABLE_DB_WAL=true). Ein Schreibvorgang wird zunächst in db.sqlite3-wal geschrieben. Erst ein Checkpoint übernimmt ihn in db.sqlite3. Wenn Sie db.sqlite3 allein kopieren, erhalten Sie den Datenbankstand des letzten Checkpoints. Ein vor zehn Minuten gespeichertes Passwort kann deshalb im Archiv fehlen, ohne dass eine Warnung ausgegeben wird.

Auch das Kopieren aller drei Dateien mit cp ist keine Lösung. Die Kopien werden zu leicht unterschiedlichen Zeitpunkten erstellt. Dadurch kann das gesicherte WAL Seitenversionen beschreiben, die nicht mehr zum ebenfalls kopierten Hauptbestand passen. SQLite führt dann eine Wiederherstellung aus den Dateien durch. Das Ergebnis ist falsch. Sie bemerken das erst deutlich später:

Error: database disk image is malformed

.backup vermeidet dieses Problem, weil es die SQLite Online Backup API verwendet. SQLite dokumentiert diese API als vorgesehenen Weg, eine Datenbank zu kopieren, die aktiv verwendet werden kann. Die API liest die Seiten unter einer Lesesperre. Wenn ein Schreibvorgang die Datei währenddessen ändert, beginnt sie von vorn. Dadurch entspricht der auf dem Datenträger gespeicherte Stand einem konsistenten Zeitpunkt.

Erstellen Sie die Datenbankkopie mit sqlite3 .backup

sudo apt update && sudo apt install -y sqlite3
sudo install -d -m 700 /var/backups/vaultwarden
OUT=/var/backups/vaultwarden/db-$(date '+%Y%m%d-%H%M').sqlite3
sudo sqlite3 /opt/vaultwarden/data/db.sqlite3 ".backup '$OUT'"
sudo sqlite3 "$OUT" "PRAGMA integrity_check;"

Der letzte Befehl gibt ok in einer eigenen Zeile aus. Jede andere Ausgabe bedeutet, dass die Kopie nicht verwendbar ist. Behalten Sie sie dann nicht und löschen Sie die vorherige Kopie nicht. Die gesamte Sequenz läuft auf einem aktiven Server. Niemand wird abgemeldet und kein Container wird neu gestartet.

Das Tool sqlite3 ist nicht im Vaultwarden-Container enthalten. Das Image basiert auf debian:trixie-slim mit ca-certificates, curl, libmariadb3, libpq5 und openssl. Deshalb schlägt docker exec vaultwarden sqlite3 ... mit folgendem Fehler fehl:

exec: "sqlite3": executable file not found in $PATH

Führen Sie den Befehl stattdessen auf dem Host für den eingebundenen Pfad aus. Genau das machen die obigen Befehle. Wenn die Daten in einem benannten Volume liegen, gibt docker volume inspect <name> den Hostpfad unter /var/lib/docker/volumes/ aus.

Vaultwarden liefert seit Version 1.32.1 außerdem einen eigenen Backup-Befehl aus. Führen Sie auf Ihrem Server Folgendes aus:

docker exec -it vaultwarden /vaultwarden backup

Der Befehl führt VACUUM INTO aus und schreibt db_YYYYMMDD_HHMMSS.sqlite3 in den Datenordner. Daraus ergeben sich zwei Punkte. Die Kopie liegt auf demselben Datenträger neben dem Original. Daher ist dies nur ein Bereitstellungsschritt und noch kein Backup. Außerdem funktioniert der Befehl nur mit SQLite. Bei MariaDB oder PostgreSQL bricht er mit The database type is not SQLite. Backups only works for SQLite databases ab.

Die Dateien, die häufig vergessen werden

attachments/ enthält Chiffretext unter nichtssagenden Dateinamen. Der Datenbankeintrag für jeden Anhang enthält dessen verschlüsselten Dateinamen sowie das Schlüsselmaterial, das ein Client zum Entschlüsseln der Datei benötigt. Anhänge ohne die Datenbank sind unlesbare Daten. Eine Datenbank ohne die Anhänge führt zu Einträgen, deren Downloads fehlschlagen. Sichern Sie beides im selben Durchlauf.

config.json enthält alles, was Sie auf der Admin-Seite gespeichert haben. Die dort gespeicherten Werte haben Vorrang vor den entsprechenden Umgebungsvariablen. Das kann in beide Richtungen problematisch sein: Beim Wiederherstellen einer alten config.json werden die Einstellungen in Ihrer Compose-Datei stillschweigend überschrieben. Außerdem ist die Datei selbst vertraulich, weil sie Ihr SMTP-Passwort und Ihr Admin-Token enthalten kann. Speichern Sie dieses Token als Argon2id-PHC-(password hashing competition-)String und nicht als Klartext. docker run --rm -it vaultwarden/server /vaultwarden hash gibt einen solchen String aus.

rsa_key.pem signiert die JSON Web Tokens (JWT), mit denen Clients angemeldet bleiben. Fehlt die Datei beim Start, erzeugt Vaultwarden einen neuen Schlüssel. Dadurch sind alle mit dem alten Schlüssel signierten Tokens nicht mehr gültig, und alle Clients werden abgemeldet. Die Inhalte des Vaults bleiben erhalten, weil sie mit aus dem Master-Passwort abgeleiteten Schlüsseln verschlüsselt sind. Durch das Wiederherstellen der Schlüsseldatei vermeiden Sie die Abmeldung aller Clients.

sends/ enthält die Dateien hinter Send-Links. Fehlen diese Dateien, schlagen die entsprechenden Downloads fehl. Andere Funktionen sind nicht betroffen.

Das Ganze in ein Skript aufnehmen

#!/bin/bash
set -euo pipefail

DATA=/opt/vaultwarden/data
DEST=/var/backups/vaultwarden
STAMP=$(date '+%Y%m%d-%H%M%S')
STAGE=$(mktemp -d /tmp/vw-stage.XXXXXX)

install -d -m 700 "$DEST"
sqlite3 "$DATA/db.sqlite3" ".backup '$STAGE/db.sqlite3'"
test "$(sqlite3 "$STAGE/db.sqlite3" 'PRAGMA integrity_check;')" = "ok"
cp -a "$DATA"/rsa_key* "$STAGE/"
for extra in config.json attachments sends; do
  if [ -e "$DATA/$extra" ]; then cp -a "$DATA/$extra" "$STAGE/"; fi
done
tar -C "$STAGE" -czf "$DEST/vw-$STAMP.tar.gz" .
chmod 600 "$DEST/vw-$STAMP.tar.gz"
rm -rf "$STAGE"
tar -tzf "$DEST/vw-$STAMP.tar.gz"

Speichern Sie das Skript als /usr/local/sbin/vw-backup.sh, machen Sie es mit chmod 700 ausführbar und führen Sie es als root aus. Die Zeile test übernimmt die eigentliche Fehlerbehandlung: sqlite3 beendet sich auch dann mit Exit-Code 0, wenn PRAGMA integrity_check eine Beschädigung meldet. Erst der Vergleich der Ausgabe mit ok führt daher dazu, dass eine fehlerhafte Kopie als fehlgeschlagenes Skript behandelt wird. set -euo pipefail beendet anschließend den gesamten Ablauf, statt tar ein formal korrektes Archiv um eine beschädigte Datenbank erstellen zu lassen.

tar -tzf listet abschließend auf, welche Daten tatsächlich erfasst wurden. Lesen Sie die Ausgabe beim ersten Durchlauf. Achten Sie auf ./db.sqlite3, ./rsa_key.pem, ./config.json und ./attachments/ sowie darauf, dass ./db.sqlite3-wal nicht vorhanden ist. Führen Sie das Skript jede Nacht mit einem systemd-Service und Timer statt mit cron aus, wenn Sie eine Ausgabe mit journalctl und eine Unit wünschen, die Fehler meldet.

Die Sicherung durch eine Wiederherstellung in ein temporäres Verzeichnis prüfen

Eine nicht getestete Sicherung ist nur eine Vermutung. Die Wiederherstellung in ein temporäres Verzeichnis dauert eine Minute und verändert keine laufenden Daten.

sudo install -d -m 700 /tmp/vw-check
sudo tar -C /tmp/vw-check -xzf /var/backups/vaultwarden/vw-20260805-030000.tar.gz
ls -l /tmp/vw-check
sudo sqlite3 /tmp/vw-check/db.sqlite3 "PRAGMA integrity_check;"
sudo sqlite3 /tmp/vw-check/db.sqlite3 "select count(*) from users;"
sudo sqlite3 /tmp/vw-check/db.sqlite3 "select count(*) from ciphers;"
sudo du -sh /tmp/vw-check/attachments

Vier Ergebnisse sind relevant. integrity_check gibt ok aus. Die Anzahl der Benutzer entspricht der Zahl der bekannten Konten. Die Anzahl der Chiffren liegt nahe am aktuellen Wert aus sudo sqlite3 /opt/vaultwarden/data/db.sqlite3 "select count(*) from ciphers;" und ist bei einem verwendeten Tresor niemals null. Das Verzeichnis für Anhänge hat ungefähr die erwartete Größe. Diese Prüfung können Sie überspringen, wenn niemand Anhänge hochlädt. Führen Sie anschließend sudo rm -rf /tmp/vw-check aus, da dieses Verzeichnis nun eine zweite Kopie aller Daten enthält.

Beachten Sie beim Wiederherstellen eines manuell kopierten Datenverzeichnisses eine Regel: Löschen Sie db.sqlite3-wal und db.sqlite3-shm, bevor Sie den Server starten. SQLite versucht sonst, die wiederhergestellte Datenbank mit einem Log wiederherzustellen, das zu einer anderen Kopie gehört. Dadurch kann eine unbeschädigte Datenbank beschädigt werden. Die vom obigen Skript erzeugten Archive enthalten diese Dateien nie, weil .backup eine vollständige Datenbank schreibt.

Auf dem Server wiederherstellen

Führen Sie diese Befehle auf Ihrem eigenen Server aus, während der Container gestoppt ist. Vaultwarden darf nicht schreiben, während der Datenordner geändert wird.

cd /opt/vaultwarden
docker compose stop vaultwarden
sudo mv data data.old.$(date '+%Y%m%d-%H%M%S')
sudo install -d -m 700 data
sudo tar -C data -xzf /var/backups/vaultwarden/vw-20260805-030000.tar.gz
sudo chown -R root:root data
docker compose start vaultwarden
docker compose logs --tail 20 vaultwarden

chown muss den Benutzer angeben, unter dem der Container ausgeführt wird. Das Standard-Image wird als root ausgeführt. Daher ist root:root korrekt, sofern Sie user: nicht in Ihrer Compose-Datei gesetzt haben. Verwenden Sie in diesem Fall die dort angegebene UID und GID. Wenn der Server nicht in den Datenordner schreiben kann, wird zwar eine Anmeldeseite angezeigt, aber jede Anfrage schlägt fehl. Die Logs weisen auf die Ursache hin.

Ein erfolgreicher Start endet mit der Rocket-Zeile:

[INFO] Rocket has launched from http://0.0.0.0:80

Melden Sie sich anschließend im Browser an, öffnen Sie ein Element und laden Sie einen Anhang herunter. Wenn die Anmeldung funktioniert, aber der Download von Anhängen fehlschlägt, enthält das Archiv zwar die Datenbank, aber nicht attachments/. Behalten Sie data.old.*, bis alle Prüfungen erfolgreich sind, und löschen Sie es anschließend. Für ein Rollback führen Sie dieselben drei Schritte aus und vertauschen dabei die Verzeichnisse.

Wenn Ihre Pfade nicht mit den hier verwendeten übereinstimmen, zeigt die Vaultwarden-Installationsanleitung für einen VPS die Compose-Datei, von der diese Befehle ausgehen.

Wohin Sie das Backup nicht speichern sollten

  • Nicht auf derselben Festplatte wie den Datenordner. Ein ausgefallenes Volume zerstört beide Kopien. Das gilt auch für ein rm -rf am falschen Pfad.
  • Nicht auf demselben Server, auch nicht auf einem zweiten Volume. Ein Angreifer, der root erreicht, kann in derselben Sitzung auch auf Ihre Backups zugreifen.
  • Nicht ohne Verschlüsselung im Object Storage, weil das Archiv E-Mail-Adressen, Passwort-Hinweise, Wiederherstellungscodes und Vault-Chiffretext enthält, die offline angegriffen werden können.
  • Nicht ausschließlich in den Snapshots Ihres Providers. Sie lassen sich schnell wiederherstellen, was sinnvoll ist. Sie befinden sich jedoch im selben Konto wie der Server. Daher betrifft ein Konto-Problem auch die Snapshots.

Für eine Offsite-Kopie eignet sich restic, weil ein restic-Repository auf dem Rechner verschlüsselt wird, bevor Daten hochgeladen werden. Auf Ihrem Server:

sudo apt install -y restic
export RESTIC_REPOSITORY=s3:https://s3.example.com/vaultwarden-backups
export RESTIC_PASSWORD_FILE=/root/.restic-password
restic init
restic backup /var/backups/vaultwarden --tag vaultwarden
restic snapshots --tag vaultwarden
restic forget --tag vaultwarden --keep-daily 7 --keep-weekly 4 --keep-monthly 6 --prune

Verweisen Sie restic auf das Archivverzeichnis und nicht auf den Verzeichnis mit den Live-Daten. Dadurch wird die konsistente Kopie hochgeladen, die Sie bereits geprüft haben. Bewahren Sie das Repository-Passwort an einem anderen Ort als auf dem geschützten Server auf. Ohne dieses Passwort sind die Snapshots absichtlich nicht lesbar. Wenn der Speicher dies unterstützt, geben Sie dem Server Zugangsdaten, mit denen er schreiben, aber nicht löschen kann. So kann ein kompromittierter Server seine eigene Historie nicht löschen. restic-Backups auf einem VPS einrichten beschreibt Repository und Zeitplan vollständig. restic im Vergleich zu BorgBackup unterstützt Sie bei der Auswahl, falls diese noch nicht getroffen ist.

Testen Sie die Wiederherstellung nach einem festen Zeitplan

Wählen Sie einen Tag pro Monat aus. Kopieren Sie den neuesten Snapshot mit restic restore latest --tag vaultwarden --target /tmp/vw-check in ein temporäres Verzeichnis, führen Sie denselben PRAGMA integrity_check aus und ermitteln Sie dieselben Zeilenanzahlen. Notieren Sie anschließend das Datum und die Anzahlen. Ein Backup, aus dem seit sechs Monaten keine Wiederherstellung durchgeführt wurde, hat einen unbekannten Zustand. Sie ermitteln diesen Zustand erst bei einem Ausfall. Das ist der schlechteste Zeitpunkt dafür.

Führen Sie einmal pro Jahr den vollständigen Test durch. Starten Sie einen zweiten Vaultwarden-Container auf einem freien Port mit dem wiederhergestellten Datenverzeichnis und melden Sie sich mit einem echten Konto an. Damit prüfen Sie den Pfad des Master-Passworts von Anfang bis Ende. Keine Zeilenanzahl kann das leisten. restic check --read-data-subset=10% nach demselben Zeitplan stellt sicher, dass die gespeicherten Daten lesbar und nicht nur aufgelistet sind.

FAQ

Kann ich db.sqlite3 mit cp kopieren, während Vaultwarden läuft?

Nein. Vaultwarden verwendet SQLite im WAL-Modus. Aktuelle Schreibvorgänge befinden sich daher in db.sqlite3-wal und noch nicht in db.sqlite3. Eine cp nur der Hauptdatei verliert diese Änderungen unbemerkt. Werden die beiden Dateien separat kopiert, kann ein nicht zusammenpassendes Paar entstehen, das später als Error: database disk image is malformed sichtbar wird. Verwenden Sie stattdessen sqlite3 /path/db.sqlite3 ".backup '/path/out.sqlite3'". Dieser Befehl verwendet die SQLite Online Backup API und erstellt eine konsistente Datei, während der Server weiterhin Anfragen verarbeitet.

Muss ich den Vaultwarden-Container für ein Backup stoppen?

Nein. Genau dafür ist .backup gedacht. Die Datenbank kann auf einem laufenden Server sicher kopiert werden. Anhänge und Send-Dateien werden geschrieben, sobald ein Benutzer eine Datei hochlädt. Eine Datei, die zwischen dem Kopieren der Datenbank und dem tar hinzugefügt wird, kann daher im Archiv dieser Nacht fehlen. Im ungünstigsten Fall verlieren Sie dadurch einen Anhang. Wenn wenige Sekunden Ausfallzeit akzeptabel sind, entfernt docker compose stop vor dem Skript und docker compose start danach auch dieses Risiko.

Was passiert, wenn ich die rsa_key.pem-Dateien nicht wiederherstelle?

Vaultwarden erzeugt beim Start einen neuen Schlüssel. Dieser Schlüssel signiert die JSON Web Tokens (JWT), die Sitzungen aktiv halten. Daher werden alle vorhandenen Tokens ungültig. Alle Clients werden abgemeldet und müssen sich erneut anmelden. Die Tresorinhalte bleiben unverändert, weil sie mit Schlüsseln verschlüsselt sind, die aus dem Master-Passwort des jeweiligen Benutzers abgeleitet werden, und nicht mit dem RSA-Schlüssel. Stellen Sie rsa_key.pem zusammen mit dem restlichen Datenordner wieder her. Dann bemerkt niemand die Wiederherstellung.

Ist das Backup-Archiv sicher, wenn ich es unverändert in Object Storage hochlade?

Nein. Elementnamen, Passwörter und Notizen sind Chiffretext. E-Mail-Adressen, Kontonamen, Passworthinweise und Wiederherstellungscodes für die Zwei-Faktor-Authentifizierung liegen jedoch als Klartext in der Datenbank vor. Ein Angreifer kann den Chiffretext offline mit beliebigem Zeitaufwand analysieren. Verschlüsseln Sie das Archiv, bevor es den Rechner verlässt. Ein restic-Repository übernimmt diese Aufgabe für Sie. gpg --symmetric --cipher-algo AES256 vw-20260805-030000.tar.gz erstellt eine einzelne verschlüsselte Datei, die Sie an beliebigen Storage übergeben können.

Wie sichere ich Vaultwarden mit PostgreSQL oder MariaDB?

Die Schritte für SQLite gelten hier nicht. Der integrierte Befehl bricht mit The database type is not SQLite. Backups only works for SQLite databases ab. Sichern Sie die Datenbank mit dem jeweils nativen Werkzeug, pg_dump oder mysqldump, und befolgen Sie alle übrigen Regeln unverändert. Der Dump gehört zusammen mit attachments/, sends/, config.json und den rsa_key-Dateien in ein gemeinsames Archiv. Alle Bestandteile müssen im selben Durchlauf erstellt, verschlüsselt und an einem anderen Ort als dem Server gespeichert werden, auf dem das Backup erstellt wurde.