Vaultwarden auf einem VPS mit Docker Compose selbst hosten
Richten Sie einen gehärteten Vaultwarden-Passwortmanager auf Ihrem VPS ein. Docker Compose mit schreibgeschützten Containern, fail2ban, SMTP für 2FA, Backup und Wiederherstellung sowie Notfallzugriff.
Vaultwarden speichert sämtliche Passwörter, die Sie besitzen. Ein nachlässiges Deployment ist schlimmer als gar keines. Dieses Tutorial richtet Vaultwarden auf einem VPS mit gehärteten Docker-Containern, fail2ban, SMTP für Zwei-Faktor-Authentifizierung und einer Backup-und-Wiederherstellungsprozedur ein.
Wir setzen voraus, dass Docker Engine und ein Reverse Proxy (Nginx oder Caddy) bereits auf Ihrem Server laufen. Falls nicht, beginnen Sie mit Docker in Produktion auf einem VPS: Was schiefgeht und wie Sie es beheben und Nginx als Reverse Proxy konfigurieren.
Was ist Vaultwarden und wie unterscheidet es sich von Bitwarden?
Vaultwarden ist eine Rust-Reimplementierung der Bitwarden-Server-API. Es läuft als einzelner Docker-Container, verwendet standardmäßig SQLite, verbraucht im Leerlauf etwa 50 MB RAM und ist vollständig kompatibel mit allen offiziellen Bitwarden-Clients (Browser-Erweiterungen, Mobile-Apps, Desktop, CLI). Das offizielle selbst gehostete Bitwarden-Deployment benötigt mehr als 11 Container und mindestens 4 GB RAM.
| Vaultwarden | Bitwarden selbst gehostet | |
|---|---|---|
| Sprache | Rust | C# (.NET) |
| Container | 1 | 11+ |
| RAM (Leerlauf) | ~50 MB | ~2-4 GB |
| Datenbank | SQLite (Standard), MySQL, PostgreSQL | MSSQL (erforderlich) |
| Bitwarden-Client-Unterstützung | Vollständig | Vollständig |
| SSO (OpenID Connect) | Seit Version 1.35.0 | Nur Enterprise-Plan |
| Offizieller Support | Community | Bitwarden Inc. |
| Lizenz | AGPL-3.0 | Proprietär (SSPL für Server) |
Vaultwarden hieß früher bitwarden_rs. Falls Sie diesen Namen in älteren Anleitungen sehen, handelt es sich um dasselbe Projekt.
Wie deploye ich Vaultwarden mit Docker Compose auf einem VPS?
Erstellen Sie eine Verzeichnisstruktur für Vaultwarden-Daten und -Konfiguration. Alle persistenten Daten liegen in einem einzigen Verzeichnis, das Sie später sichern werden.
mkdir -p /opt/vaultwarden/data
cd /opt/vaultwarden
Generieren Sie ein Argon2-gehashtes Admin-Token. Speichern Sie das Admin-Token niemals im Klartext.
docker run --rm -it vaultwarden/server:1.35.4 /vaultwarden hash
Der Befehl fragt zweimal nach einem Passwort und gibt dann einen Argon2id-PHC-String aus:
Generate an Argon2id PHC string using the 'bitwarden' preset:
Password:
Confirm Password:
ADMIN_TOKEN='$argon2id$v=19$m=65540,t=3,p=4$S2mMOA8VnTtIOb3J8Gj9Jw$9cZ0YIKmGxfWEqSMKFMbORkBiW7hMGCls3SXAFXSIVE'
Speichern Sie diesen String. Sie benötigen ihn in der Umgebungsdatei.
Erstellen Sie die Secrets-Datei mit eingeschränkten Berechtigungen:
touch /opt/vaultwarden/.env
chmod 600 /opt/vaultwarden/.env
Bearbeiten Sie /opt/vaultwarden/.env mit Ihren Werten:
DOMAIN=https://vault.example.com
ADMIN_TOKEN='$argon2id$v=19$m=65540,t=3,p=4$your-hash-here'
SIGNUPS_ALLOWED=true
INVITATIONS_ALLOWED=true
EMERGENCY_ACCESS_ALLOWED=true
ORG_CREATION_USERS=all
SHOW_PASSWORD_HINT=false
IP_HEADER=X-Real-IP
LOG_FILE=/data/vaultwarden.log
LOG_LEVEL=warn
SMTP_HOST=smtp.example.com
SMTP_FROM=vault@example.com
SMTP_PORT=587
SMTP_SECURITY=starttls
SMTP_USERNAME=vault@example.com
SMTP_PASSWORD=your-smtp-password
SHOW_PASSWORD_HINT=false verhindert, dass Hinweise an jeden preisgegeben werden, der einen Benutzernamen kennt. IP_HEADER=X-Real-IP weist Vaultwarden an, die Client-IP aus dem Header Ihres Reverse Proxys zu lesen, was notwendig ist, damit fail2ban die richtige Adresse sperrt.
Erstellen Sie nun die Compose-Datei.
Wie härte ich den Vaultwarden-Docker-Container?
Die folgende Compose-Datei pinnt die Image-Version, entfernt alle Linux-Capabilities, aktiviert ein schreibgeschütztes Root-Dateisystem, blockiert Privilege Escalation und setzt Speicherlimits. Dies sind die Standardeinstellungen dieser Anleitung, keine optionalen Ergänzungen.
Erstellen Sie /opt/vaultwarden/compose.yaml:
services:
vaultwarden:
image: vaultwarden/server:1.35.4
container_name: vaultwarden
restart: unless-stopped
env_file: .env
user: "1000:1000"
security_opt:
- no-new-privileges:true
cap_drop:
- ALL
read_only: true
tmpfs:
- /tmp
volumes:
- ./data:/data
ports:
- "127.0.0.1:8080:80"
deploy:
resources:
limits:
memory: 512M
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:80/alive"]
interval: 30s
timeout: 5s
retries: 3
user: "1000:1000"führt den Prozess als Nicht-Root-Benutzer im Container aus. Sie müssen den Besitz des Datenverzeichnisses entsprechend setzen:chown -R 1000:1000 /opt/vaultwarden/data.cap_drop: ALLentfernt alle Linux-Capabilities. Vaultwarden benötigt keine, da es auf Port 80 im Container lauscht (ein unprivilegierter Port in diesem Kontext, da Docker das Mapping übernimmt).read_only: trueverhindert, dass der Container irgendwo schreibt, außer in explizit gemountete Volumes und tmpfs. Falls Vaultwarden kompromittiert wird, kann nichts ins Container-Dateisystem geschrieben werden.ports: "127.0.0.1:8080:80"bindet nur an localhost. Der Reverse Proxy übernimmt den externen Traffic. Setzen Sie Vaultwarden niemals direkt dem Internet aus.deploy.resources.limits.memory: 512Mverhindert, dass ein außer Kontrolle geratener Prozess den gesamten Server-RAM verbraucht. Vaultwarden nutzt ~50 MB im Leerlauf und ~100-150 MB unter Last. 512 MB bieten reichlich Spielraum.
Korrigieren Sie die Verzeichnisberechtigungen und starten Sie den Container:
chown -R 1000:1000 /opt/vaultwarden/data
docker compose up -d
[+] Running 1/1
✔ Container vaultwarden Started
Prüfen Sie den Container-Status:
docker compose ps
NAME IMAGE COMMAND SERVICE CREATED STATUS PORTS
vaultwarden vaultwarden/server:1.35.4 "/start.sh" vaultwarden Up 30 seconds (healthy) 127.0.0.1:8080->80/tcp
Der Status (healthy) bedeutet, dass der Healthcheck bestanden wurde. Prüfen Sie die Logs auf Startfehler:
docker compose logs --tail 20
Die Logs zeigen, dass Vaultwarden auf Port 80 im Container startet, ohne Fehler.
Reverse-Proxy-Konfiguration
Ihr Reverse Proxy leitet HTTPS-Traffic an 127.0.0.1:8080 weiter. Hier ein minimaler Nginx-Serverblock:
server {
listen 443 ssl;
http2 on;
server_name vault.example.com;
ssl_certificate /etc/letsencrypt/live/vault.example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/vault.example.com/privkey.pem;
client_max_body_size 525M;
server_tokens off;
location / {
proxy_pass http://127.0.0.1:8080;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
}
client_max_body_size 525M erlaubt Dateianhang-Uploads bis zum Bitwarden-Limit. server_tokens off verbirgt die Nginx-Version in Antworten, da Versionsinformationen Angreifern helfen, bekannte Schwachstellen gezielt auszunutzen.
Seit Vaultwarden 1.29.0 wird WebSocket-Traffic über denselben Port wie HTTP bedient. Ein separater /notifications/hub-Proxy-Pfad ist nicht nötig. Falls Sie WEBSOCKET_ENABLED in älteren Tutorials sehen, ignorieren Sie es. Diese Variable wurde in 1.29.0 als veraltet markiert und in 1.31.0 entfernt.
Für Details zur Nginx-Konfiguration siehe Nginx als Reverse Proxy konfigurieren und Let's Encrypt SSL/TLS für Nginx einrichten auf Debian 12 und Ubuntu 24.04.
Wie konfiguriere ich SMTP-E-Mail für Vaultwarden?
Vaultwarden benötigt SMTP, um E-Mail-Verifizierungscodes, 2FA-Setup-E-Mails, Organisationseinladungen und Notfallzugriffs-Benachrichtigungen zu versenden. Ohne SMTP funktionieren Funktionen wie einladungsbasierte Registrierung, E-Mail-2FA und Notfallzugriff nicht.
Die wichtigsten Umgebungsvariablen sind SMTP_HOST, SMTP_PORT, SMTP_SECURITY, SMTP_USERNAME, SMTP_PASSWORD und SMTP_FROM. Verwenden Sie SMTP_PORT=587 mit SMTP_SECURITY=starttls für die meisten Anbieter oder SMTP_PORT=465 mit SMTP_SECURITY=force_tls für implizites TLS.
Diese Variablen sind bereits in der .env-Datei oben enthalten. Testen Sie nach dem Start des Containers die E-Mail-Zustellung: Melden Sie sich im Web-Vault unter https://vault.example.com an, erstellen Sie Ihr Konto und aktivieren Sie unter Settings > Security > Two-step Login die E-Mail-basierte 2FA. Wenn Sie den Verifizierungscode erhalten, funktioniert SMTP.
Prüfen Sie die Logs, falls E-Mails fehlschlagen:
docker compose logs | grep -i smtp
Häufige Probleme:
- Authentifizierung fehlgeschlagen: Überprüfen Sie
SMTP_USERNAMEundSMTP_PASSWORD. Sonderzeichen im Passwort erfordern möglicherweise einfache Anführungszeichen in der.env-Datei. - Verbindung auf Port 587 abgelehnt: Einige VPS-Anbieter blockieren ausgehende Ports 25 und 587 standardmäßig. Erkundigen Sie sich bei Ihrem Anbieter oder versuchen Sie Port 465 mit
force_tls. - Zertifikatsfehler: Das TLS-Zertifikat des SMTP-Servers muss gültig sein. Selbstsignierte Zertifikate erfordern
SMTP_ACCEPT_INVALID_CERTS=true(nicht empfohlen für Produktion).
| Variable | Zweck | Beispiel |
|---|---|---|
SMTP_HOST |
Hostname des Mailservers | smtp.example.com |
SMTP_PORT |
Verbindungsport | 587 |
SMTP_SECURITY |
TLS-Methode | starttls oder force_tls |
SMTP_FROM |
Absenderadresse | vault@example.com |
SMTP_USERNAME |
Authentifizierungs-Benutzername | vault@example.com |
SMTP_PASSWORD |
Authentifizierungs-Passwort | (gespeichert in .env, chmod 600) |
SMTP_AUTH_MECHANISM |
Authentifizierungstyp (optional) | Login |
Wie sichere ich das Vaultwarden-Admin-Panel?
Das Admin-Panel unter /admin ermöglicht die Verwaltung von Benutzern, Einsicht in die Konfiguration und Änderung von Einstellungen. Es ist durch das ADMIN_TOKEN geschützt, das Sie zuvor generiert haben. Der Argon2-Hash bedeutet, dass das Roh-Token niemals in Ihrer .env-Datei gespeichert wird. Selbst wenn jemand die Datei liest, erhält er einen Hash, kein Passwort.
Nach der Ersteinrichtung (Kontoerstellung, SMTP-Konfiguration, Deaktivierung der Registrierung) haben Sie zwei Möglichkeiten:
Option 1: Admin-Panel vollständig deaktivieren. Entfernen oder kommentieren Sie ADMIN_TOKEN in .env aus und starten Sie neu:
docker compose down && docker compose up -d
Ohne gesetztes ADMIN_TOKEN gibt der /admin-Endpunkt eine 404 zurück. Das ist die sicherste Option für Einzelbenutzer-Deployments.
Option 2: Zugriff über den Reverse Proxy einschränken. Behalten Sie das Admin-Panel, blockieren Sie aber externen Zugriff:
location /admin {
allow 127.0.0.1;
deny all;
proxy_pass http://127.0.0.1:8080;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
Greifen Sie bei Bedarf über einen SSH-Tunnel auf das Admin-Panel zu:
ssh -L 8888:127.0.0.1:443 user@your-vps
Dann öffnen Sie https://127.0.0.1:8888/admin in Ihrem Browser.
Öffentliche Registrierung deaktivieren
Sobald Ihr Konto existiert, deaktivieren Sie die offene Registrierung. Bearbeiten Sie /opt/vaultwarden/.env:
SIGNUPS_ALLOWED=false
Starten Sie den Container neu:
cd /opt/vaultwarden && docker compose down && docker compose up -d
Neue Benutzer können weiterhin über Organisationseinladungen beitreten, wenn INVITATIONS_ALLOWED=true. So können Sie Teammitglieder hinzufügen, ohne die Registrierung für alle zu öffnen.
Wie richte ich fail2ban für Vaultwarden in Docker ein?
Fail2ban überwacht die Logdatei von Vaultwarden auf fehlgeschlagene Anmeldeversuche und sperrt die betreffenden IPs. Da Vaultwarden in Docker läuft, muss die Sperrregel die iptables-Kette DOCKER-USER verwenden. Standardmäßige INPUT-Kettenregeln haben keinen Einfluss auf Docker-gerouteten Traffic.
Der Vaultwarden-Container schreibt Logs nach /opt/vaultwarden/data/vaultwarden.log (gemappt von /data/vaultwarden.log im Container), weil wir LOG_FILE=/data/vaultwarden.log in der Umgebung gesetzt haben.
Für eine ausführliche fail2ban-Installationsanleitung siehe Fail2Ban auf einem Linux-VPS installieren und konfigurieren.
Login-Filter
Erstellen Sie /etc/fail2ban/filter.d/vaultwarden.local:
[INCLUDES]
before = common.conf
[Definition]
failregex = ^.*?Username or password is incorrect\. Try again\. IP: <ADDR>\. Username:.*$
ignoreregex =
Admin-Panel-Filter
Erstellen Sie /etc/fail2ban/filter.d/vaultwarden-admin.local:
[INCLUDES]
before = common.conf
[Definition]
failregex = ^.*?Invalid admin token\. IP: <ADDR>.*$
ignoreregex =
Jail-Konfiguration
Erstellen Sie /etc/fail2ban/jail.d/vaultwarden.local:
[vaultwarden]
enabled = true
port = http,https
filter = vaultwarden
action = iptables-allports[name=vaultwarden, chain=DOCKER-USER]
logpath = /opt/vaultwarden/data/vaultwarden.log
maxretry = 3
bantime = 14400
findtime = 14400
backend = pyinotify
[vaultwarden-admin]
enabled = true
port = http,https
filter = vaultwarden-admin
action = iptables-allports[name=vaultwarden-admin, chain=DOCKER-USER]
logpath = /opt/vaultwarden/data/vaultwarden.log
maxretry = 3
bantime = 14400
findtime = 14400
backend = pyinotify
| Parameter | Wert | Warum |
|---|---|---|
chain |
DOCKER-USER |
Docker umgeht die INPUT-Kette. Regeln müssen in DOCKER-USER stehen, um Container-Traffic zu betreffen. |
maxretry |
3 |
Drei Fehlversuche lösen eine Sperre aus. Legitime Benutzer scheitern selten mehr als zweimal. |
bantime |
14400 |
Vierstündige Sperre. Lang genug, um Brute-Force abzuschrecken, kurz genug, um einen legitimen Benutzer nicht dauerhaft auszusperren. |
findtime |
14400 |
Zählt Fehlversuche innerhalb eines Vier-Stunden-Fensters. |
backend |
pyinotify |
Dateibasierte Log-Überwachung. Das Standard-Backend systemd kann Docker-Container-Logdateien nicht lesen. |
Starten Sie fail2ban neu und prüfen Sie das Jail:
systemctl restart fail2ban
fail2ban-client status vaultwarden
Status for the jail: vaultwarden
|- Filter
| |- Currently failed: 0
| |- Total failed: 0
| `- File list: /opt/vaultwarden/data/vaultwarden.log
`- Actions
|- Currently banned: 0
|- Total banned: 0
`- Banned IP list:
Testen Sie den Regex gegen das tatsächliche Log-Format:
fail2ban-regex /opt/vaultwarden/data/vaultwarden.log /etc/fail2ban/filter.d/vaultwarden.local
Falls noch keine fehlgeschlagenen Anmeldungen existieren, zeigt die Ausgabe 0 matched. Das ist zu erwarten. Lösen Sie einen falschen Login über den Web-Vault aus und führen Sie den Befehl erneut aus, um zu bestätigen, dass der Regex greift.
Wie verbinde ich Browser-Erweiterungen und Mobile-Apps mit Vaultwarden?
Alle offiziellen Bitwarden-Clients funktionieren mit Vaultwarden. Die einzige Änderung besteht darin, sie auf Ihre Server-URL statt auf bitwarden.com zu verweisen.
Browser-Erweiterung (Chrome, Firefox, Safari):
- Installieren Sie die Bitwarden-Erweiterung aus dem Add-on-Store Ihres Browsers
- Klicken Sie auf dem Anmeldebildschirm auf das Zahnrad-Symbol (oder „Self-hosted" bei neueren Versionen)
- Setzen Sie Server URL auf
https://vault.example.com - Speichern Sie und melden Sie sich mit Ihren Zugangsdaten an
Mobile-App (iOS, Android):
- Installieren Sie die Bitwarden-App aus dem App Store oder Google Play
- Tippen Sie vor der Anmeldung auf das Zahnrad-Symbol auf dem Anmeldebildschirm
- Setzen Sie Server URL auf
https://vault.example.com - Speichern Sie und melden Sie sich an
Desktop-App:
- Klicken Sie vor der Anmeldung auf das Zahnrad-Symbol
- Setzen Sie Server URL auf
https://vault.example.com
CLI:
bw config server https://vault.example.com
bw login
Alle Clients synchronisieren über Ihre Vaultwarden-Instanz. Vault-Daten berühren niemals Bitwardens Server.
Wie richte ich den Notfallzugriff in Vaultwarden ein?
Der Notfallzugriff (Emergency Access) ermöglicht es einem vertrauenswürdigen Kontakt, auf Ihren Vault zuzugreifen oder ihn zu übernehmen, falls Sie nicht mehr erreichbar sind. SMTP muss konfiguriert sein, da Vaultwarden während des Prozesses Benachrichtigungs-E-Mails versendet.
Bestätigen Sie, dass die Funktion in Ihrer .env aktiviert ist:
EMERGENCY_ACCESS_ALLOWED=true
Vertrauenswürdigen Kontakt einrichten:
- Melden Sie sich im Web-Vault unter
https://vault.example.coman - Gehen Sie zu Settings > Emergency Access
- Klicken Sie auf Add emergency contact
- Geben Sie die E-Mail-Adresse der vertrauenswürdigen Person ein (sie muss ein Konto auf Ihrer Vaultwarden-Instanz haben)
- Wählen Sie die Zugriffsebene:
- View: Der Kontakt kann Ihre Vault-Einträge einsehen (nur lesen)
- Takeover: Der Kontakt kann Ihr Master-Passwort zurücksetzen und die volle Kontrolle übernehmen
- Setzen Sie die Wartezeit (1 bis 90 Tage). Das ist die Verzögerung zwischen der Zugriffsanfrage des Kontakts und dem tatsächlichen Zugriff. Sie erhalten eine E-Mail-Benachrichtigung und können die Anfrage in diesem Zeitraum ablehnen.
- Klicken Sie auf Save
Der vertrauenswürdige Kontakt erhält eine Einladungs-E-Mail. Nach der Annahme erscheint er als ausstehender Notfallkontakt. Die Wartezeit funktioniert als Totmannschalter: Wenn Sie innerhalb der konfigurierten Tage nicht reagieren, wird der Zugriff automatisch gewährt.
Für einen persönlichen Vault sind 7 Tage Wartezeit mit View-Zugriff angemessen. Für gemeinsam genutzte Team-Infrastruktur sollten Sie kürzere Wartezeiten in Betracht ziehen.
Wie sichere und stelle ich eine Vaultwarden-Instanz wieder her?
Vaultwarden speichert alles im /data-Verzeichnis: die SQLite-Datenbank (db.sqlite3), Dateianhänge, Icon-Cache und Konfiguration. Ein ordnungsgemäßes Backup erfasst all dies konsistent.
Die SQLite-Datenbank muss mit sqlite3 .backup gesichert werden, nicht durch direktes Kopieren der Datei. Das Kopieren einer aktiven SQLite-Datei kann ein korruptes Backup erzeugen, wenn während des Kopiervorgangs ein Schreibvorgang stattfindet. Der .backup-Befehl erstellt einen konsistenten Snapshot.
| Was sichern | Speicherort | Methode | Häufigkeit |
|---|---|---|---|
| SQLite-Datenbank | /opt/vaultwarden/data/db.sqlite3 |
sqlite3 .backup |
Täglich |
| Anhänge | /opt/vaultwarden/data/attachments/ |
rsync oder cp -a |
Täglich |
| Icon-Cache | /opt/vaultwarden/data/icon_cache/ |
Überspringen (wird automatisch regeneriert) | - |
| Umgebungsdatei | /opt/vaultwarden/.env |
cp |
Bei Änderung |
| Compose-Datei | /opt/vaultwarden/compose.yaml |
cp |
Bei Änderung |
Backup-Skript
Für automatisierte Backups verwendet das Skript age mit einer Empfänger-Schlüsseldatei. Das vermeidet interaktive Passphrase-Abfragen, sodass das Skript aus cron laufen kann.
Generieren Sie ein Schlüsselpaar (einmalig):
apt install age
age-keygen -o /opt/vaultwarden/backup-key.txt
chmod 600 /opt/vaultwarden/backup-key.txt
Der Befehl gibt den öffentlichen Schlüssel auf stdout aus. Speichern Sie ihn in einer Empfängerdatei:
age-keygen -y /opt/vaultwarden/backup-key.txt > /opt/vaultwarden/backup-key.pub
Bewahren Sie eine Kopie von backup-key.txt (dem privaten Schlüssel) außerhalb des Servers auf. Sie brauchen ihn zum Entschlüsseln der Backups. Wenn Sie diesen Schlüssel verlieren, sind Ihre verschlüsselten Backups unwiederbringlich verloren.
Erstellen Sie /opt/vaultwarden/backup.sh:
#!/bin/bash
set -euo pipefail
BACKUP_DIR="/opt/vaultwarden/backups"
DATA_DIR="/opt/vaultwarden/data"
DATE=$(date +%Y-%m-%d_%H%M)
BACKUP_FILE="${BACKUP_DIR}/vaultwarden-${DATE}.tar"
RECIPIENT="/opt/vaultwarden/backup-key.pub"
mkdir -p "${BACKUP_DIR}"
# Back up SQLite database consistently
sqlite3 "${DATA_DIR}/db.sqlite3" ".backup '${BACKUP_DIR}/db-${DATE}.sqlite3'"
# Package database + attachments + config
tar cf "${BACKUP_FILE}" \
-C "${BACKUP_DIR}" "db-${DATE}.sqlite3" \
-C "${DATA_DIR}" attachments/ \
-C /opt/vaultwarden .env compose.yaml 2>/dev/null || true
# Encrypt with age recipient key (non-interactive)
age -R "${RECIPIENT}" -o "${BACKUP_FILE}.age" "${BACKUP_FILE}"
# Clean up unencrypted files
rm -f "${BACKUP_FILE}" "${BACKUP_DIR}/db-${DATE}.sqlite3"
# Remove backups older than 30 days
find "${BACKUP_DIR}" -name "*.age" -mtime +30 -delete
echo "Backup complete: ${BACKUP_FILE}.age"
chmod 700 /opt/vaultwarden/backup.sh
Für automatisierte tägliche Backups fügen Sie einen Cronjob hinzu:
echo "0 3 * * * root /opt/vaultwarden/backup.sh >> /var/log/vaultwarden-backup.log 2>&1" > /etc/cron.d/vaultwarden-backup
chmod 644 /etc/cron.d/vaultwarden-backup
Für Offsite-Kopien schieben Sie das verschlüsselte Backup auf einen entfernten Server oder Objektspeicher:
rsync -az /opt/vaultwarden/backups/*.age backup-user@remote-server:/backups/vaultwarden/
Wiederherstellungsprozedur
Ein Backup, das Sie nie wiederhergestellt haben, ist ein Backup, dem Sie nicht vertrauen können. Die vollständige Prozedur:
# Stop the container
cd /opt/vaultwarden && docker compose down
# Decrypt the backup
age -d -i /opt/vaultwarden/backup-key.txt -o /tmp/vaultwarden-restore.tar /opt/vaultwarden/backups/vaultwarden-2026-03-20_0300.tar.age
# Extract
mkdir -p /tmp/vaultwarden-restore
tar xf /tmp/vaultwarden-restore.tar -C /tmp/vaultwarden-restore
# Replace the database (delete WAL files first)
rm -f /opt/vaultwarden/data/db.sqlite3-wal /opt/vaultwarden/data/db.sqlite3-shm
cp /tmp/vaultwarden-restore/db-2026-03-20_0300.sqlite3 /opt/vaultwarden/data/db.sqlite3
chown 1000:1000 /opt/vaultwarden/data/db.sqlite3
# Restore attachments
rsync -a /tmp/vaultwarden-restore/attachments/ /opt/vaultwarden/data/attachments/
chown -R 1000:1000 /opt/vaultwarden/data/attachments/
# Start the container
docker compose up -d
# Clean up
rm -rf /tmp/vaultwarden-restore /tmp/vaultwarden-restore.tar
Sie müssen die WAL- (Write-Ahead Log) und SHM-Dateien vor der Wiederherstellung löschen. Diese Dateien gehören zum alten Datenbankzustand. Vaultwarden mit einer wiederhergestellten Datenbank, aber veralteten WAL-Dateien zu starten, führt zu Datenkorruption.
Melden Sie sich nach der Wiederherstellung im Web-Vault an und prüfen Sie, ob Ihre Einträge vorhanden sind.
Wie aktualisiere ich Vaultwarden sicher?
Pinnen Sie Ihr Image auf einen spezifischen Versions-Tag (wir haben 1.35.4 verwendet). Verwenden Sie in Produktion niemals :latest, da Sie weder nachvollziehen können, was sich geändert hat, noch zuverlässig zurückrollen können.
Zum Aktualisieren:
cd /opt/vaultwarden
# Back up first
./backup.sh
# Pull the new version
docker compose pull
# Recreate the container
docker compose up -d
Bearbeiten Sie vor dem Pull compose.yaml, um den Image-Tag auf die neue Version zu ändern. Prüfen Sie die Release Notes auf Breaking Changes.
docker compose logs --tail 30
Falls das Update Probleme verursacht, stellen Sie aus Ihrem Backup wieder her:
# Revert compose.yaml to the old version tag
docker compose down
# Follow the restore procedure above
docker compose up -d
Etwas funktioniert nicht?
Container beendet sich sofort:
docker compose logs
Suchen Sie nach Berechtigungsfehlern. Die Direktive user: 1000:1000 erfordert passende Eigentümerschaft auf /opt/vaultwarden/data. Führen Sie chown -R 1000:1000 /opt/vaultwarden/data aus und versuchen Sie es erneut.
Kein Zugriff auf den Web-Vault:
Prüfen Sie, ob der Reverse Proxy an 127.0.0.1:8080 weiterleitet:
curl -s -o /dev/null -w "%{http_code}" http://127.0.0.1:8080/alive
Eine 200-Antwort bedeutet, Vaultwarden läuft. Das Problem liegt in Ihrer Reverse-Proxy-Konfiguration.
Fail2ban sperrt nicht:
fail2ban-regex /opt/vaultwarden/data/vaultwarden.log /etc/fail2ban/filter.d/vaultwarden.local
Wenn der Regex keine Zeilen trifft, prüfen Sie, ob LOG_FILE=/data/vaultwarden.log in .env gesetzt ist und ob die Logdatei unter /opt/vaultwarden/data/vaultwarden.log existiert.
E-Mails werden nicht versendet:
docker compose logs | grep -i "smtp\|mail\|email"
Prüfen Sie, ob Ihr VPS ausgehende Verbindungen auf dem SMTP-Port erlaubt:
nc -zv smtp.example.com 587
Database-Locked-Fehler:
Dies kann passieren, wenn Sie die Datenbankdatei kopieren, während Vaultwarden läuft. Verwenden Sie immer sqlite3 .backup für Backups und stoppen Sie immer den Container vor der Wiederherstellung.
Log-Speicherorte:
# Application logs
docker compose logs -f
# Log file (if LOG_FILE is set)
tail -f /opt/vaultwarden/data/vaultwarden.log
# Fail2ban logs
journalctl -u fail2ban -f
Für Docker-Container-Sicherheit über diese Anleitung hinaus siehe Docker-Sicherheit härten: Rootless-Modus, Seccomp, AppArmor auf einem VPS. Für Backup-Strategien für alle Ihre Docker-Dienste siehe Docker-Volumes auf einem VPS sichern und wiederherstellen.
Copyright 2026 Virtua.Cloud. Alle Rechte vorbehalten. Dieser Inhalt ist ein Originalwerk des Virtua.Cloud-Teams. Vervielfältigung, Wiederveröffentlichung oder Weiterverbreitung ohne schriftliche Genehmigung ist untersagt.
Bereit, es selbst auszuprobieren?
Stellen Sie Ihren eigenen Server in Sekunden bereit. Linux, Windows oder FreeBSD. →