Vaultwarden auf einem VPS mit Docker Compose selbst hosten

11 Min. Lesezeit·Matthieu·self-hostingfail2bansecuritypassword-managerdocker-composedockervaultwarden|

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: ALL entfernt 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: true verhindert, 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: 512M verhindert, 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/1Container 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_USERNAME und SMTP_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):

  1. Installieren Sie die Bitwarden-Erweiterung aus dem Add-on-Store Ihres Browsers
  2. Klicken Sie auf dem Anmeldebildschirm auf das Zahnrad-Symbol (oder „Self-hosted" bei neueren Versionen)
  3. Setzen Sie Server URL auf https://vault.example.com
  4. Speichern Sie und melden Sie sich mit Ihren Zugangsdaten an

Mobile-App (iOS, Android):

  1. Installieren Sie die Bitwarden-App aus dem App Store oder Google Play
  2. Tippen Sie vor der Anmeldung auf das Zahnrad-Symbol auf dem Anmeldebildschirm
  3. Setzen Sie Server URL auf https://vault.example.com
  4. Speichern Sie und melden Sie sich an

Desktop-App:

  1. Klicken Sie vor der Anmeldung auf das Zahnrad-Symbol
  2. 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:

  1. Melden Sie sich im Web-Vault unter https://vault.example.com an
  2. Gehen Sie zu Settings > Emergency Access
  3. Klicken Sie auf Add emergency contact
  4. Geben Sie die E-Mail-Adresse der vertrauenswürdigen Person ein (sie muss ein Konto auf Ihrer Vaultwarden-Instanz haben)
  5. 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
  6. 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.
  7. 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.