SSD Nodes Learn Hosting plans →
Anleitungen Matt ConnorVon Matt Connor

Vaultwarden auf VPS selbst hosten mit Docker

Betreiben Sie Vaultwarden auf einer VPS mit Docker und offiziellen Bitwarden-Apps. Der Leitfaden zeigt HTTPS, Admin-Token, Fail2ban sowie getestete Backups.

Was Sie erstellen

Ein Passwortmanager, den Sie vollständig selbst betreiben: Vaultwarden läuft in einem kleinen Container hinter einem Reverse Proxy, der HTTPS terminiert. Die offiziellen Bitwarden-Apps auf Ihrem Telefon, Laptop und in Ihrem Browser greifen darauf zu. Vaultwarden implementiert die Bitwarden-Server-API in Rust neu und verwendet dasselbe Protokoll wie bitwarden.com. Daher funktionieren die offiziellen Clients unverändert damit, solange Sie den Server aktuell halten. Neue Client-Releases benötigen manchmal ein passendes Vaultwarden-Release: Für Clients ab 2026.8.0 ist 1.37.2 erforderlich. Vaultwarden benötigt jedoch etwa 100 MB RAM statt des offiziellen Stacks mit mehreren Containern.

Die Installation umfasst ein Dutzend Compose-Zeilen. Entscheidend sind diese drei Punkte, an denen die Einrichtung typischerweise scheitert: TLS muss eingerichtet sein, bevor Sie den Web Vault zum ersten Mal laden. Öffentliche Registrierungen müssen geschlossen werden, sobald Ihr eigenes Konto existiert. Das Daten-Volume muss gesichert und testweise wiederhergestellt werden, weil dieses eine Verzeichnis jedes von Ihnen gespeicherte Passwort enthält.

Voraussetzungen und wichtige Einschränkungen

  • Eine VPS mit Docker Engine und dem Compose-Plugin auf einer frisch installierten Ubuntu-24.04-KVM-Instanz mit root oder sudo. 512 MB RAM sind tatsächlich ausreichend; 1 GB bietet komfortable Reserven. Dies gehört zu den ressourcenschonendsten Diensten, die Sie betreiben können, und steht weit oben auf der Auswahlliste sinnvoller Dienste für Self-Hosting. Dimensionieren Sie die Instanz trotzdem für alle weiteren Dienste, die darauf laufen: Wenn Sie eine selbst gehostete Fotobibliothek wie PhotoPrism oder Immich auf derselben VPS betreiben, steigt der erforderliche Arbeitsspeicher auf mehrere Gigabyte, während Vaultwarden den Bedarf kaum erhöht. Dasselbe gilt für Medien-Frontends, die Sie später ergänzen, denn eine Jellyfin-Bibliothek wie eine begehbare Videothek aus den 90er-Jahren zu gestalten bedeutet einen weiteren dauerhaft laufenden Container sowie Reserven für Transcoding aus demselben Budget.
  • Eine Domain mit einem A-Record (und einem AAAA-Record, falls Sie IPv6 verwenden), der vault.example.com auf die VPS verweist. Das TLS-Zertifikat wird für genau diesen Namen ausgestellt. Daher muss DNS vor dem Start korrekt aufgelöst werden.
  • Die Ports 80 und 443 müssen aus dem Internet erreichbar sein und von Ihrem Reverse Proxy terminiert werden, niemals direkt von Vaultwarden. Port 80 wird ausschließlich für die ACME-Zertifikatsprüfung und die Weiterleitung von HTTP auf HTTPS verwendet.
  • Der wichtigste Punkt vorab: Die Bitwarden-Clients verweigern die Verbindung zu einem Server ohne HTTPS. Es gibt keinen funktionierenden Weg, den Dienst zunächst über http zu testen. Der konkrete Grund wird im nächsten Abschnitt erklärt.

Warum Vaultwarden statt des offiziellen Bitwarden-Stacks

Gleiche Clients, ein Bruchteil des Ressourcenbedarfs. Die offizielle Self-Hosting-Bereitstellung von Bitwarden besteht standardmäßig aus einem Verbund von Containern (MSSQL Express, Identity, Api, Admin und weitere) und benötigt mindestens 2 GB RAM. Bitwarden bietet außerdem Bitwarden lite an, ein einzelnes Docker-Image mit einem Mindestbedarf von 200 MB RAM. Es ist jedoch für den persönlichen Einsatz und Homelabs vorgesehen, nicht für Unternehmen, und die Verantwortung für die Datenbank und deren Backups liegt vollständig bei Ihnen. Vaultwarden ist eine einzelne Binärdatei. Standardmäßig speichert sie alle Daten in einer SQLite-Datenbank und benötigt im Leerlauf nur einige Dutzend Megabyte. Für eine Person, eine Familie oder ein kleines Team ist das die naheliegende Wahl. Da Vaultwarden die Bitwarden-API vollständig implementiert, bleiben Ihre Daten zwischen Vaultwarden und bitwarden.com portabel.

Sie verzichten damit auf den Großteil der Enterprise-Funktionen: Es gibt kein SCIM-Provisioning, auch wenn die Unterstützung für OpenID Connect SSO in 1.35.0 hinzugekommen ist. Außerdem sind Sie selbst der Betreiber. Patching, HTTPS und Backups fallen in Ihre Verantwortung. Diese Anleitung behandelt genau diese drei Aufgaben.

Warum HTTPS nicht optional ist

Der Bitwarden-Web-Tresor und die Browser-Erweiterungen leiten ihre Verschlüsselungsschlüssel mithilfe der Web Crypto API (window.crypto.subtle) im Browser ab. Browser stellen crypto.subtle nur in einem sicheren Kontext, über HTTPS oder im Sonderfall von Loopback-Adressen wie http://localhost und http://127.0.0.1 bereit. Über reines http://vault.example.com ist dies undefined. Sobald die Anwendung einen Schlüssel ableiten soll, tritt daher ein Fehler auf. Die Konsole zeigt:

Uncaught (in promise) TypeError: Cannot read properties of undefined (reading 'importKey')

Die Seite reagiert nicht mehr oder zeigt einen allgemeinen Kryptografiefehler. Eine Anmeldung ist nicht möglich. Die Desktop-, Mobil- und Browser-Clients prüfen eine selbst gehostete URL ebenfalls selbstständig. Bei einem http-Endpunkt oder einem nicht erreichbaren Endpunkt lehnen sie die Verbindung mit folgender Meldung ab:

This is not a recognized Bitwarden server. You may need to check with your provider or update your server.

Beide Fehler haben dieselbe Ursache: Es ist kein gültiges HTTPS verfügbar. Richten Sie TLS daher zuerst ein. Öffnen Sie den Tresor niemals über http, auch nicht einmalig zur Kontrolle.

Schritt 1, DNS und der Reverse Proxy (zuerst TLS)

Verweisen Sie den Record auf Ihre VPS-Adresse und prüfen Sie, ob er zur richtigen Adresse aufgelöst wird:

dig +short vault.example.com

Die ausgegebene Zeile muss die IP-Adresse Ihrer VPS enthalten. Wenn sie leer oder falsch ist, korrigieren Sie DNS und warten Sie das TTL-Intervall ab. Die Zertifikatsausstellung schlägt fehl, wenn der Name nicht aufgelöst werden kann.

Für das HTTPS-Frontend verwendet diese Anleitung Traefik. Traefik stellt Let's Encrypt-Zertifikate automatisch aus und erneuert sie. Außerdem lässt es sich direkt in Compose integrieren. Wenn Traefik noch nicht läuft, befolgen Sie zuerst die Anleitung zum Traefik-Reverse-Proxy und zur automatischen TLS-Konfiguration. Dabei werden ein externes Docker-Netzwerk (proxy weiter unten) und ein ACME-Resolver (letsencrypt) erstellt, an den der Vaultwarden-Dienst angebunden wird. Reines nginx mit einem manuell ausgestellten Zertifikat funktioniert aus Sicht von Vaultwarden identisch.

Bevorzugen Sie nginx und Certbot statt Traefik? Binden Sie Vaultwarden an 127.0.0.1:8080 an (fügen Sie ports: ["127.0.0.1:8080:80"] zum Dienst hinzu und entfernen Sie die Traefik-Labels). Stellen Sie anschließend ein Zertifikat aus und richten Sie den Proxy auf Vaultwarden. Der Zertifikatsteil wird in Let's Encrypt-Zertifikate mit Certbot und nginx ausstellen beschrieben. Wichtig ist zusätzlich das WebSocket-Upgrade für den Benachrichtigungspfad:

server {
    listen 443 ssl;
    server_name vault.example.com;

    client_max_body_size 525M;

    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;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
    }
}

Beachten Sie die Zeile X-Real-IP. Sie sorgt dafür, dass Fail2ban später die echte Angreiferadresse statt 127.0.0.1 erkennt. Alles andere in dieser Anleitung ist identisch, unabhängig davon, ob Traefik oder nginx vorgeschaltet ist.

Schritt 2: Die Compose-Datei

Erstellen Sie zuerst das Projektverzeichnis. Diese Anleitung verwendet /opt/vaultwarden. Dadurch bleiben der Compose-Projektname und damit das Daten-Volume vaultwarden_vw-data vorhersehbar. Die folgenden Schritte für Fail2ban und Backups hängen von diesem exakten Namen ab.

sudo mkdir -p /opt/vaultwarden
cd /opt/vaultwarden

Erstellen Sie in diesem Verzeichnis eine .env für das Administrationsgeheimnis und die Compose-Datei.

# .env
ADMIN_TOKEN=paste-a-strong-token-here

Generieren Sie dieses Token mit openssl rand -base64 48 und fügen Sie es ein. Eine stärker gehashte Form wird im nächsten Abschnitt behandelt. Für den Anfang genügt eine lange zufällige Zeichenfolge.

# docker-compose.yml
services:
  vaultwarden:
    image: vaultwarden/server:latest
    container_name: vaultwarden
    restart: unless-stopped
    environment:
      DOMAIN: "https://vault.example.com"
      SIGNUPS_ALLOWED: "true"          # closed in Step 4, keep true just to register
      ADMIN_TOKEN: "${ADMIN_TOKEN}"
      IP_HEADER: "X-Forwarded-For"     # X-Real-IP if your proxy sends that instead
      LOG_FILE: "/data/vaultwarden.log"
      LOG_LEVEL: "warn"
    volumes:
      - vw-data:/data
    networks:
      - proxy
    labels:
      - "traefik.enable=true"
      - "traefik.http.routers.vw.rule=Host(`vault.example.com`)"
      - "traefik.http.routers.vw.entrypoints=websecure"
      - "traefik.http.routers.vw.tls.certresolver=letsencrypt"
      - "traefik.http.services.vw.loadbalancer.server.port=80"

volumes:
  vw-data:

networks:
  proxy:
    external: true

Zwei Aspekte dieser Datei tragen das gesamte Konzept. Es gibt kein ports:-Mapping. Vaultwarden ist daher nur über Traefik und dessen TLS erreichbar. Wenn Sie den Port auf dem Host veröffentlichen, kann der Tresor versehentlich über HTTP bereitgestellt werden. Außerdem muss DOMAIN die vollständige öffentliche HTTPS-URL sein. Dieser Wert wird in Anhang-Links, WebAuthn-2FA und den Benachrichtigungsendpunkt übernommen. Ein falscher Wert oder eine HTTP-URL führt daher dazu, dass diese Funktionen nicht funktionieren, obwohl die Website geladen wird. Das Tag latest ist eine bewusste Ausnahme von der üblichen Regel, niemals latest zu verwenden. Vaultwarden veröffentlicht seine stabilen Versionen als ein fortlaufend aktualisiertes Image. :testing ist der separate Kanal für Vorabversionen. Aktualisieren Sie daher bewusst und überfliegen Sie die Release-Hinweise, bevor Sie das Image abrufen. Diese Ausnahme ist jedoch begrenzt: Die meisten langlebigen Container sollten besser auf ein exaktes Tag festgelegt werden. Dadurch bleibt ein dauerhaft aktiver, selbst gehosteter Agent auf demselben VPS auch bei Reboots und dem Abrufen von Images vorhersehbar.

Starten Sie den Stack und überwachen Sie das Log:

docker compose up -d
docker compose logs -f vaultwarden

Ein korrekter Start endet mit einer Zeile wie Rocket has launched from http://0.0.0.0:80. Warten Sie einige Sekunden, damit Traefik das Zertifikat abrufen kann. Laden Sie anschließend https://vault.example.com. Sie sollten den Bitwarden-Webtresor mit einem gültigen Schlosssymbol und ohne Zertifikatswarnung sehen.

Schritt 3: ein starkes ADMIN_TOKEN und die $$-Falle

ADMIN_TOKEN schützt /admin, das Panel, das jeden Benutzer und jede Einstellung Ihrer Instanz lesen kann. Behandeln Sie es daher wie ein root-Passwort. Zwei Formen funktionieren.

Die einfache Form ist die zufällige Zeichenfolge, die Sie bereits mit openssl rand -base64 48 erzeugt haben. Da Base64 niemals ein $ enthält, kann die Zeichenfolge ohne Escaping direkt in .env eingefügt werden.

Die gehärtete Form ist ein Argon2-PHC-Hash. Dadurch wird das Token im Klartext nie auf der Festplatte gespeichert. Erzeugen Sie den Hash mit demselben Image:

docker run --rm -it vaultwarden/server /vaultwarden hash --preset owasp

Der Befehl fordert Sie zweimal zur Eingabe auf und gibt eine Zeichenfolge aus, die mit $argon2id$v=19$... beginnt. Hier liegt die Falle, die viele eine Stunde kostet: Docker Compose behandelt $ als Variableninterpolation. Wenn Sie den Hash in der Compose-Datei direkt unter environment: einfügen, müssen Sie daher jedes $ durch $$ ersetzen. Sie können den Wert dort in Anführungszeichen setzen. Entscheidend ist das Escaping:

    environment:
      ADMIN_TOKEN: $$argon2id$$v=19$$m=19456,t=2,p=1$$c29tZXNhbHQ$$RdescudvJCsgt3ub+b+dWRWJTmaaJObG

Wenn Sie den Hash lieber in .env speichern möchten, gilt die umgekehrte Regel: Lassen Sie die einzelnen $-Zeichen stehen, setzen Sie den gesamten Wert in einfache Anführungszeichen (ADMIN_TOKEN='$argon2id$v=19$...'), und die vorhandene ${ADMIN_TOKEN}-Zeile in der Compose-Datei übernimmt den Wert. Verdoppeln Sie $ niemals in .env. Wenn Sie einzelne $-Zeichen direkt in der Compose-Datei verwenden, gibt Compose eine Warnung zu The "argon2id" variable is not set aus und leert das Token. /admin weist Ihr korrektes Passwort dann zurück. Führen Sie docker compose up -d aus, und speichern Sie den am Prompt eingegebenen Klartext in Ihrem eigenen Passwortmanager.

Schritt 4: Registrieren Sie Ihr Konto und schließen Sie anschließend die Tür

Öffnen Sie mit SIGNUPS_ALLOWED: "true" die Seite https://vault.example.com, klicken Sie auf Create account und registrieren Sie sich mit Ihrer E-Mail-Adresse und einem starken Master-Passwort. Dieses Master-Passwort kann nicht wiederhergestellt werden. Es gibt keine Möglichkeit zum Zurücksetzen. Speichern Sie es daher vorher an einem dauerhaften Ort.

Schließen Sie jetzt die Tür. Bearbeiten Sie die Compose-Datei, um Registrierungen zu deaktivieren:

      SIGNUPS_ALLOWED: "false"

Wenden Sie die Änderung mit docker compose up -d erneut an. Diese Absicherung sollten Sie nicht aufschieben. Wenn die Registrierung offen bleibt, kann jeder, der die URL findet, ein Konto auf Ihrem Server erstellen. Das gilt auch für Crawler. Sie können Ihren Tresor nicht lesen, verbrauchen aber Ressourcen und machen Ihre private Instanz zu einem offenen Dienst. Daran erkennen Sie, dass die Einstellung noch aktiv ist: /admin listet Konten auf, die Sie nicht erstellt haben.

Um später Familienmitglieder oder Teammitglieder hinzuzufügen, ohne öffentliche Registrierungen wieder zu aktivieren, verwenden Sie die Schaltfläche Invite User in /admin. Dafür muss SMTP konfiguriert sein, damit die eingeladene Person ihren Link erhält.

Schritt 5: /admin aufrufen

Rufen Sie https://vault.example.com/admin auf und geben Sie das Admin-Token im Klartext ein (die zufällige Zeichenfolge oder das Passwort, dessen Hash Sie erstellt haben, nicht den Hash selbst). Im Panel können Sie Benutzer auflisten, Einstellungen anpassen, eine Test-E-Mail senden und einen Datenbank-Snapshot erstellen.

Wenn die Seite stattdessen The admin panel is disabled, please configure the 'ADMIN_TOKEN' variable to enable it anzeigt, ist ADMIN_TOKEN leer oder nicht gesetzt. Dadurch wird das Panel vollständig deaktiviert. Das ist eine gültige Option, wenn Sie es nie benötigen. Wenn das Panel geladen wird, Ihr Token aber ablehnt, beachten Sie den $$-Escaping-Fehler in der folgenden Fehlerliste. Haben Sie das Token vergessen? Es gibt keine Wiederherstellungsabfrage. Bearbeiten Sie .env oder die Compose-Datei, setzen Sie ein neues Token und docker compose up -d.

Schritt 6: Bitwarden-Clients verbinden

Jeder offizielle Client kann eine Verbindung zu einem selbst gehosteten Server herstellen. Installieren Sie den Bitwarden-Desktop-, Mobil- oder Browser-Client aus den regulären Stores. Sie benötigen keinen speziellen Vaultwarden-Build.

Öffnen Sie vor der Anmeldung das Einstellungszahnrad auf dem Anmeldebildschirm (mit Self-hosted oder Region → Self-hosted beschriftet), setzen Sie Server URL auf https://vault.example.com und speichern Sie die Einstellung. Melden Sie sich anschließend mit der registrierten E-Mail-Adresse und dem Master-Passwort an. Der Client sollte sofort eine Verbindung herstellen und anbieten, Zugangsdaten auszufüllen und zu speichern.

Wenn ein Client This is not a recognized Bitwarden server. You may need to check with your provider or update your server. anzeigt, ist die URL falsch, verwendet http oder das Zertifikat wird nicht als vertrauenswürdig eingestuft. Prüfen Sie erneut, ob https://vault.example.com zuerst in einem Browser problemlos geladen wird. Verzögerte Aktualisierungen auf anderen Geräten werden durch WebSocket-Push verursacht und weiter unten behandelt.

Schritt 7, ein Fail2ban-Jail für den Login-Endpunkt

Vaultwarden protokolliert jeden fehlgeschlagenen Login in der durch LOG_FILE festgelegten Datei. Damit sind genau die Informationen verfügbar, die ein Schutz gegen Brute-Force-Angriffe benötigt. Wenn Fail2ban noch nicht läuft, finden Sie die Installation und die Grundlagen im Leitfaden zur Härtung von SSH mit Fail2ban. Hier fügen wir ein Jail für den Tresor hinzu.

Ermitteln Sie zunächst, wo das benannte Volume auf dem Host liegt, damit Fail2ban das Log lesen kann:

docker volume inspect vaultwarden_vw-data --format '{{ .Mountpoint }}'

Das gibt etwa /var/lib/docker/volumes/vaultwarden_vw-data/_data aus. Das Log liegt darin unter vaultwarden.log. Erstellen Sie den Filter:

# /etc/fail2ban/filter.d/vaultwarden.conf
[Definition]
failregex = ^.*Username or password is incorrect\. Try again\. IP: <ADDR>\. Username:.*$
ignoreregex =

Und anschließend das Jail:

# /etc/fail2ban/jail.d/vaultwarden.local
[vaultwarden]
enabled   = true
filter    = vaultwarden
logpath   = /var/lib/docker/volumes/vaultwarden_vw-data/_data/vaultwarden.log
banaction = iptables-allports
chain     = DOCKER-USER
maxretry  = 5
findtime  = 600
bantime   = 3600

Laden Sie die Konfiguration mit sudo systemctl restart fail2ban neu und prüfen Sie sie mit sudo fail2ban-client status vaultwarden.

Drei Docker-Details entscheiden darüber, ob dieser Schutz tatsächlich funktioniert. Wenn das Log bei jedem fehlgeschlagenen Versuch IP: 127.0.0.1 oder die Adresse Ihres Proxys enthält, sperrt Vaultwarden den Proxy. Setzen Sie IP_HEADER dann auf den Header, den Ihr Proxy tatsächlich sendet: X-Forwarded-For bei Traefik, X-Real-IP für den obigen nginx-Block und CF-Connecting-IP hinter Cloudflare. Seit 1.37.4 verwendet Vaultwarden mit X-Forwarded-For die äußerste rechte Adresse, die nicht in IP_HEADER_TRUSTED_PROXIES enthalten ist. Der Standardwert local deckt einen Proxy auf demselben Host oder im selben Docker-Netzwerk ab. Wenn ein CDN vor Ihrem Proxy sitzt, tragen Sie auch dessen Adressen dort ein.

Zweitens hängt die richtige iptables-Kette von Ihrem Proxy ab. Wenn Traefik als Container mit veröffentlichten Ports läuft, durchläuft der Datenverkehr Dockers FORWARD-Pfad. Die Sperre muss daher wie oben in DOCKER-USER erfolgen. Wenn Sie dagegen die Host-nginx-Option aus Schritt 1 gewählt haben, werden die Verbindungen in nginx auf dem Host in der Kette INPUT beendet. Eine Sperre in DOCKER-USER sieht diese Verbindungen nicht. Löschen Sie in diesem Fall die Zeile chain = DOCKER-USER, damit Fail2ban die Standardkette INPUT verwendet.

Drittens sollten Sie banaction = iptables-allports statt des portbasierten Standards verwenden. Dieses Jail definiert keinen Port. Eine Sperre für alle Ports in DOCKER-USER blockiert den Angreifer zuverlässig für jeden veröffentlichten Dienst auf dem Host.

Schritt 8: Sichern Sie den Tresor und stellen Sie ihn anschließend tatsächlich wieder her

Das Volume vw-data ist Ihr Passwortmanager. Es enthält db.sqlite3 (jeden Eintrag), die Verzeichnisse attachments/ und sends/, die rsa_key.*-Dateien zum Signieren von Anmeldesitzungen sowie config.json aus dem Administrationsbereich. Eine Sicherung, die einen dieser Bestandteile auslässt, schlägt fehl, wenn Sie sie benötigen.

Wenn Sie db.sqlite3 kopieren, während Vaultwarden Schreibvorgänge ausführt, kann die Datei unvollständig und beschädigt sein. Erstellen Sie daher einen Snapshot bei angehaltenem Dienst. Die Ausfallzeit beträgt nur wenige Sekunden:

#!/usr/bin/env bash
set -euo pipefail
STAMP=$(date +%F)
DEST=/root/vw-backups
VOL=$(docker volume inspect vaultwarden_vw-data --format '{{ .Mountpoint }}')
mkdir -p "$DEST"
docker compose -f /opt/vaultwarden/docker-compose.yml stop vaultwarden
tar czf "$DEST/vw-$STAMP.tgz" -C "$VOL" .
docker compose -f /opt/vaultwarden/docker-compose.yml start vaultwarden

Führen Sie dies jede Nacht über cron aus und kopieren Sie .tgz vom Server herunter. Eine Sicherung, die nur auf dem Server liegt, den Sie schützen, ist keine Sicherung. Der saubere Weg besteht darin, jede Nacht eine restic-Sicherung auf einen anderen Server oder in einen Objektspeicher zu übertragen. Dabei verschlüsselt restic das Archiv und dedupliziert wiederholte Snapshots automatisch. Die Schaltfläche Backup Database im Administrationsbereich erstellt bequem einen aktuellen Snapshot ausschließlich der SQLite-Datei. Anhänge und Schlüssel sind darin jedoch nicht enthalten.

Führen Sie nun den entscheidenden Test durch, der eine echte Sicherung von einer bloßen Hoffnung unterscheidet: Stellen Sie sie einmal wieder her und prüfen Sie, ob sie funktioniert:

mkdir -p /tmp/vw-restore
tar xzf /root/vw-backups/vw-2026-07-15.tgz -C /tmp/vw-restore
docker run --rm -p 127.0.0.1:8888:80 -v /tmp/vw-restore:/data vaultwarden/server

Bauen Sie von Ihrem Laptop aus mit ssh -L 8888:127.0.0.1:8888 you@your-vps einen Tunnel dorthin auf und öffnen Sie http://localhost:8888 (oder http://127.0.0.1:8888). Da Loopback-Adressen als sicherer Kontext gelten, ist crypto.subtle verfügbar. Der Tresor wird hier über einfaches http entschlüsselt. Dies ist die einzige Art von Adresse, unter der das zulässig ist. Melden Sie sich mit Ihrem Master-Passwort an und prüfen Sie, ob Ihre Einträge vorhanden sind. Wenn dies der Fall ist, funktionieren Ihre Datenbank, die RSA-Schlüssel und Ihr Master-Passwort über den gesamten Sicherungs- und Wiederherstellungsvorgang hinweg. Sie können den Tresor auf einer neuen VPS innerhalb weniger Minuten wieder aufbauen. Beenden Sie den Container mit Ctrl-C und löschen Sie /tmp/vw-restore. Verwenden Sie diese Tunnel-Methode auch für andere Administrationsoberflächen auf dem Server, die niemals aus dem Internet erreichbar sein sollten. So würden Sie beispielsweise auch einen selbst gehosteten Open-Source-Sicherheitsscanner auf Port 5173 erreichen.

Fehlerbilder und die dabei angezeigten Zeichenfolgen

Cannot read properties of undefined (reading 'importKey') in der Browserkonsole. Der Tresor wurde über http geladen, daher ist crypto.subtle nicht definiert. Rufen Sie ihn nur über https:// auf und richten Sie am Proxy eine Weiterleitung von HTTP auf HTTPS ein.

This is not a recognized Bitwarden server... in einem Client. Die Server-URL verwendet http, enthält einen Tippfehler oder das Zertifikat wird nicht als vertrauenswürdig eingestuft. Prüfen Sie, ob https://vault.example.com ein gültiges Vorhängeschloss anzeigt, und geben Sie die URL anschließend in den Self-Hosted-Einstellungen des Clients erneut ein.

/admin weist das korrekte Passwort zurück. Der Argon2-Hash hat seine Maskierung verloren. In der Compose-Datei muss jedes $ als $$ geschrieben werden. Innerhalb von einfachen Anführungszeichen in .env muss dagegen ein einzelnes $ verwendet werden. Alternativ haben Sie möglicherweise den Hash statt des von ihm repräsentierten Klartextpassworts eingegeben.

Langsame Synchronisierung zwischen Geräten; die Konsole zeigt WebSocket connection to 'wss://vault.example.com/notifications/hub' failed. Der Proxy leitet die Upgrade/Connection-Header nicht weiter. Traefik erledigt dies automatisch. Bei nginx müssen Sie die beiden Upgrade-Zeilen aus Schritt 1 ergänzen. Der Tresor funktioniert weiterhin, synchronisiert sich jedoch erst beim Öffnen. Der frühere dedizierte Port 3012 ist seit v1.31.0 entfallen. Daher ist keine separate WebSocket-Route erforderlich.

Fail2ban meldet eine Sperre, aber der Angreifer stellt weiterhin Verbindungen her. Fail2ban sperrt 127.0.0.1, weil IP_HEADER falsch ist, oder die Sperre befindet sich in der falschen iptables-Kette. Setzen Sie chain = DOCKER-USER und banaction = iptables-allports.

Upgrades

Laden Sie das neue Image herunter und erstellen Sie den Container neu. Das benannte Volume und alle Ihre Daten bleiben erhalten:

docker compose pull
docker compose up -d

Vaultwarden veröffentlicht häufig neue Versionen. Beobachten Sie die Release Notes des Projekts, statt eine Patch-Version festzulegen, da einige Releases Hinweise zu Migrationen enthalten. Erstellen Sie vor jedem größeren Versionssprung ein aktuelles Backup. Sie können ein Rollback durchführen, indem Sie das Tarball in ein neues Volume zurückspielen.

FAQ

Ist Vaultwarden dasselbe wie Bitwarden?

Es handelt sich um einen kompatiblen, unabhängigen Server, nicht um den offiziellen Server. Vaultwarden implementiert die Bitwarden-Server-API in Rust neu. Daher funktionieren die offiziellen Desktop-, Mobil-, Browser- und CLI-Clients damit, während der Ressourcenverbrauch deutlich geringer ist als beim offiziellen Stack. Das Tresorformat ist identisch. Sie können daher in beide Richtungen migrieren, indem Sie exportieren und importieren.

Brauche ich wirklich HTTPS, oder kann ich es über http in meinem LAN betreiben?

Außer für einen Loopback-Test benötigen Sie HTTPS. Der Bitwarden-Webtresor und die Erweiterungen verwenden die Web Crypto API des Browsers. Diese ist nur in einem sicheren Kontext verfügbar. Über einfaches http gibt der Client daher Cannot read properties of undefined aus und meldet sich nicht an. Die einzigen funktionierenden http-Adressen sind Loopback-Adressen wie http://localhost oder http://127.0.0.1. Deshalb verwendet der Wiederherstellungstest in Schritt 8 einen SSH-Tunnel.

Wie verhindere ich, dass sich Unbefugte auf meinem Server registrieren?

Setzen Sie SIGNUPS_ALLOWED: "false" in der Compose-Datei und führen Sie docker compose up -d direkt nach der Erstellung Ihres eigenen Kontos aus. Fügen Sie neue Personen danach über die Schaltfläche Invite User in /admin hinzu. Dafür muss SMTP konfiguriert sein, damit die Personen den Einladungslink erhalten. Prüfen Sie die Liste der Administratorkonten gelegentlich, um unerwartete Konten zu erkennen.

Wie sichere ich meinen Vaultwarden-Tresor?

Stoppen Sie den Container kurz und archivieren Sie das gesamte Volume vw-data, außerdem db.sqlite3, attachments/, sends/, config.json und die Dateien rsa_key.*. Kopieren Sie das Archiv anschließend vom Server weg, idealerweise jeden Abend über cron. Wenn Sie die aktive SQLite-Datei kopieren, während der Server läuft, kann der Snapshot beschädigt sein. Erstellen Sie die Sicherung daher im gestoppten Zustand. Stellen Sie sie vor allem einmal in einem Wegwerf-Container wieder her und melden Sie sich an. So wissen Sie, dass die Sicherung tatsächlich verwendbar ist, bevor Sie sich darauf verlassen.

Ist es wirklich sicher, meine Passwörter selbst zu hosten?

Ja, wenn Sie die drei Punkte aus diesem Leitfaden umsetzen: echtes HTTPS, geschlossene Registrierungen mit einem starken Admin-Token sowie getestete Sicherungen. Ihr Tresor wird clientseitig mit Ihrem Master-Passwort verschlüsselt. Selbst der Server sieht Ihre Passwörter daher nie im Klartext. Auch ein gestohlenes db.sqlite3 gibt Ihre Einträge ohne dieses Passwort nicht preis. Der Server enthält jedoch weiterhin die E-Mail-Adressen der Konten und einen gesalzenen Hash, der aus jedem Master-Passwort abgeleitet wird. Ein Angreifer kann versuchen, diesen Hash offline zu knacken. Schützen Sie daher die Datenbankdatei und jede Kopie davon. Der Nachteil besteht darin, dass Sie nun für Patches und Sicherungen verantwortlich sind. Deshalb sind Fail2ban und der Wiederherstellungstest hier unverzichtbar. Sobald diese Maßnahmen umgesetzt sind, ist eine genauere Betrachtung der tatsächlichen Angriffsmöglichkeiten eines selbst gehosteten Tresors der sinnvolle nächste Schritt. Da die Einträge selbst clientseitig verschlüsselt sind, müssen Sie vor allem noch das Admin-Token und das Sicherungsarchiv schützen.