Vaultwarden is a lightweight, Bitwarden-compatible server — you get all the official Bitwarden apps and browser extensions, pointed at your own infrastructure instead of Bitwarden's cloud. Here's how to run it properly, and how to migrate an existing instance without losing anything.
If you're already running a pile of Docker containers on a general-purpose NAS or server, it's tempting to just add Vaultwarden as one more container there. The problem: your password vault ends up sharing fate with whatever else that host is doing — unrelated container churn, experiments, reboots — and may not be covered by whatever backup job protects your "real" infrastructure. Give it its own small VM or container, on its own backup schedule, isolated from everything else.
services:
vaultwarden:
image: vaultwarden/server:latest
restart: unless-stopped
ports:
- "80:80"
volumes:
- ./data:/data
That's genuinely most of it — Vaultwarden is a single lightweight binary with no external database dependency by default (SQLite).
If you're moving an existing Vaultwarden instance to new infrastructure, four things actually need to move:
db.sqlite3 (+ -wal/-shm) — the vault database itself. Stop the
source container first so SQLite's write-ahead log gets checkpointed cleanly before copying.rsa_key.pem — the cryptographic identity. Losing this invalidates every existing client
session and JWT.config.json — Vaultwarden's persisted runtime config, which overrides environment
variables. Copy it verbatim rather than reconstructing settings by hand — it holds things like
real SMTP credentials for invite/2FA emails that are easy to get subtly wrong from scratch.attachments/ and sends/ — real user data. (Skip icon_cache/ and
tmp/ — pure cache, safe to leave behind.)rsync binary is setuid-root, and that specifically breaks
over SSH. Running rsync from a remote host straight over SSH against a NAS like this
can fail immediately with Permission denied, please try again. and a closed connection — the
vendor's OS is (correctly) blocking a setuid-root binary from being invoked non-interactively over SSH.
Work around it with a tar stream over SSH instead:
ssh <nas> "sudo tar -C /path/to/vaultwarden -cf - --exclude=icon_cache --exclude=tmp ." \
| tar -C <local-staging> -xf -
If your domain is already served through a reverse proxy that terminates TLS and forwards to a backend address, cutover is usually just editing that one rule's backend from the old address to the new one — no DNS change, no new certificate needed. This is the reusable pattern for migrating any already reverse-proxied service: check whether the domain already routes through a reverse proxy before assuming a migration needs new TLS/DNS work.
Before flipping it, confirm the new instance is actually healthy — check its logs for a clean startup
message and hit its health-check endpoint (Vaultwarden exposes GET /alive) — then do a real
end-to-end login test against the new backend before considering the migration done.
Leave the old instance stopped (not deleted) and its data directory untouched for a while after cutover — a cheap, cold rollback path in case something surfaces later that the migration missed.