Infrastructure/docker/vaultwarden/README.md

3.4 KiB

Vaultwarden

Password manager for both of us. Runs on the OptiPlex homeserver (192.168.30.20) in ~/vaultwarden, reachable only as https://vault.home.staffenberger.at — at home or through the WireGuard VPN. Clients are the official Bitwarden apps and browser extensions, set to the self-hosted server URL.

Network

The container publishes no ports. NPM reaches it on a shared Docker network called proxy, so the only way in is HTTPS through NPM. Bitwarden clients refuse plain HTTP anyway, and this stops anyone on the LAN from going around TLS.

One-time setup on the OptiPlex, before the first docker compose up -d:

docker network create proxy

Then recreate NPM so it joins the network (cd ~/npm && docker compose up -d).

Setup

  1. Pi-hole Local DNS record: vault.home.staffenberger.at → 192.168.30.20, on whichever Pi-hole the clients use right now.
  2. NPM proxy host: vault.home.staffenberger.at, scheme http, forward to vaultwarden port 80, Websockets Support on (live sync between devices), wildcard certificate, Force SSL, HTTP/2. The forward host must be the container name, not 192.168.30.20: the host's port 80 is NPM itself, which caused a redirect loop (ERR_TOO_MANY_REDIRECTS).
  3. Open the URL and create both accounts. Each person picks their own master password; it can't be reset, only changed while logged in.
  4. Set SIGNUPS_ALLOWED: "false" and run docker compose up -d. Check that "Create account" fails.
  5. Turn on two-step login (authenticator app) for both accounts, and keep the recovery codes outside the vault.
  6. Create an Organization (e.g. "Home") with collections for shared logins, invite the partner's account, then confirm them as owner. No SMTP is configured, so no invite mail is sent: the partner accepts in the web vault, then you confirm. Untested here, check while setting it up.
  7. Import the old vaults (Tools → Import data; Bitwarden reads Enpass JSON). Delete the plain-text export files afterwards and empty the trash.

Backups

Don't move real passwords in before this works. Devices that are logged in keep an encrypted offline copy, but that doesn't replace a backup.

  • Contents of ./data to keep: db.sqlite3, attachments/, sends/, rsa_key* and config.json (if present).
  • Copy the database with sqlite3 db.sqlite3 ".backup ...", not cp, since the file may be mid-write.
  • Encrypted copy to the NAS, part of the OptiPlex off-box backup (see ../../docs/todo.md).
  • Occasionally: an encrypted export from the web vault, kept offline.
  • Test a restore once, onto a throwaway container.

Using it away from home

The apps can fill passwords offline, but saving or editing needs the server. Set the WireGuard app on both phones to connect automatically when not on the home Wi-Fi, otherwise passwords for new sign-ups get lost. The VPN is split-tunnel (Servers + IoT only), so normal browsing doesn't go through it.

Notes

  • /admin is disabled (no ADMIN_TOKEN). If it is ever needed, set a hashed token generated with docker exec -it vaultwarden /vaultwarden hash, never a plain-text one.
  • The image is pinned; check the release notes before bumping.
  • Write down for the partner how to get at their passwords if the server or I am unavailable: their master password, where the backups are, and how to restore them.