Hand aufs Herz: Wie viele deiner Passwörter sind Variationen von ein und demselben Wort? Eben. Ein Passwort-Manager löst das Problem — aber dann liegen alle deine Zugänge bei einem Cloud-Anbieter, und du musst hoffen, dass der seinen Job ernst nimmt. Es gibt einen dritten Weg: Vaultwarden, ein schlanker, quelloffener Server, der die komplette Bitwarden-Welt spricht. Die offiziellen Bitwarden-Apps auf Handy, Desktop und im Browser verbinden sich damit, als wäre es das Original — nur dass der Tresor bei dir im Homelab steht. Genau das bauen wir jetzt.

Kurz gesagt: Am Ende läuft Vaultwarden als Docker-Container hinter dem Reverse Proxy Caddy, mit automatischem HTTPS-Zertifikat, geschlossener Registrierung und einem Backup-Plan. Dauer: rund 30 Minuten. Schwierigkeitsgrad: Einsteiger mit Docker-Grundlagen.
Schaubild: Vaultwarden in 3 Schritten installieren — Bauplan anlegen, starten und anmelden, Tür zuschließen
Der ganze Weg auf einen Blick — die Details zu jedem Schritt folgen unten.

Was du brauchst

  • Einen Server mit Docker samt Compose-Plugin (Test: docker compose version) — falls Docker bei dir noch nicht läuft, haben wir die Grundlagen in der Uptime-Kuma-Anleitung schon einmal durchgekaut
  • Eine eigene (Sub-)Domain wie vault.example.com, die auf deinen Server zeigt: Die braucht Caddy für das HTTPS-Zertifikat. Die Ports 80 und 443 müssen dafür aus dem Internet erreichbar sein
  • SSH-Zugang und ein bisschen Terminal-Grundwissen
  • Rund 30 Minuten Zeit

Warum der Aufwand mit HTTPS? Weil es ohne schlicht nicht geht: Der Web-Tresor von Bitwarden nutzt Verschlüsselungs-Funktionen, die Browser nur über HTTPS freigeben. Über blankes HTTP bekommst du eine Seite, die hübsch aussieht und nichts tut. Deshalb ist der Reverse Proxy hier kein Nice-to-have, sondern Teil der Grundausstattung.

Reverse Proxy? Der Türsteher vor deinen Diensten: Jede Anfrage aus dem Internet landet zuerst bei ihm, er übernimmt die HTTPS-Verschlüsselung und reicht die Anfrage dann intern an den richtigen Dienst weiter. Caddy ist die einsteigerfreundlichste Variante — er besorgt und verlängert die Zertifikate von selbst.
Handy / Browser→ HTTPS :443 →Caddy→ intern :80 →Vaultwarden

Schritt 1: Projektordner und Compose-Datei anlegen

Erst mal ein Zuhause für den Tresor:

mkdir -p ~/vaultwarden
cd ~/vaultwarden

Darin erstellst du die Datei compose.yaml — sie beschreibt beide Container, Vaultwarden und Caddy. Das ist die offizielle Vorlage aus dem Vaultwarden-Wiki, mit deutschen Kommentaren:

services:
  vaultwarden:
    image: vaultwarden/server:latest
    container_name: vaultwarden
    restart: always
    environment:
      DOMAIN: "https://vault.example.com"  # deine Domain — mit https davor
      SIGNUPS_ALLOWED: "true"              # nach dem Anlegen deines Kontos auf "false" stellen
    volumes:
      - ./vw-data:/data                    # hier lebt der Tresor — ohne diese Zeile ist er weg

  caddy:
    image: caddy:2
    container_name: caddy
    restart: always
    ports:
      - 80:80         # braucht Let's Encrypt für die Zertifikats-Ausstellung
      - 443:443
      - 443:443/udp   # HTTP/3
    volumes:
      - ./Caddyfile:/etc/caddy/Caddyfile:ro
      - ./caddy-config:/config
      - ./caddy-data:/data
    environment:
      DOMAIN: "https://vault.example.com"  # deine Domain
      EMAIL: "du@example.com"              # E-Mail für Let's Encrypt
      LOG_FILE: "/data/access.log"

Trage bei DOMAIN und EMAIL deine echten Werte ein, an beiden Stellen dieselbe Domain. Und falls es dir aufgefallen ist: Der Vaultwarden-Container hat absichtlich keine ports-Zeile. Nur Caddy ist von außen erreichbar, Vaultwarden selbst bleibt im internen Docker-Netz. Genau so soll es sein.

Schritt 2: Caddyfile anlegen

Im selben Ordner kommt jetzt die Datei Caddyfile dazu — die Anweisung für den Türsteher. Sie liest die Werte aus der Compose-Datei, du musst hier also nichts mehr anpassen:

{$DOMAIN} {
  log {
    level INFO
    output file {$LOG_FILE} {
      roll_size 10MB
      roll_keep 10
    }
  }

  # Zertifikat automatisch per Let's Encrypt holen
  tls {$EMAIL}

  encode zstd gzip

  # alles an Vaultwarden weiterreichen
  reverse_proxy vaultwarden:80 {
       header_up X-Real-IP {remote_host}
  }
}

Mehr ist es nicht. Caddy kümmert sich ab jetzt selbstständig darum, das Zertifikat zu holen und rechtzeitig zu verlängern. Bei anderen Reverse Proxies füllt dieses Thema ganze Wochenenden.

Schritt 3: Starten und Konto anlegen

docker compose up -d && docker compose logs -f

Docker lädt beide Images, startet die Container, und Caddy holt sich im Hintergrund das Zertifikat. Wenn die Logs ruhig geworden sind (Abbruch mit Strg+C, die Container laufen weiter), öffnest du https://vault.example.com im Browser und legst dein Konto an.

Ein Wort zum Master-Passwort, ganz ohne Augenzwinkern: Es ist der einzige Schlüssel zu allem, was du ab jetzt in den Tresor legst. Vaultwarden kann es nicht zurücksetzen, weil dein Tresor damit verschlüsselt ist. Nimm einen langen Satz, den du dir merken kannst, und bewahre eine Kopie an einem sicheren Ort auf — analog, auf Papier.

Jetzt kommt der Teil, der Spaß macht: die Apps verbinden. In der Bitwarden-App und der Browser-Erweiterung tippst du vor dem Login auf die Server-Auswahl (meist „Selbst gehostet" oder das kleine Zahnrad) und trägst https://vault.example.com als Server-URL ein. Danach anmelden wie gewohnt — nur dass deine Passwörter jetzt zu dir nach Hause synchronisieren.

Schritt 4: Tür zu — Registrierung schließen und Admin-Token setzen

Dein Konto steht, also schließen wir die offene Tür: Aktuell könnte sich jeder, der deine Domain findet, ein Konto auf deinem Server anlegen. In der compose.yaml stellst du dafür um auf:

      SIGNUPS_ALLOWED: "false"

Dazu spendieren wir noch den Zugang zur Admin-Oberfläche, über die du später Nutzer verwalten und Einstellungen ändern kannst. Dafür braucht es ein Admin-Passwort — und zwar nicht im Klartext in der Compose-Datei, sondern als Argon2-Hash. Den erzeugt Vaultwarden praktischerweise selbst:

docker run --rm -it vaultwarden/server /vaultwarden hash
Argon2-Hash? Eine Einbahnstraßen-Verschlüsselung für Passwörter: Aus deinem Passwort wird eine lange Zeichenkette berechnet, aus der sich das Passwort nicht mehr zurückrechnen lässt. Selbst wer deine Compose-Datei in die Finger bekommt, kennt damit dein Admin-Passwort nicht.

Der Befehl fragt zweimal nach einem Passwort deiner Wahl und spuckt dann eine Zeichenkette aus, die mit $argon2id$ beginnt. Ein Stolperdraht dabei: In der Compose-Datei musst du jedes Dollarzeichen verdoppeln, sonst interpretiert Docker Compose die $-Zeichen als Variablen und der Login schlägt fehl. Das Ganze kommt als neue Zeile zu den environment-Einträgen von Vaultwarden:

      ADMIN_TOKEN: "$$argon2id$$v=19$$m=65540,t=3,p=4$$..."   # deine Ausgabe, alle $ zu $$ verdoppelt

Dann die Änderungen übernehmen:

docker compose up -d

Die Admin-Oberfläche findest du ab jetzt unter https://vault.example.com/admin — Zugang mit dem Passwort, das du gerade gehasht hast.

Schritt 5: Backup einrichten

Ein selbst gehosteter Passwort-Manager ohne Backup ist ein Tresor auf einem wackligen Tisch. Alles Wichtige liegt im Ordner vw-data: die Datenbank db.sqlite3, der Ordner attachments, die rsa_key-Dateien und die config.json. Die Datenbank sicherst du am besten nicht per einfachem Kopieren, sondern mit dem SQLite-eigenen Backup-Mechanismus — der funktioniert auch, während Vaultwarden läuft:

sqlite3 vw-data/db.sqlite3 ".backup '/pfad/zu/backups/db-$(date '+%Y%m%d-%H%M').sqlite3'"

Den Rest des Ordners kannst du normal mitkopieren. Pack das in einen Cronjob, leg die Backups auf eine zweite Platte oder einen anderen Rechner, und teste einmal, ob sich aus so einem Backup wirklich alles wiederherstellen lässt. Ein Backup, das nie getestet wurde, ist eine Hoffnung mit Dateinamen.

Häufige Stolpersteine

Die Seite lädt, aber Login oder Tresor rühren sich nicht. Fast immer: Du bist über HTTP statt HTTPS unterwegs, etwa direkt über die IP. Die Verschlüsselungs-Funktionen des Web-Tresors gibt der Browser nur in HTTPS-Kontexten frei. Da führt kein Weg dran vorbei: immer über die Domain und HTTPS zugreifen.

Der Admin-Login scheitert, obwohl das Passwort stimmt. Dann sind mit hoher Wahrscheinlichkeit die Dollarzeichen im ADMIN_TOKEN nicht verdoppelt. Docker Compose hat sie als Variablen gefressen. Alle fünf $ zu $$ machen und docker compose up -d erneut ausführen.

Port 80 oder 443 ist schon belegt. Läuft bei dir bereits ein Reverse Proxy wie Nginx Proxy Manager oder Traefik? Dann lass den Caddy-Block einfach weg, gib dem Vaultwarden-Container ein Port-Mapping wie 11001:80 und häng ihn hinter deinen bestehenden Proxy. Die DOMAIN-Variable bleibt trotzdem gesetzt. Fertige Konfigurationen für alle gängigen Proxies listet das Wiki unter „Proxy examples".

Du hast keine öffentliche Domain oder willst den Tresor gar nicht ins Internet stellen. Auch dafür gibt es einen offiziellen Weg: die Caddy-Variante mit DNS-Challenge (z.B. über Duck DNS). Damit bekommst du ein echtes Zertifikat, obwohl der Server nur im Heimnetz erreichbar ist. Die Anleitung dazu steht im selben Wiki-Artikel wie unsere Compose-Vorlage.

Fazit

Meine Einschätzung: Vaultwarden ist einer der lohnendsten Dienste, die man selbst hosten kann. Die Bitwarden-Apps sind ausgereift, der Server begnügt sich mit ein paar Megabyte RAM und läuft problemlos auf einem Raspberry Pi. Dafür übernimmst du echte Verantwortung: Updates einspielen und Backups pflegen sind ab jetzt dein Job, nicht der eines Anbieters. Wer dazu keine Lust hat, fährt mit dem offiziellen Bitwarden-Cloud-Angebot ehrlicherweise besser. Alle anderen bekommen hier volle Kontrolle über ihre sensibelsten Daten — und übrigens auch einen Ort für Passkeys, falls du nach unserem Beitrag zu den WhatsApp-Passkeys auf den Geschmack gekommen bist.

Wie hältst du es mit deinen Passwörtern — alles selbst hosten oder liegen die Kronjuwelen bei dir bewusst in der Cloud, weil ein Anbieter-Rechenzentrum seltener ausfällt als ein Homelab? Und traust du dich, auch den Rest der Familie auf den eigenen Server umzuziehen? Schreib's in die Kommentare.

One more thing … wenn deine Container-Sammlung so langsam wächst, lohnt ein Blick auf unsere Meldung zu Portainer 2.45 LTS — gerade weil die Version eine kritische Lücke stopft.

Quellen