Vaultwarden: eigener Passwortmanager hinter Traefik
Vaultwarden selbst hosten: ein schlanker, Bitwarden-kompatibler Passwortmanager hinter Traefik mit HTTPS, Admin-Panel und verschlüsseltem Backup.
Inhaltsverzeichnis
Passwörter gehören in einen Passwortmanager – aber müssen sie in der Cloud eines fremden Anbieters liegen? Mit Vaultwarden hostest du deinen eigenen, verschlüsselt und unter deiner Kontrolle. Er spricht die Bitwarden-Sprache, also nutzt du die gewohnten Bitwarden-Apps und -Browser-Erweiterungen – nur zeigen sie auf deinen Server.
Was bauen wir?
Am Ende läuft Vaultwarden 1.36 in einem Container hinter deinem Traefik-Proxy,
erreichbar unter https://vault.DEINE_DOMAIN mit gültigem HTTPS-Zertifikat. Vaultwarden
ist eine schlanke, in Rust geschriebene Neuimplementierung des Bitwarden-Servers:
API-kompatibel, aber sparsam genug, um auf einem kleinen VPS zu laufen. Du verbindest
die offiziellen Bitwarden-Clients (Browser-Erweiterung, Handy-App, Desktop) mit
deinem Server, legst deine Zugangsdaten ab – Ende-zu-Ende verschlüsselt – und
verwaltest den Dienst über ein abgesichertes Admin-Panel.
Deine Passwörter liegen damit auf deinem Server, in deinem Land, unter deinem Backup – und du zahlst keine Abo-Gebühr für Funktionen wie 2FA oder Attachments.
Vaultwarden ≠ Bitwarden
Voraussetzungen
- Ein laufender Traefik-Reverse-Proxy mit dem gemeinsamen
proxy-Netzwerk und dem Let’s-Encrypt-Resolverle– genau das Setup aus dem Tutorial Reverse Proxy mit Traefik. Ohne Traefik funktioniert dieses Rezept nicht: Vaultwarden verlangt HTTPS. - Eine Subdomain, z. B.
vault.DEINE_DOMAIN, deren DNS-Record (A/AAAA) auf deine Server-IP zeigt – siehe Domain mit Server verbinden. - Ein funktionierendes Backup deines Servers. Ein Passwortmanager ist der Ort, an dem Datenverlust am meisten wehtut – richte, falls noch nicht geschehen, zuerst Backups mit Restic ein.
VPS 1000 G12
4 vCore · 8 GB RAM · 256 GB NVMe
ab 10,36 €/Monat
Vaultwarden ist so sparsam, dass schon der kleinste VPS locker reicht.
Schritt für Schritt
Schritt 1: Den ADMIN_TOKEN erzeugen
Vaultwarden hat ein Admin-Panel unter /admin. Zugriff darauf schützt ein
ADMIN_TOKEN. Den solltest du nicht im Klartext hinterlegen, sondern als Hash –
dann steht dein Panel-Passwort nirgends lesbar in der Compose-Datei.
Vaultwarden bringt dafür einen eigenen Befehl mit. Wir lassen ihn kurz in einem Wegwerf-Container laufen:
docker run --rm -it vaultwarden/server:1.36.0 /vaultwarden hash --preset owaspDer Befehl fragt dich zweimal nach einem Passwort (Eingabe bleibt unsichtbar) und gibt dann einen Argon2id-Hash aus – eine lange Zeichenkette, die so beginnt:
Generate an Argon2id PHC string using the 'owasp' preset.
Password:
Confirm Password:
ADMIN_TOKEN='$argon2id$v=19$m=19456,t=2,p=1$FkxFEQ64Wy4zlQOWMI1fJ...$TxULe6MSND3By6GPVPKB1...'Kopiere die komplette Zeichenkette zwischen den Anführungszeichen (inklusive der
$argon2id$…-Teile) heraus – die brauchst du gleich. Das Passwort, das du hier
eingegeben hast, ist dein Admin-Panel-Passwort; leg es im Passwortmanager ab (fürs
Erste noch im alten).
Warum der Umweg über den Hash?
ADMIN_TOKEN auch als Klartext-Passwort setzen. Der Hash ist aber
sicherer: Selbst wer deine compose.yaml in die Finger bekommt, kann daraus dein
Panel-Passwort nicht zurückrechnen. --preset owasp wählt Argon2-Parameter nach der
aktuellen OWASP-Empfehlung.Schritt 2: Die compose.yaml anlegen
Leg einen eigenen Ordner an und wechsle hinein:
mkdir -p ~/vaultwarden && cd ~/vaultwardenErstelle die compose.yaml. Ersetze vault.DEINE_DOMAIN durch deine echte Subdomain
und den ADMIN_TOKEN durch den Hash aus Schritt 1:
services:
vaultwarden:
image: vaultwarden/server:1.36.0
volumes:
- ./vw-data:/data
environment:
DOMAIN: "https://vault.DEINE_DOMAIN"
SIGNUPS_ALLOWED: "true"
ADMIN_TOKEN: "$$argon2id$$v=19$$m=19456,t=2,p=1$$FkxFE...$$TxULe..."
labels:
- "traefik.enable=true"
- "traefik.http.routers.vaultwarden.rule=Host(`vault.DEINE_DOMAIN`)"
- "traefik.http.routers.vaultwarden.entrypoints=websecure"
- "traefik.http.routers.vaultwarden.tls.certresolver=le"
- "traefik.http.services.vaultwarden.loadbalancer.server.port=80"
networks:
- proxy
restart: unless-stopped
networks:
proxy:
external: trueDie wichtigsten Zeilen im Detail:
image: vaultwarden/server:1.36.0– wir pinnen die Version bewusst fest, stattlatestzu nehmen. So aktualisierst du kontrolliert (siehe „Wartung"). Für ein noch kleineres Image gibt es auch:1.36.0-alpine.volumes: ./vw-data:/data– hier liegen deine Datenbank (db.sqlite3), die Verschlüsselungs-Keys und die Attachments. Dieses Volume ist Pflicht. Ohne Volume verweigert Vaultwarden absichtlich den Start, damit du deine Daten nicht in einem flüchtigen Container verlierst.DOMAIN– die vollständige HTTPS-URL. Vaultwarden braucht sie u. a. für WebAuthn/ 2FA und Einladungslinks. Muss exakt zu deiner Router-Regel passen.SIGNUPS_ALLOWED: "true"– erlaubt vorerst die Registrierung, damit du dein erstes Konto anlegen kannst. Das drehen wir gleich wieder ab.ADMIN_TOKEN– dein Hash aus Schritt 1. Wichtig: In einer Compose-Datei muss jedes Dollarzeichen verdoppelt werden ($→$$), sonst versucht Compose, es als Variable zu interpretieren. Aus$argon2id$…wird also$$argon2id$$….loadbalancer.server.port=80– Vaultwarden lauscht im Container auf Port 80. Diese Zeile sagt Traefik explizit, wohin es intern weiterleiten soll, statt den Zielport aus dem Image raten zu lassen – dasselbe Muster wie bei jeder App hinter Traefik.- Kein
ports:– wie bei jeder App hinter Traefik ist Vaultwarden nur über den Proxy erreichbar, niemals direkt von außen.
Schritt 3: Starten und den ersten Aufruf
Starte den Container:
docker compose up -dBeim ersten Start legt Vaultwarden das Datenverzeichnis an und initialisiert die Datenbank. Wirf einen Blick ins Log:
docker compose logs -f vaultwardenDu solltest am Ende diese Zeile sehen – sie bestätigt, dass der Dienst läuft:
[INFO] Rocket has launched from http://0.0.0.0:80Mit Strg+C verlässt du die Log-Ansicht wieder (der Container läuft weiter). Ruf jetzt
https://vault.DEINE_DOMAIN im Browser auf. Traefik holt beim ersten Zugriff das
Let’s-Encrypt-Zertifikat – das kann ein paar Sekunden dauern. Danach erscheint die
Bitwarden-Web-Oberfläche.
Klick auf Konto erstellen und leg dein erstes Konto an – mit deiner E-Mail-Adresse und einem Namen:

Im nächsten Schritt legst du dein Master-Passwort fest. Das ist der eine Schlüssel, der deinen gesamten Tresor entsperrt:

Das Master-Passwort ist nicht wiederherstellbar
Schritt 4: Die Registrierung wieder schließen
Sobald dein Konto steht, willst du verhindern, dass Fremde sich ebenfalls
registrieren können – dein Vaultwarden hängt schließlich offen im Internet. Setz
SIGNUPS_ALLOWED in der compose.yaml auf false:
environment:
DOMAIN: "https://vault.DEINE_DOMAIN"
SIGNUPS_ALLOWED: "false"
ADMIN_TOKEN: "$$argon2id$$..."Und übernimm die Änderung:
docker compose up -dCompose erkennt die geänderte Umgebungsvariable und startet den Container neu. Ab jetzt weist die Anmeldeseite neue Registrierungen ab. Weitere Nutzer (z. B. für die Familie) lädst du bei Bedarf gezielt über das Admin-Panel ein – dazu gleich mehr.
Nicht vergessen
SIGNUPS_ALLOWED: "true" ist die häufigste Fehlkonfiguration bei
selbst gehostetem Vaultwarden. Jeder, der deine Domain kennt, könnte sich sonst ein
Konto anlegen. Dieser Schritt ist Pflicht, kein Extra.Schritt 5: Das Admin-Panel
Ruf https://vault.DEINE_DOMAIN/admin auf und melde dich mit dem Passwort an, das
du in Schritt 1 beim Erzeugen des Hashes eingegeben hast (nicht mit dem Hash selbst).
Du landest in der Verwaltungsoberfläche:

Hier steuerst du den Dienst zentral:
- Users – vorhandene Nutzer einsehen, neue einladen (auch bei
SIGNUPS_ALLOWED=false), Konten deaktivieren. - Settings → SMTP Email Settings – trag hier die Zugangsdaten deines Mail-Servers ein, damit Vaultwarden Einladungen und 2FA-Codes per Mail verschicken kann. Ohne SMTP funktioniert die Einladung per Link zwar auch, aber E-Mail-basierte 2FA nicht.
- Diagnostics – zeigt dir, ob deine
DOMAINkorrekt gesetzt ist und ob Vaultwarden von außen erreichbar ist – praktisch bei der Fehlersuche.
Einstellungen im Panel vs. Umgebungsvariablen
vw-data/config.json abgelegt und
überschreibt die Umgebungsvariablen aus der compose.yaml. Entscheide dich pro
Einstellung für einen Weg, um Verwirrung zu vermeiden. Für die Grund-Konfiguration
(Domain, Token, Signups) bleiben wir bewusst bei der Compose-Datei – sie ist
versionierbar und reproduzierbar.Schritt 6: Die Clients verbinden
Jetzt kommt der eigentliche Nutzen. Installiere die offizielle Bitwarden-App oder -Browser-Erweiterung (aus dem jeweiligen App- bzw. Add-on-Store). Bevor du dich anmeldest, stellst du den Server um:
- Öffne in der App/Erweiterung noch vor dem Login die Einstellungen für die selbst gehostete Umgebung (Zahnrad-Symbol bzw. „Region: Selbst gehostet").
- Trag als Server-URL
https://vault.DEINE_DOMAINein und speichere. - Melde dich jetzt mit deiner E-Mail und deinem Master-Passwort an – die App spricht ab sofort mit deinem Server.
Das Schöne: Es sind dieselben ausgereiften Clients wie beim kommerziellen Bitwarden. Autofill, Passwort-Generator, sichere Notizen, Attachments und 2FA-Speicherung funktionieren genauso – nur liegen die Daten auf deinem Server.
Bestehende Passwörter importieren: Wechselst du von einem anderen Manager (oder
dem Browser-Passwortspeicher), musst du nicht alles abtippen. Exportiere dort deine
Einträge als CSV oder JSON und importiere sie über die Web-Oberfläche unter
Werkzeuge → Daten importieren. Vaultwarden versteht die Exportformate der gängigen
Manager (KeePass, LastPass, 1Password, Chrome/Firefox u. a.) direkt.
Export-Dateien danach sicher löschen
Zwei-Faktor-Authentifizierung aktivieren
Wenn es nicht funktioniert
Symptom: Der Container startet nicht, das Log sagt sinngemäß
Running without a persistent volume is not recommended.
Ursache & Lösung: Es fehlt das volumes:-Mapping. Vaultwarden verweigert absichtlich
den Start ohne Datenverzeichnis, damit deine Passwörter nicht in einem flüchtigen
Container landen. Ergänze ./vw-data:/data wie in Schritt 2 und starte neu.
Symptom: Die Web-Oberfläche zeigt „You need to enable HTTPS!" oder der Login scheitert mit Krypto-Fehlern.
Ursache & Lösung: Vaultwarden nutzt die Web-Crypto-API des Browsers, die nur in
einem sicheren Kontext (echtes HTTPS) verfügbar ist. Du hast die Seite über http://
oder mit ungültigem Zertifikat aufgerufen. Stell sicher, dass Traefik ein gültiges
Let’s-Encrypt-Zertifikat geholt hat (Traefik-Log prüfen) und du die Seite über
https:// erreichst. Die DOMAIN-Variable muss ebenfalls mit https:// beginnen.
Symptom: Das Admin-Panel weist dein Passwort ab, obwohl es stimmt.
Ursache & Lösung: Vermutlich sind die Dollarzeichen im ADMIN_TOKEN nicht
verdoppelt. In der compose.yaml muss aus jedem $ ein $$ werden. Prüfe mit
docker compose config, wie der Token tatsächlich ankommt (Compose zeigt dort den
aufgelösten Wert). Denk auch daran: Beim Login gibst du das Passwort ein, nicht den
Hash.
Symptom: Die Handy-App findet den Server nicht oder meldet „Server-URL ungültig".
Ursache & Lösung: Die Server-URL muss die vollständige https://-Adresse ohne
abschließenden Pfad sein (https://vault.DEINE_DOMAIN). Prüfe außerdem, ob die Domain
von außen per Browser erreichbar ist und das Zertifikat gültig ist – Apps sind bei
Zertifikatsfehlern strenger als Browser.
Symptom: Trotz SIGNUPS_ALLOWED=false konnte sich jemand registrieren.
Ursache & Lösung: Wahrscheinlich wurde die Einstellung im Admin-Panel gesetzt und
überschreibt die Umgebungsvariable, oder der Container wurde nach der Änderung nicht neu
gestartet. Kontrolliere den Wert unter Settings → General settings im Panel und
starte mit docker compose up -d neu.
Wartung & Backups
Backups sind bei einem Passwortmanager nicht verhandelbar. Dein gesamter Tresor steckt im Verzeichnis
vw-data/(SQLite-Datenbank, Keys, Attachments). Sichere es verschlüsselt und off-site mit Restic – nimm den Ordner~/vaultwarden/vw-datain deine Backup-Quellen auf. Für einen konsistenten Datenbank-Stand führst du vor dem Backup kurzdocker compose stopaus oder nutzt die „Backup Database"-Funktion im Admin-Panel. Eine bloße Dateikopie bei laufendem Container kann dagegen einen inkonsistenten Stand erwischen (SQLite schreibt in WAL-Dateien) – bei einem Passwortmanager ist das kein Risiko wert.Updates kontrolliert einspielen. Weil wir die Version gepinnt haben, aktualisierst du bewusst: Vor dem Wechsel die Release-Notes lesen, dann den Tag in der
compose.yamlerhöhen (z. B. auf die nächste1.x) und neu ziehen:Terminaldocker compose pull && docker compose up -dPrüfe danach im Log wieder die
Rocket has launched-Zeile und teste einen Login.Registrierung geschlossen lassen. Kontrolliere gelegentlich, dass
SIGNUPS_ALLOWEDweiterhinfalseist – neue Nutzer immer gezielt über das Admin-Panel einladen.ADMIN_TOKEN rotieren, wenn er kompromittiert sein könnte: neuen Hash mit dem
hash-Befehl aus Schritt 1 erzeugen, in dercompose.yamlersetzen, neu starten.Master-Passwort niemals verlieren. Es gibt keine Wiederherstellung. Bei einem Team/Familien-Setup kann ein Notfall-Zugang (Emergency Access) sinnvoll sein – den richtest du pro Tresor in den Kontoeinstellungen ein.
Feedback per E-Mail: feedback@serverkueche.de
Das könnte dir auch schmecken

Immich selbst hosten: dein privates Foto-Backup hinter Traefik
Immich mit Docker hinter Traefik aufsetzen: die selbst gehostete Alternative zu Google Fotos – mit automatischem …

Paperless-ngx selbst hosten: papierloses Büro mit OCR
Paperless-ngx mit Docker hinter Traefik aufsetzen: Dokumente per OCR durchsuchbar archivieren – mit Volltextsuche, Tags …

Nextcloud selbst hosten: deine eigene Cloud hinter Traefik
Nextcloud mit Docker hinter Traefik aufsetzen: eigene Cloud für Dateien, Kalender und Kontakte – mit MariaDB, Redis und …