Every browser password manager has the same quiet problem: your most sensitive secrets live on someone else's server, protected by someone else's breach history. Chrome syncs them to Google, and even dedicated services have had their incidents. Vaultwarden flips the model — a complete Bitwarden-compatible password server you run yourself, light enough for a Raspberry Pi.
This guide deploys Vaultwarden with Docker, locks it down properly, and connects your browsers and phones.
What Vaultwarden actually is
Vaultwarden is a Rust reimplementation of the Bitwarden server API. Your official Bitwarden apps — browser extensions, Android, iOS, desktop — connect to it just by changing the server URL. You get the polished Bitwarden client experience with the database on your own disk.
It is also tiny: the official Bitwarden server wants gigabytes of RAM and a fleet of containers. Vaultwarden runs happily in under 100 MB.
Before you start
- A server with Docker and Docker Compose (a Pi, a VPS, anything)
- A domain or subdomain like
vault.example.compointing at it - HTTPS is not optional — the Bitwarden apps use browser crypto APIs that refuse to work over plain HTTP. If you don't have TLS set up yet, our Let's Encrypt guide takes ten minutes
Deploy with Docker Compose
services:
vaultwarden:
image: vaultwarden/server:latest
container_name: vaultwarden
restart: unless-stopped
environment:
DOMAIN: "https://vault.example.com"
SIGNUPS_ALLOWED: "false"
ADMIN_TOKEN: "replace-with-a-long-random-string"
volumes:
- ./vw-data:/data
ports:
- "127.0.0.1:8080:80"
Three decisions baked in here, deliberately:
-
SIGNUPS_ALLOWED: "false"— without this, anyone who finds your server can create an account and store secrets on your disk. Create your own account first, then flip it to false (or leave it false and use admin-panel invites). -
ADMIN_TOKEN— protects the/adminpanel. Generate it withopenssl rand -base64 48. Better still, use Argon2: rundocker run --rm -it vaultwarden/server /vaultwarden hashand store the PHC string. - Port bound to
127.0.0.1— Vaultwarden should never be exposed directly. Put it behind your reverse proxy (Nginx, Caddy, Traefik — see our reverse proxy guide) which handles TLS.
Bring it up:
docker compose up -d
Point your apps at it
In any Bitwarden client — browser extension, mobile app, desktop — before logging in, open the region/self-hosted selector and set:
-
Server URL:
https://vault.example.com
Leave the advanced fields empty; the single URL is enough. Create your account (with signups temporarily enabled), log in, and it behaves exactly like Bitwarden cloud — autofill, TOTP codes, secure notes, passkeys, the lot.
The settings people regret skipping
Disable open signups after creating accounts. Either set SIGNUPS_ALLOWED=false and invite family from the admin panel, or use INVITATIONS_ALLOWED=false plus SIGNUPS_DOMAINS_WHITELIST for your own domain.
Enable 2FA on your Vaultwarden account itself. The vault that holds all your 2FA seeds should not be protected only by a password. Keep the recovery codes on paper — losing both your master password and 2FA means the vault is gone forever. There is no "forgot password" on your own server.
Rate limiting. Vaultwarden has built-in limits, but add your reverse proxy's rate limiting on /identity/accounts/prelogin if the server is internet-facing.
Backups: the whole point of self-hosting
Your entire vault lives in ./vw-data — mainly db.sqlite3 plus attachments and the rsa_key* files. A safe backup needs SQLite's own tooling, not a naive file copy of a live database:
docker exec vaultwarden sqlite3 /data/db.sqlite3 \
".backup '/data/db-backup.sqlite3'"
Then copy db-backup.sqlite3, rsa_key*, attachments/, and sends/ somewhere off the server. The 3-2-1 backup strategy guide has a restic setup that fits this perfectly. Test a restore once: spin up a second container with the backup mounted and log in. Five minutes now beats a catastrophe later.
Keeping it updated
docker compose pull && docker compose up -d
Vaultwarden tracks the Bitwarden client API, so staying current matters — clients auto-update and occasionally expect newer server behavior. Read the release notes for breaking changes; they are rare but real.
The honest trade-off
You are now the uptime department and the backup department for your passwords. If the server dies and your backup is stale, that's on you. But your secrets are no longer in a breach-target database alongside millions of other people's — they're encrypted blobs on hardware you control, unlockable only with a master password that never leaves your devices.
Pair it with Aegis for 2FA on a deGoogled phone and your authentication life is fully yours.
Top comments (0)