Ein Passwort-Manager ist die eine Datei, die du nie verlieren darfst und nie in fremde Hände geben willst. Genau deshalb landet sie bei den meisten in einer Cloud, die beides verspricht. Vaultwarden dreht das um: Der Tresor liegt auf deinem Rechner, und die Apps auf Handy, Laptop und im Browser bleiben die von Bitwarden, weil Vaultwarden deren Sprache spricht.

Der Haken steht nicht auf der Startseite, sondern in der FAQ: Die Bitwarden-Apps brauchen eine sichere Verbindung, sonst verweigern sie Teile der Arbeit. Ohne HTTPS kein Tresor, auch nicht im eigenen Wohnzimmer. Darum ist das hier keine Anleitung mit einem Container, sondern mit zwei: Vaultwarden und davor Caddy, der sich das Zertifikat selbst besorgt. Das klingt nach mehr Arbeit, ist aber der Teil, den alle anderen Anleitungen „für später“ aufheben und dann nie nachliefern.

Kurz gesagt: Am Ende läuft Vaultwarden auf deinem Server, erreichbar unter einer eigenen Adresse mit echtem Let's-Encrypt-Zertifikat, aber nur aus deinem Heimnetz. Die Bitwarden-Apps sind verbunden, die Registrierung ist zu, die Admin-Seite gesichert, das erste Backup liegt auf der Platte. Dauer: eine Stunde, wenn DuckDNS mitspielt. Schwierigkeit: Standard, du kennst Docker und die Kommandozeile im Groben. Stand: Vaultwarden 1.37.2, geprüft am 07-09-2026.
Vaultwarden in vier Schritten: DuckDNS-Name anlegen, vier Dateien schreiben, starten und HTTPS prüfen, Konto und Apps einrichten
Der ganze Weg auf einen Blick: Name, Dateien, Zertifikat, Konto.

Was Vaultwarden ist und warum Caddy mit muss

Vaultwarden? Ein Nachbau des Bitwarden-Servers, in Rust geschrieben, der mit denselben Apps redet. Stell dir vor, du wechselst die Küche, aber Teller, Besteck und Rezepte bleiben gleich. Die Apps merken den Unterschied nicht, nur dein Stromzähler: Vaultwarden kommt mit ein paar Dutzend Megabyte Arbeitsspeicher aus.

Dass ein einzelner Entwickler, Daniel García, den kompletten Bitwarden-Server so nachgebaut hat, dass die offiziellen Apps ihn für das Original halten, ist eine Leistung, die ich jedes Mal wieder gern erwähne. Inzwischen hält ein kleines Team das Projekt im Takt der Bitwarden-Apps. Das ist auch der Grund, warum du später bei den Updates dranbleiben musst, aber dazu weiter unten.

Der Datenfluss ist kurz. Die App spricht deine Adresse an, Caddy nimmt die Verbindung verschlüsselt entgegen und reicht sie unverschlüsselt im Docker-Netz an Vaultwarden weiter. Vaultwarden selbst hört auf Port 80 und bekommt von außen nie jemanden zu sehen.

Handy, Browser→ https://meintresor.duckdns.org →Caddy (Zertifikat)→ Port 80, nur intern →Vaultwarden→ speichert in →./vw-data

Für das Zertifikat braucht Caddy einen Namen, den Let's Encrypt kennt. Da dein Server nicht aus dem Internet erreichbar ist (und das soll er auch nicht), geht die übliche Prüfung nicht. Das Vaultwarden-Wiki hat dafür eine eigene Seite, und die geht über den Umweg DNS.

DNS-Challenge? Let's Encrypt will einen Beweis, dass dir der Name gehört. Normalerweise klingelt es dafür an deiner Haustür, also an deinem Server. Bei der DNS-Challenge legst du stattdessen einen Zettel in den Briefkasten, den Nameserver. Der ist von außen lesbar, dein Server bleibt hinter der Tür.

Den Namen liefert DuckDNS, ein kostenloser Dienst für dynamische Adressen. Die DuckDNS-FAQ verliert kein Wort darüber, ob man dort eine private Adresse wie 192.168.178.20 eintragen darf. Das Vaultwarden-Wiki tut es einfach, und es funktioniert, weil DuckDNS speichert, was man ihm gibt. Der Name zeigt dann ins Heimnetz, und nur dort hilft er weiter.

Was du brauchst

Einen Linux-Rechner mit Docker und dem Compose-Plugin, der dauerhaft läuft. Der alte Büro-PC reicht; Vaultwarden ist eine der genügsamsten Anwendungen, die du hosten kannst. Läuft Docker noch nicht, hilft dir die Docker-Doku, und du kommst danach hierher zurück. Prüfen:

So liest du diese Anleitung: Alles, was du selbst tun sollst, steht in einem farbigen Kasten. [ per klick ] heißt: Das erledigst du mit der Maus in einer Web-Oberfläche, hier bei DuckDNS, in deiner FritzBox oder im Bitwarden-Tresor im Browser. [ über die shell ] heißt: Den Befehl kopieren, ins Terminal einfügen, Enter. Stehen beide Kästen direkt untereinander, führen sie zum selben Ergebnis. Du gehst EINEN davon, nicht beide.
docker --version
docker compose version

Beide Befehle geben eine Versionsnummer aus. Dann Port 443, den Caddy nach außen belegt. Der Befehl darf nichts ausgeben:

ss -tulpn | grep :443

Kommt eine Zeile zurück, sitzt dort schon etwas, meist ein Reverse Proxy, den du schon hast. Dann brauchst du den Caddy aus dieser Anleitung nicht, sondern hängst Vaultwarden hinter deinen vorhandenen Türsteher. Wie das im Grundsatz geht, steht in Was ist ein Reverse Proxy?; wer das Ding auf 443 ist, findest du mit Port belegt? So findest du den Schuldigen heraus.

Dazu ein Konto bei duckdns.org, Anmeldung mit GitHub-, Google- oder anderem Login, kostet nichts. Und die IP-Adresse deines Servers im Heimnetz:

hostname -I

Die erste Adresse der Ausgabe ist deine. In dieser Anleitung heißt sie so:

  • IP-Adresse des Servers im Heimnetz: 192.168.178.20
  • DuckDNS-Adresse für den Tresor: meintresor.duckdns.org
  • Projektordner auf dem Server: ~/vaultwarden
  • Datenordner von Vaultwarden: ~/vaultwarden/vw-data
  • Port nach außen: 443 (Caddy); Vaultwarden hört nur im Docker-Netz auf 80

Schritt 1: Der Name zeigt ins Heimnetz

Bei DuckDNS legst du die Subdomain an und trägst als IP die private Adresse deines Servers ein, nicht die deines Internetanschlusses. Den Token findest du laut DuckDNS-FAQ auf der Kontoseite; er ist das Passwort, mit dem Caddy gleich den Beweis-Zettel in den Nameserver legt.

Auf duckdns.org anmelden. Im Feld sub domain den Namen meintresor eintippen, add domain. In der Zeile der neuen Domain im Feld current ip die Adresse 192.168.178.20 eintragen, update ip. Den token oben auf der Seite kopieren und irgendwo ablegen, du brauchst ihn in Schritt 2.

Domain und Token hast du im Browser angelegt; die IP setzt du auch per Aufruf der Update-Adresse aus der DuckDNS-Doku (Token einsetzen):

curl "https://www.duckdns.org/update?domains=meintresor&token=DEIN-TOKEN&ip=192.168.178.20"

Antwort: OK.

Jetzt die Probe, ob dein Netz den Namen auch auflöst. Vom Server aus:

nslookup meintresor.duckdns.org

Steht in der Antwort Address: 192.168.178.20, ist der Name da. Steht dort NXDOMAIN oder No answer, hast du eine FritzBox oder einen anderen Router mit DNS-Rebind-Schutz. Der unterdrückt Antworten, in denen ein öffentlicher Name auf eine private Adresse zeigt, weil das eine bekannte Angriffsmasche ist. In der Vaultwarden-Diskussion 4139 auf GitHub hat Nutzer Sonnex7 erst bei Pi-hole und Nginx gesucht, bis sich der Router als Ursache herausstellte. Die Ausnahme ist ein Eintrag:

In der FritzBox (Stand FRITZ!OS 7 und 8): Heimnetz → Netzwerk → Reiter Netzwerkeinstellungen, nach unten scrollen bis DNS-Rebind-Schutz. Dort meintresor.duckdns.org in das Feld eintragen und Übernehmen. Danach den nslookup von oben wiederholen.

Schritt 2: Vier Dateien anlegen

Alles liegt in einem Ordner: die Compose-Datei, die Caddy-Konfiguration, ein kleiner Bauplan für Caddy und eine Datei mit den Geheimnissen. Zuerst der Ordner:

mkdir -p ~/vaultwarden/caddy
cd ~/vaultwarden

Vor den Dateien der Admin-Token. Vaultwarden hat eine Verwaltungsseite, und ihr Passwort willst du nicht im Klartext in einer Datei stehen haben. Vaultwarden bringt dafür einen Hash-Generator mit, den du im Container aufrufst; er fragt zweimal nach einem Passwort und gibt eine lange Zeichenkette aus, die mit $argon2id$ beginnt.

docker run --rm -it vaultwarden/server:latest /vaultwarden hash

Die Ausgabe ist eine Zeile der Form $argon2id$v=19$m=65540,t=3,p=4$…. Komplett kopieren; das gewählte Passwort merken, es ist später dein Admin-Passwort.

Dieser Hash kommt in die Datei .env, zusammen mit Domain und DuckDNS-Token. Die einfachen Anführungszeichen um den Hash sind Pflicht. Der Grund ist der häufigste Fehler im Vaultwarden-Forum: Docker Compose liest jedes Dollarzeichen als Variable, und ein Argon2-Hash hat fünf davon. Wer den Hash direkt in die Compose-Datei schreibt, muss jedes $ zu $$ verdoppeln, so steht es im Wiki. Im Forum-Thread „How to set ADMIN_TOKEN in docker-compose.yml“ landete Nutzer jahway603 nach mehreren Anläufen bei der .env-Datei, und undermemphis bestätigte, dass es bei ihm genauso läuft. Ich würde diesen Weg von Anfang an nehmen.

Datei anlegen mit nano .env, Inhalt einfügen, eigene Werte einsetzen, speichern mit Strg+O, Enter, schließen mit Strg+X:

DOMAIN=meintresor.duckdns.org
DUCKDNS_TOKEN=00112233-4455-6677-8899-aabbccddeeff
ADMIN_TOKEN='$argon2id$v=19$m=65540,t=3,p=4$HIER-DEIN-HASH'

Dann die Compose-Datei. Sie folgt dem Beispiel aus dem Vaultwarden-Wiki, nur dass Caddy hier selbst gebaut wird, weil das fertige Caddy-Image das DuckDNS-Modul nicht enthält. Die Variable DOMAIN muss laut Wiki mit https:// beginnen, sonst funktionieren Anhänge und Einladungen nicht richtig. SIGNUPS_ALLOWED bleibt vorerst auf true, damit du dein eigenes Konto anlegen kannst; das stellst du in den ersten Einstellungen wieder ab.

Datei anlegen mit nano compose.yaml, Inhalt einfügen, speichern, schließen:

services:
  vaultwarden:
    image: vaultwarden/server:latest
    container_name: vaultwarden
    restart: always
    environment:
      DOMAIN: "https://${DOMAIN}"
      SIGNUPS_ALLOWED: "true"
      ADMIN_TOKEN: ${ADMIN_TOKEN}
    volumes:
      - ./vw-data:/data

  caddy:
    build: ./caddy
    container_name: caddy
    restart: always
    ports:
      - 443:443
      - 443:443/udp
    volumes:
      - ./Caddyfile:/etc/caddy/Caddyfile:ro
      - ./caddy-config:/config
      - ./caddy-data:/data
    environment:
      DOMAIN: ${DOMAIN}
      DUCKDNS_TOKEN: ${DUCKDNS_TOKEN}

Zwei Dinge fallen auf. Vaultwarden hat keine ports-Zeile: Es ist nur für Caddy erreichbar, und so soll es bleiben. Und Caddy bekommt zwei Datenordner, weil laut Caddy-Doku in /data die Zertifikate liegen und dieser Ordner „nicht wie ein Cache behandelt“ werden darf. Löschst du ihn, holt Caddy neue Zertifikate, und Let's Encrypt hat dafür ein Wochenlimit.

Der Bauplan für Caddy ist vier Zeilen lang und stammt aus der Caddy-Doku auf Docker Hub: ein Bau-Container mit dem DuckDNS-Modul, dann wird nur die fertige Datei ins schlanke Image kopiert.

Datei anlegen mit nano caddy/Dockerfile, Inhalt einfügen, speichern, schließen:

FROM caddy:2-builder AS builder
RUN xcaddy build --with github.com/caddy-dns/duckdns
FROM caddy:2
COPY --from=builder /usr/bin/caddy /usr/bin/caddy

Zuletzt die Caddyfile, wörtlich aus dem Vaultwarden-Wiki bis auf das Ziel: Dort steht localhost:8001, weil das Beispiel ohne Docker läuft. Im Compose-Netz heißt das Ziel wie der Dienst.

Datei anlegen mit nano Caddyfile (großes C, ohne Endung), Inhalt einfügen, speichern, schließen:

{$DOMAIN}:443 {
    tls {
        dns duckdns {$DUCKDNS_TOKEN}
    }
    reverse_proxy vaultwarden:80
}

Ob Compose die vier Dateien versteht und die Geheimnisse richtig einsetzt, zeigt es dir vor dem Start:

docker compose config | grep -E "DOMAIN|ADMIN_TOKEN|DUCKDNS"

Vier Zeilen, mit deiner Domain, dem Token und dem Hash. Compose zeigt die Dollarzeichen im Hash dabei verdoppelt an; das ist seine Schreibweise und richtig so. Steht dort ADMIN_TOKEN: '' oder eine Warnung über eine unbekannte Variable, fehlen die Anführungszeichen in der .env.

Schritt 3: Starten und das Zertifikat kommen sehen

docker compose up -d --build

Das --build baut Caddy einmalig zusammen, das dauert beim ersten Mal ein bis drei Minuten, weil Go den Webserver kompiliert. Danach laufen beide Container im Hintergrund und kommen nach einem Neustart des Servers von selbst wieder. Ob Vaultwarden hochgekommen ist, sagt sein Log:

docker compose logs vaultwarden

Die letzte Zeile ist die, auf die du wartest:

[start][INFO] Rocket has launched from http://0.0.0.0:80

Davor steht beim ersten Start eine Zeile über rsa_key.pem: Vaultwarden hat sich gerade den Schlüssel erzeugt, mit dem es Anmeldungen unterschreibt. Der liegt in vw-data und gehört später ins Backup. Jetzt Caddy:

docker compose logs caddy | grep -i certificate

Innerhalb von ein bis zwei Minuten taucht eine Zeile mit certificate obtained successfully auf. Bleibt sie aus und du siehst stattdessen Fehler mit duckdns oder DNS problem, stimmt der Token nicht oder der DuckDNS-Eintrag ist noch keine Minute alt; Let's Encrypt fragt die Nameserver von außen, und die brauchen kurz. Zwei Minuten warten, Log noch einmal lesen.

Dann der Moment im Browser, auf irgendeinem Gerät im Heimnetz: https://meintresor.duckdns.org öffnen. Du siehst die Bitwarden-Anmeldeseite mit geschlossenem Schloss in der Adressleiste, ohne Warnung, ohne Ausnahme bestätigen. Ein echtes Zertifikat für einen Server, den niemand von draußen erreicht. Das ist der Trick der ganzen Anleitung, und er hat gerade funktioniert.

So schnell, dass ich es kurz nachprüfen würde: Ändere die Adresse auf http://meintresor.duckdns.org, ohne s. Der Browser meldet, dass die Verbindung abgelehnt wurde. Richtig so, Caddy hört nur auf 443, und Vaultwarden hat keinen Port nach außen. Wenn dort doch etwas antwortet, hast du einen zweiten Webserver auf dem Rechner, den du dir ansehen solltest.

Schritt 4: Das erste Konto

Das erste Konto legst du im Browser an. Es ist ein ganz normaler Nutzer; Vaultwarden kennt keinen Superuser im Tresor, die Verwaltung läuft getrennt über die Admin-Seite. Der Klick-Weg gilt für den Bitwarden-Tresor, den Vaultwarden 1.37 mitbringt.

https://meintresor.duckdns.org öffnen. Unter dem Anmeldeformular auf Create account. E-Mail-Adresse eintippen, Continue. Es folgt die Seite mit Name, Master password und Re-type master password; das Feld Master password hint leer lassen. Create account. Danach mit E-Mail und Master-Passwort anmelden.

Du siehst einen leeren Tresor mit dem Menü Vaults, Send, Tools, Settings. Das ist die Erfolgskontrolle für Schritt 4, und der schwierigste Teil liegt hinter dir. Der Hinweis zum Master-Passwort ist bewusst leer: Vaultwarden zeigt Hinweise ohne Mail-Server auf der Anmeldeseite an, für jeden, der sie aufruft. Das Wiki hat dafür die Option SHOW_PASSWORD_HINT, die inzwischen standardmäßig aus ist. Ein Hinweis, den jeder lesen kann, ist kein Hinweis, sondern ein halbes Passwort.

Schritt 5: Die Apps an den eigenen Server hängen

Die Bitwarden-Apps verbinden sich standardmäßig mit der Bitwarden-Cloud. Auf deinen Server zeigen sie erst, wenn du es ihnen vor der Anmeldung sagst. Der Weg ist laut Bitwarden-Doku in allen Apps derselbe, nur das Menü heißt unterschiedlich.

Browser-Erweiterung und Handy-App: Auf dem Anmeldebildschirm das Auswahlfeld Logging in on aufklappen, Self-hosted wählen. In das Feld Server URL die Adresse https://meintresor.duckdns.org eintragen, Save. In der Desktop-App heißt das Auswahlfeld Accessing. Danach ganz normal mit E-Mail und Master-Passwort anmelden.

Als Probe legst du im Browser-Tresor einen ersten Eintrag an, irgendetwas, und ziehst in der Handy-App die Liste nach unten. Taucht der Eintrag auf, synchronisiert alles über deinen Server. Das Handy fragt dabei nicht nach einem Zertifikat, weil es ein echtes ist. Genau das ersparen wir uns mit der DNS-Challenge: In der Bitwarden-Doku steht der Schritt „Laden Sie ggf. ein Zertifikat hoch“, und den brauchst du nicht.

Außerhalb deines Netzes erreichen die Apps den Server nicht, und das bleibt in dieser Anleitung so. Wer den Tresor unterwegs braucht, holt sich mit einem VPN sein Heimnetz aufs Handy; die Bitwarden-Apps behalten den Tresor ohnehin verschlüsselt auf dem Gerät und kommen eine Weile ohne Server aus. Port 443 im Router freizugeben wäre der andere Weg, und den würde ich für einen Passwort-Server nicht gehen, bevor der Rest sitzt.

Die ersten Einstellungen

Der Tresor läuft, aber er steht in der Werkseinstellung, und die ist auf „jeder darf rein“ gestellt. Vier Handgriffe ändern das, und nur der erste ist eilig.

Registrierung schließen

Solange SIGNUPS_ALLOWED auf true steht, kann jeder, der die Adresse erreicht, ein Konto anlegen; das Wiki selbst schreibt hinter die Zeile, sie nach dem eigenen Konto abzuschalten. Im Heimnetz ist das der Besuch mit dem WLAN-Passwort. Du willst selbst entscheiden, wer einen Tresor bekommt.

In compose.yaml (nano compose.yaml) die Zeile ändern auf SIGNUPS_ALLOWED: "false", speichern, dann den Container mit der neuen Einstellung neu erzeugen:

docker compose up -d

Compose baut nur den Vaultwarden-Container neu, Caddy läuft weiter.

Kontrolle: Anmeldeseite neu laden, der Link Create account ist verschwunden. Laut Wiki dürfen bestehende Nutzer, die eine Organisation besitzen, weiterhin per Einladung Leute holen; für die Familie reicht das. Ein zweites Konto für den Partner legst du am einfachsten an, indem du die Registrierung für zehn Minuten wieder öffnest.

Die Admin-Seite: ansehen, nicht speichern

Unter https://meintresor.duckdns.org/admin meldest du dich mit dem Passwort an, das du in Schritt 2 gehasht hast. Dort siehst du alle Nutzer, kannst Konten löschen und unter Diagnostics prüfen, ob Vaultwarden mit deiner Domain und der Zeit einverstanden ist. Das Wiki empfiehlt HTTPS vor der Admin-Seite ausdrücklich, und das hast du.

Eine Sache würde ich dort nicht tun: auf Save klicken. Sobald du auf der Admin-Seite einmal speicherst, legt Vaultwarden laut Wiki eine config.json im Datenordner an, und die hat ab dann Vorrang vor allem, was in der Compose-Datei steht. Du änderst also SIGNUPS_ALLOWED in der Datei, und nichts passiert, weil die JSON-Datei gewinnt. Wer das nicht weiß, sucht lange. Der Standard ist gut, weil er alles an einem Ort hält; behalte ihn.

Zweiter Faktor für dein Konto

Das Master-Passwort ist der einzige Schlüssel zum Tresor. Ein zweiter Faktor kostet dich beim Anmelden auf einem neuen Gerät eine Zahl aus der Authenticator-App und macht aus einem abgefischten Passwort einen Fehlschlag. Der Standard hat keinen, weil Vaultwarden nicht wissen kann, welche App du benutzt.

Im Browser-Tresor oben rechts Settings → Security → Reiter Two-step login. Bei Authenticator app auf Manage, Master-Passwort bestätigen, den QR-Code mit deiner Authenticator-App scannen, den sechsstelligen Code eintippen, Turn on.

Kontrolle: Direkt darunter bietet der Tresor Recovery code an. Den anzeigen lassen und auf Papier schreiben. Geht das Handy mit der Authenticator-App verloren, ist dieser Code der einzige Weg zurück in den Tresor. Ohne ihn hilft dir auch die Admin-Seite nur, indem sie den zweiten Faktor für dein Konto ganz löscht.

Das Backup, jetzt, wo es noch klein ist

Ja, der Backup-Absatz. Bei einem Passwort-Manager ist er der Absatz, wegen dem du diese Anleitung in einem Jahr noch mögen wirst oder nicht. Der Standard hat gar kein Backup, und die naheliegende Idee, einfach db.sqlite3 zu kopieren, warnt das Wiki ab: Bei laufendem Vaultwarden kann die Kopie inkonsistent sein. Seit Version 1.32.1 bringt Vaultwarden einen eigenen Befehl mit, der es richtig macht.

docker exec vaultwarden /vaultwarden backup
ls -l vw-data/db_*.sqlite3

Die zweite Zeile zeigt eine neue Datei nach dem Muster db_20260907_213000.sqlite3 im Datenordner. Das ist die Kopie deiner Datenbank, aber noch auf derselben Platte wie das Original, also noch kein Backup. Dazu gehören laut Wiki außerdem der Ordner attachments und die Dateien rsa_key*; ohne den Schlüssel müssen sich nach dem Zurückspielen alle Geräte neu anmelden, mehr nicht. Ich würde den ganzen vw-data-Ordner nach dem Befehl auf eine zweite Platte oder einen anderen Rechner kopieren und den Befehl per Cron jede Nacht laufen lassen. Wie du daraus einen Plan machst, der Feuer und Fehlbedienung übersteht, ist ein eigener Beitrag.

Beim Zurückspielen, sagt das Wiki, muss die Datei db.sqlite3-wal vorher gelöscht sein, sonst versucht SQLite, eine fremde Datenbank mit einem alten Journal zu reparieren. In der Diskussion 6104 auf GitHub hat threehappypenguins die Schritte durchgespielt: Container stoppen, Backup-Datei in db.sqlite3 umbenennen, WAL-Datei weg, starten. Einmal ausprobieren, solange der Tresor drei Einträge hat, ist billiger als beim ersten Ernstfall.

Updates: der Server muss den Apps folgen

Bei den meisten Diensten sind Updates eine Frage der Bequemlichkeit. Bei Vaultwarden nicht: Die Bitwarden-Apps entwickeln sich weiter, und die Release-Notes zu 1.37.2 vom August sagen es klar, diese Version sei nötig für Apps ab 2026.8.0. Hängt dein Server zurück, meldet sich irgendwann die Handy-App nicht mehr an, und du suchst den Fehler am falschen Ende. Das Team hinter Vaultwarden hält Schritt; du musst es nur mitnehmen.

Vor jedem Update das Backup von oben, dann:

docker compose pull vaultwarden
docker compose build --pull caddy
docker compose up -d

Die erste Zeile holt das neue Vaultwarden-Image, die zweite baut Caddy mit dem aktuellen Grundimage neu, die dritte tauscht nur die Container aus, deren Image sich geändert hat. Die Daten liegen in deinen Ordnern und bleiben. Kontrolle wie in Schritt 3: docker compose logs vaultwarden zeigt in der ersten Zeile die Versionsnummer, in der letzten das gestartete Rocket.

Wo es klemmt

Drei Stellen tauchen in Forum, Issues und Diskussionen immer wieder auf; zwei davon hast du oben schon umschifft.

  • „Invalid admin token“ beim Anmelden an der Admin-Seite: fast immer die Dollarzeichen im Hash, die Compose verschluckt hat. Allein im Vaultwarden-Forum gibt es dazu drei Threads, auf GitHub weitere. Prüfen mit docker compose config wie in Schritt 2; steht der Hash dort verstümmelt, fehlen die einfachen Anführungszeichen in der .env.
  • Der Name löst im Heimnetz nicht auf, obwohl DuckDNS ihn kennt: DNS-Rebind-Schutz im Router, siehe Schritt 1. Wer Pi-hole oder Unbound als DNS betreibt, braucht die Ausnahme laut Wiki dort statt im Router (bei Unbound private-domain).
  • Der Tresor lädt ewig oder die App meldet Verschlüsselungsfehler: Die Adresse wurde über http:// oder eine nackte IP aufgerufen. Die Vaultwarden-FAQ ist da knapp: Die Clients brauchen eine sichere Verbindung. In der Diskussion 2096 hat Maintainer BlackDex genau darum auf die Wiki-Seite verwiesen, die dieser Anleitung zugrunde liegt.
  • Eine Einstellung in der Compose-Datei greift nicht: Nachsehen, ob in vw-data eine config.json liegt. Wenn ja, hat jemand auf der Admin-Seite gespeichert, und die Datei gewinnt. Entweder dort ändern oder die Datei löschen und Vaultwarden neu starten.

Lohnt sich das gegenüber der Bitwarden-Cloud?

Bitwarden verschenkt sein Cloud-Konto für Einzelnutzer, und es ist gut. Vaultwarden gewinnt trotzdem in zwei Fällen: wenn du die Familienfunktionen willst, ohne dafür zu zahlen, und wenn dir der Gedanke wichtig ist, dass die verschlüsselte Datei mit allen deinen Zugängen auf einer Platte liegt, die du anfassen kannst. Beides trifft auf mich zu, also würde ich es so betreiben wie oben, mit einer Bedingung.

Die Bedingung ist das Backup. Bitwarden hat ein Rechenzentrum, du hast eine Platte. Wer den Cron-Job aus dem Backup-Abschnitt nicht innerhalb einer Woche einrichtet, sollte den Tresor lieber in der Cloud lassen; ein Passwort-Manager ohne Kopie ist eine Wette auf eine Festplatte. Mit Kopie ist Vaultwarden der Dienst, der auf deinem Server am wenigsten Strom braucht und am meisten wert ist.

Bei dir läuft der Tresor jetzt im Heimnetz. Wie holst du ihn unterwegs aufs Handy, per VPN, Tailscale, oder gar nicht, weil die App den Tresor ohnehin lokal hält? Und wohin wandert dein nächtliches Backup? Schreib es in die Kommentare, das nächste Thema aus dieser Reihe suche ich mir daraus.

Falls Caddy für dich neu war und du wissen willst, was der Türsteher da eigentlich tut, erklärt Was ist ein Reverse Proxy? das Prinzip in Ruhe; und wer den Server selbst noch nicht abgesichert hat, fängt mit SSH absichern auf Debian & Ubuntu an, bevor der Tresor dort einzieht.

Quellen