Table of contents
- CT 103 — Vaultwarden (Passwortmanager) — Rebuild-Runbook
- 1. Container erstellen
- 2. TUN-Device für Tailscale (siehe 01-pve-host.md, Abschnitt 8)
- 3. Docker
- 4. Tailscale-Mitgliedschaft + HTTPS-Zertifikat
- 5. Vaultwarden via Docker Compose
- 6. HTTPS-Exposition via tailscale serve (kein Caddy, kein manuelles Zertifikat)
- 7. Konto-Anlage (manueller Web-Schritt, nicht per CLI)
- 8. Update-Vorfall: Client zeigte nur graue Platzhalter nach einem fälligen Server-Update
- Bekannte Stolpersteine (bereits behoben, hier nur als Hinweis)
- Verifikation
CT 103 — Vaultwarden (Passwortmanager) — Rebuild-Runbook
Sensibelster Dienst im gesamten Setup — bewusst nur über Tailscale erreichbar, nie öffentlich.
1. Container erstellen
pct create 103 local:vztmpl/<DEBIAN_TEMPLATE> \
--hostname vaultwarden \
--unprivileged 1 \
--cores 1 \
--memory 512 \
--swap 512 \
--rootfs local-lvm:4 \
--net0 name=eth0,bridge=vmbr0,ip=<LAN_IP_VAULTWARDEN>/24,gw=<LAN_IP_ROUTER> \
--features nesting=1 \
--timezone Europe/Berlin \
--onboot 1 \
--nameserver <LAN_IP_ADGUARD>
pct start 103
2. TUN-Device für Tailscale (siehe 01-pve-host.md, Abschnitt 8)
pct stop 103
cat >> /etc/pve/lxc/103.conf <<'EOF'
lxc.cgroup2.devices.allow: c 10:200 rwm
lxc.mount.entry: /dev/net/tun dev/net/tun none bind,create=file 0 0
EOF
pct start 103
3. Docker
pct exec 103 -- apt-get update
pct exec 103 -- apt-get install -y curl ca-certificates
pct exec 103 -- bash -c "curl -fsSL https://get.docker.com | sh"
4. Tailscale-Mitgliedschaft + HTTPS-Zertifikat
pct exec 103 -- bash -c "curl -fsSL https://tailscale.com/install.sh | sh"
pct exec 103 -- tailscale up --authkey=<AUTH_KEY> --hostname=vaultwarden
Kein --accept-routes nötig — anders als CT 102 sitzt dieser Container nicht zusätzlich im <LAN_SUBNET>-LAN in einer Weise, die einen Routing-Konflikt erzeugen würde (Netz-Interface ist zwar auf dem LAN, aber der Dienst wird ausschließlich über die Tailscale-IP angesprochen).
Voraussetzung in der Tailscale-Admin-Konsole: Settings → DNS → „HTTPS Certificates" muss aktiviert sein (einmalig für den ganzen Tailnet, siehe 01-pve-host.md).
5. Vaultwarden via Docker Compose
mkdir -p /opt/vaultwarden/data
ADMIN_TOKEN=$(openssl rand -base64 48 | tr -d '\n')
cat > /opt/vaultwarden/docker-compose.yml <<EOF
services:
vaultwarden:
image: vaultwarden/server:latest
container_name: vaultwarden
restart: unless-stopped
logging:
driver: json-file
options:
max-size: "10m"
max-file: "3"
environment:
DOMAIN: "https://vaultwarden.<TAILNET>"
ADMIN_TOKEN: "$ADMIN_TOKEN"
SIGNUPS_ALLOWED: "true"
WEBSOCKET_ENABLED: "true"
volumes:
- ./data:/data
ports:
- "127.0.0.1:8080:80"
EOF
cd /opt/vaultwarden && docker compose up -d
SIGNUPS_ALLOWED bewusst zuerst true, um das/die Konto(s) anzulegen. Nach der Konto-Anlage zwingend zurückstellen:
sed -i 's/SIGNUPS_ALLOWED: "true"/SIGNUPS_ALLOWED: "false"/' /opt/vaultwarden/docker-compose.yml
cd /opt/vaultwarden && docker compose up -d
6. HTTPS-Exposition via tailscale serve (kein Caddy, kein manuelles Zertifikat)
tailscale serve --bg http://127.0.0.1:8080
Erreichbar unter https://vaultwarden.<TAILNET>, automatisch gültiges Let's-Encrypt-Zertifikat, automatische Erneuerung, nicht öffentlich (nur Tailnet-Mitglieder).
⚠️ NICHT TUN: tailscale serve --bg https / http://... (alte Syntax). Neuere Tailscale-CLI-Versionen erwarten nur noch tailscale serve --bg http://127.0.0.1:8080 (HTTPS wird automatisch angenommen).
⚠️ NICHT TUN: Vaultwarden zusätzlich über Caddy auf dem VPS öffentlich exponieren (wie bei Guacamole). Bewusste Entscheidung: der Passwort-Tresor ist der sensibelste Dienst im gesamten Setup, öffentliche Erreichbarkeit erhöht die Angriffsfläche unnötig — der Internetcafé-Fall wird stattdessen über Guacamole selbst abgedeckt (SFTP/RDP-Zugriff auf andere Dienste, nicht direkt auf den Tresor).
7. Konto-Anlage (manueller Web-Schritt, nicht per CLI)
Über https://vaultwarden.<TAILNET> (nur von einem Tailnet-Mitglied aus erreichbar) im Browser ein Konto mit selbst gewähltem Master-Passwort anlegen. Das Master-Passwort wird bewusst nie programmatisch gesetzt oder irgendwo notiert — es ist der einzige Schlüssel zum gesamten Tresor.
8. Update-Vorfall: Client zeigte nur graue Platzhalter nach einem fälligen Server-Update
Vaultwarden aktualisiert sich nicht selbst — die Anwendung ist das Image. Weder der Tresor noch das Admin-Panel können das auslösen; ein Update heißt Image holen und Container neu erzeugen.
# 1. Konsistente Sicherung OHNE Dienst-Stopp (kein blosses cp der laufenden DB!)
python3 - <<'EOF'
import sqlite3, os, shutil
ziel = "/opt/vaultwarden/pre-update-$(date +%Y%m%d-%H%M)"
os.makedirs(ziel, exist_ok=True)
src = sqlite3.connect("/opt/vaultwarden/data/db.sqlite3")
dst = sqlite3.connect(os.path.join(ziel, "db.sqlite3"))
with dst: src.backup(dst)
EOF
# rsa_key.pem und docker-compose.yml mitsichern, Kopie per 'pct pull' vom Container holen
# 2. Integritaet der Sicherung pruefen, BEVOR etwas angefasst wird
# pragma integrity_check + Anzahl Eintraege merken
# 3. Update
cd /opt/vaultwarden && docker compose pull && docker compose up -d
# 4. Gegenpruefen: Version, /api/config, integrity_check, gleiche Anzahl Eintraege
Ausfallzeit im Praxisfall: ca. 7 Sekunden.
⚠️ NICHT TUN: image: vaultwarden/server:latest für aktuell halten. latest wird nur beim docker pull neu aufgelöst. Der Container lief so drei Monate auf einem Image, das Monate zuvor „latest" war — ohne jeden Hinweis. Genau dafür ist ein Image-Update-Notifier vorgesehen (siehe 08-monitoring.md).
⚠️ NICHT TUN: die laufende db.sqlite3 einfach kopieren. SQLite läuft im WAL-Modus; ein cp erwischt einen inkonsistenten Zwischenstand. Die .backup-Schnittstelle liefert einen sauberen Schnappschuss, ohne den Dienst zu stoppen.
Vorfall: Chrome-Erweiterung zeigte nur graue Platzhalter
Symptom: Tresor-Liste lud nie, die Erweiterung zeigte dauerhaft Skeleton-Platzhalter. In der Browser-Konsole:
Error: invalid type: JsValue(Object({...})), expected a string (bitwarden_wasm_internal_bg.js)
Diagnose-Kette, jeder Schritt am Protokoll belegt statt vermutet:
- Server gesund — Container „healthy", Endpunkt 200 in 20 ms, keine Fehler im Log
- Client verbunden — Anmeldung 200 OK, sogar erfolgreiches
POST /api/ciphers - Aber: in zwei Stunden kein einziger
GET /api/sync— das ist der Aufruf, der die Tresor-Inhalte holt. Ohne ihn bleibt die Liste leer, ganz ohne Fehlermeldung - Ursache: der Server meldete einen älteren API-Stand, die Browser-Erweiterung erwartete bereits einen neueren — die Release-Notes der neuen Server-Version waren dazu explizit: eine Mindest-Server-Version wird für neuere Client-Versionen vorausgesetzt
- Nach dem Update trotzdem derselbe Fehler — weil der Client per
GET /api/accounts/revision-dateprüft, ob sich etwas geändert hat, ein „nein" bekam und weiter aus seinem lokalen Zwischenspeicher im alten Format arbeitete - Gelöst durch „Jetzt synchronisieren" in der Erweiterung →
GET /api/sync => 200 OK
⚠️ Merksatz: nach einem Vaultwarden-Update reicht ein Neustart des Browsers nicht. Der Client synchronisiert nur, wenn sich das Revisionsdatum geändert hat — nach einem reinen Versionssprung tut es das nicht. Ein Abgleich muss manuell erzwungen werden (Einstellungen → Tresor synchronisieren), sonst bleibt er auf altem Datenformat hängen.
Vor dem Abmelden immer prüfen, ob 2FA aktiv ist (select atype, enabled from twofactor) — bei einem Passwort-Tresor ist ein Selbst-Aussperren die teuerste Fehlerart. Hier: keine 2FA, nur Master-Passwort.
Mitgeliefert wurden mit diesem Update drei Sicherheitskorrekturen: SSRF über den Icon-Endpunkt, Cross-Organization Cipher Access, Policy-Bypass beim Directory-Import.
Bekannte Stolpersteine (bereits behoben, hier nur als Hinweis)
- Beim Passwort-Import versehentlich Duplikate erzeugt (zweimal importiert) → behoben durch: alle Einträge auswählen → löschen → Papierkorb leeren → sauber neu importieren.
Verifikation
curl -s -o /dev/null -w "%{http_code}\n" http://127.0.0.1:8080/ # lokal, im Container
curl -s -o /dev/null -w "%{http_code}\n" https://vaultwarden.<TAILNET>/ # von einem Tailnet-Mitglied
tailscale serve status
Rebuild-Runbooks
Aufbau
- Übersicht
- PVE-Host
- AdGuard · CT100
- NAS · CT101
- Management-Desktop · CT102
- Vaultwarden · CT103
- VPS · STRATO
- Backup & Restore
- Monitoring · CT104
- Gast-Zugang
Referenz