Vaultwarden ist eine schlanke Neuimplementierung der Bitwarden-Server-API. Die offiziellen Bitwarden-Clients, Browser, Handy, Desktop, sprechen damit, ohne etwas zu merken. Der Ressourcenbedarf liegt bei ein paar hundert Megabyte RAM, was den Dienst zum idealen Bewohner eines kleinen VPS macht.
Bevor es losgeht, eine Einordnung: Der Wechsel von einem gehosteten Passwortmanager zum selbst betriebenen tauscht ein Risiko gegen ein anderes. Statt „ein Anbieter könnte kompromittiert werden“ heißt es „ich bin für Verfügbarkeit und Backup zuständig“. Der Tausch lohnt nur, wenn die zweite Seite ernst genommen wird, deshalb steht der Backup-Abschnitt hier nicht am Ende.
Aufsetzen#
# /opt/vaultwarden/compose.yaml
name: vaultwarden
services:
vaultwarden:
image: vaultwarden/server:1.35.0-alpine
restart: unless-stopped
environment:
DOMAIN: "https://vault.example.com"
# Registrierung offen lassen, bis das eigene Konto steht — danach zu.
SIGNUPS_ALLOWED: "true"
# Admin-Oberfläche: Token als Argon2-Hash, siehe unten
ADMIN_TOKEN: ${ADMIN_TOKEN_HASH}
# Push-Benachrichtigungen und Websockets für sofortige Synchronisierung
WEBSOCKET_ENABLED: "true"
# Weniger Angriffsfläche
SHOW_PASSWORD_HINT: "false"
LOG_LEVEL: "warn"
volumes:
- ./daten:/data
ports:
- "127.0.0.1:8222:80"
mkdir -p /opt/vaultwarden/daten
cd /opt/vaultwarden
docker compose up -d
docker compose logs -f
Davor der Reverse-Proxy:
vault.example.com {
reverse_proxy 127.0.0.1:8222
header {
Strict-Transport-Security "max-age=31536000; includeSubDomains"
X-Frame-Options "DENY"
}
}
Die Bitwarden-Clients verweigern die Verbindung zu einer unverschlüsselten Adresse, zu Recht. Ein gültiges Zertifikat ist hier keine Kür, sondern Voraussetzung für den Betrieb.
Die ersten drei Handgriffe nach dem Start#
1. Eigenes Konto anlegen, dann Registrierung schließen#
Ein offener Vaultwarden im Internet wird gefunden und mit fremden Konten gefüllt. Also: Konto anlegen, danach sofort
SIGNUPS_ALLOWED: "false"
INVITATIONS_ALLOWED: "true" # Einladungen bleiben möglich
docker compose up -d
Weitere Personen kommen dann per Einladung aus der Organisation herein, nicht über ein offenes Formular.
2. Admin-Token als Hash setzen#
Das Admin-Panel unter /admin erlaubt Benutzerverwaltung und Konfigurationsänderungen. Ein Klartext-Token in der Umgebungsvariable steht in jedem docker inspect. Vaultwarden nimmt stattdessen einen Argon2-Hash:
docker run --rm -it vaultwarden/server:1.35.0-alpine /vaultwarden hash
# fragt nach dem Token, gibt einen $argon2id$... -String aus
Diesen String in die .env als ADMIN_TOKEN_HASH, das Klartext-Token in den Passwortmanager. Wer das Panel gar nicht braucht, lässt ADMIN_TOKEN weg, dann ist es abgeschaltet.
3. Zwei-Faktor aktivieren#
Im Web-Tresor unter Einstellungen → Zwei-Faktor-Anmeldung. TOTP genügt; wer einen Hardware-Token hat, kann WebAuthn nutzen.
Vaultwarden zeigt beim Einrichten der Zwei-Faktor-Anmeldung einen Wiederherstellungscode. Der gehört ausgedruckt oder auf einen zweiten Datenträger, nicht in den Tresor, den er entsperren soll. Das klingt offensichtlich und passiert trotzdem regelmäßig.
Backup: der Teil, der wirklich zählt#
Vaultwarden legt alles in /data ab: eine SQLite-Datenbank, Anhänge, den rsa_key-Satz für die Sitzungsverwaltung. Die Datenbank darf nicht im laufenden Betrieb kopiert werden, SQLite schreibt währenddessen weiter.
#!/bin/bash
# /usr/local/bin/vaultwarden-backup.sh
set -euo pipefail
DATEN=/opt/vaultwarden/daten
ZIEL=/var/backups/vaultwarden
STAMP=$(date +%F)
mkdir -p "$ZIEL"
# Konsistente Kopie der Datenbank — .backup statt cp
docker compose -f /opt/vaultwarden/compose.yaml exec -T vaultwarden \
sqlite3 /data/db.sqlite3 ".backup '/data/db-backup.sqlite3'"
tar czf "$ZIEL/vaultwarden-$STAMP.tar.gz" \
-C "$DATEN" db-backup.sqlite3 attachments sends config.json rsa_key.pem rsa_key.pub.pem 2>/dev/null || true
rm -f "$DATEN/db-backup.sqlite3"
# Verschlüsselt weg vom Server — siehe Backup-Beitrag
restic backup "$ZIEL/vaultwarden-$STAMP.tar.gz" --tag vaultwarden
find "$ZIEL" -name 'vaultwarden-*.tar.gz' -mtime +14 -delete
# /etc/systemd/system/vaultwarden-backup.timer
[Unit]
Description=Tägliche Vaultwarden-Sicherung
[Timer]
OnCalendar=*-*-* 02:40:00
Persistent=true
[Install]
WantedBy=timers.target
Der Rest, Aufbewahrung, zweites Ziel, Verschlüsselungspasswort, steht in Backup-Strategie 3-2-1.
Warum rsa_key.pem mit muss#
Wird nur die Datenbank gesichert und der Schlüsselsatz nicht, funktioniert die Wiederherstellung scheinbar, aber alle bestehenden Sitzungen sind ungültig, und je nach Version bekommt man Anmeldeprobleme, die schwer zuzuordnen sind. Die Datei ist wenige Kilobyte groß; es gibt keinen Grund, sie wegzulassen.
Der Notfallplan#
Ein selbst gehosteter Passwortmanager hat eine unangenehme Eigenschaft: Wenn er weg ist, fehlen auch die Zugangsdaten, mit denen man ihn wiederherstellen würde.
Drei Vorkehrungen, die dieses Problem lösen:
-
Der Client hat einen lokalen Zwischenspeicher. Browser-Erweiterung und Handy-App halten den Tresor verschlüsselt lokal vor und funktionieren offline weiter. Das verschafft Zeit, verlass dich aber nicht darauf, dass er nach einer Neuinstallation noch da ist.
-
Ein regelmäßiger Export als Notfallkopie. Im Web-Tresor unter Werkzeuge → Tresor exportieren, Format „verschlüsselt (Passwortgeschützt)“. Diese Datei auf einen USB-Stick, den Stick an einen anderen Ort. Vierteljährlich erneuern.
-
Die Zugangsdaten, die man zum Wiederaufbau braucht, außerhalb des Tresors. Das sind typischerweise vier: SSH-Schlüssel-Passphrase, Zugang zum Kundenpanel des Anbieters, das restic-Passwort und das Master-Passwort selbst. Auf Papier, an einem sicheren Ort.
Der Export im JSON- oder CSV-Format enthält alle Passwörter im Klartext. Er ist praktisch für den Umzug zwischen Passwortmanagern und danach sofort sicher zu löschen, inklusive Papierkorb und Downloads-Ordner. Für Notfallkopien immer die verschlüsselte Variante.
Wiederherstellung üben#
Einmal im Jahr, zwanzig Minuten:
# Sicherung an einen Testort auspacken
mkdir -p /tmp/vw-test && tar xzf /var/backups/vaultwarden/vaultwarden-2026-04-20.tar.gz -C /tmp/vw-test
mv /tmp/vw-test/db-backup.sqlite3 /tmp/vw-test/db.sqlite3
# Zweite Instanz auf einem anderen Port starten
docker run --rm -d --name vw-test -p 127.0.0.1:8223:80 \
-v /tmp/vw-test:/data vaultwarden/server:1.35.0-alpine
# Über einen SSH-Tunnel im Browser aufrufen und anmelden:
# ssh -L 8223:127.0.0.1:8223 user@server
docker stop vw-test && rm -rf /tmp/vw-test
Wer sich in dieser Testinstanz anmelden und einen Eintrag sehen kann, hat ein funktionierendes Backup. Alles andere ist eine Vermutung.
Aktuell halten#
Vaultwarden erscheint regelmäßig in neuen Versionen, und einzelne davon schließen sicherheitsrelevante Lücken. Das Vorgehen, Version festnageln, vor dem Update sichern, Changelog lesen, steht in Container aktuell halten. Bei diesem Dienst ist das kein optionaler Zusatzaufwand.
Kurz gefasst#
- HTTPS ist Voraussetzung, nicht Kür.
- Registrierung schließen, sobald das eigene Konto steht.
ADMIN_TOKENnur als Hash, oder gar nicht.- Backup mit
sqlite3 .backup, inklusiversa_key.pem, verschlüsselt weg vom Server. - Papier-Notfallkopie an einem anderen Ort, vierteljährlich erneuert.
- Einmal im Jahr eine Wiederherstellung durchspielen.
Geschrieben aus dem laufenden Betrieb: MRMedia betreibt eigene Proxmox- Hosts, einen Backup-Server und Kundendienste in der EU. Fehler in einer Anleitung sind Fehler im eigenen Betrieb. Korrekturen bitte über Discord.