Migrating from official Bitwarden self-hosted to Vaultwarden using Docker Compose requires exporting your vault data from the Bitwarden web interface, standing up a fresh Vaultwarden container, and importing the exported JSON file — the entire process takes under an hour on a standard Linux VPS. Vaultwarden (formerly bitwarden_rs) is a community-maintained, Rust-based implementation of the Bitwarden server API that runs on far lighter hardware than the official stack, which demands at minimum 2 GB RAM and a full SQL Server instance.
Prerequisites / What You'll Need
- A running official Bitwarden self-hosted instance (version 2024.x or later)
- A Linux host for Vaultwarden — Ubuntu 22.04 LTS or Debian 12 recommended
- Docker Engine 25.0+ and Docker Compose v2.24+ installed on the new host
- At least 256 MB RAM available (Vaultwarden idles around 15–20 MB)
- A domain name with DNS pointing to the new host (Vaultwarden requires HTTPS for WebAuthn)
- An SSL certificate — Let's Encrypt via Certbot or a Cloudflare-proxied setup works fine
- Admin access (sudo) on both the old and new server
- Your Bitwarden master password and TOTP code if 2FA is enabled
Step 1: Export Your Vault from Bitwarden Self-Hosted
Log into your existing Bitwarden web vault at https://your-bitwarden-domain.com. Navigate to Tools → Export Vault. Choose Encrypted JSON (Account Restricted) — this format is AES-256 encrypted with your account encryption key, so it's safe to transfer over the network without additional wrapping. Do not choose the unencrypted JSON unless you intend to inspect the file and then delete it immediately.
Click Confirm Format, enter your master password, and download the .json file. The filename will be something like bitwarden_export_20260917123456.json.
If you manage an Organization vault: repeat this step under Admin Console → Tools → Export Organization Vault. Organization exports and personal exports are separate files and must be imported separately.
Gotcha: If you have attachments (file attachments on vault items), they are not included in the JSON export. You'll need to download attachments manually and re-upload them after import. Vaultwarden supports attachments at $0 additional cost; the official Bitwarden hosted plan charges for premium features.
Step 2: Prepare the Vaultwarden Docker Compose File
On your new server, create a working directory:
mkdir -p /opt/vaultwarden/data
cd /opt/vaultwarden
Create a docker-compose.yml:
version: "3.8"
services:
vaultwarden:
image: vaultwarden/server:latest
container_name: vaultwarden
restart: unless-stopped
environment:
DOMAIN: "https://vault.yourdomain.com"
ADMIN_TOKEN: "your-strong-random-admin-token-here"
SIGNUPS_ALLOWED: "true"
LOG_LEVEL: "warn"
WEBSOCKET_ENABLED: "true"
volumes:
- /opt/vaultwarden/data:/data
ports:
- "127.0.0.1:8080:80"
- "127.0.0.1:3012:3012"
caddy:
image: caddy:2-alpine
container_name: caddy
restart: unless-stopped
ports:
- "80:80"
- "443:443"
volumes:
- ./Caddyfile:/etc/caddy/Caddyfile
- caddy_data:/data
- caddy_config:/config
volumes:
caddy_data:
caddy_config:
Create a Caddyfile in the same directory:
vault.yourdomain.com {
encode gzip
reverse_proxy /notifications/hub vaultwarden:3012
reverse_proxy vaultwarden:80
}
Gotcha: ADMIN_TOKEN must be a bcrypt hash in Vaultwarden 1.30+. Generate one with:
docker run --rm -it vaultwarden/server /vaultwarden hash --preset owasp
Paste the $argon2id$... output as the ADMIN_TOKEN value (wrap in single quotes to avoid shell escaping issues).
Step 3: Start Vaultwarden and Create Your Account
docker compose up -d
docker compose logs -f vaultwarden
Expected output includes lines like:
INFO vaultwarden::config] Loading config from '/data/config.json'
INFO vaultwarden] Rocket has launched from http://0.0.0.0:80
Navigate to https://vault.yourdomain.com and create a new account using the same email address you used on your old Bitwarden instance. Use the same master password if you want credential continuity, though technically any strong password works at this stage.
Vaultwarden uses AES-256-CBC for vault item encryption with keys derived via PBKDF2-SHA256 (default 600,000 iterations) or Argon2id if you enable it in account settings — matching the official Bitwarden client protocol exactly.
Gotcha: If you see a 502 Bad Gateway, confirm the container name in the Caddyfile (vaultwarden) matches the container_name in docker-compose.yml and that both services are on the same Docker network (Docker Compose creates this automatically).
Step 4: Import Your Vault Data
Log into https://vault.yourdomain.com with your new account. Go to Tools → Import Data. From the format dropdown, select Bitwarden (json). Click Choose File, select your exported .json file, enter your master password when prompted (for encrypted exports), and click Import Data.
The import screen will show a progress bar. For a vault with 500 items, expect under 10 seconds.
For Organization vaults: first create an Organization in Vaultwarden (Admin Console → New Organization), then import under Admin Console → Tools → Import Data, selecting Bitwarden (json) again.
Gotcha: If you exported from Bitwarden as an unencrypted JSON by mistake, the import will still work — but delete the source file from your local machine immediately after.
Step 5: Verify the Migration
After import completes:
- Check the item count: Tools → Import Data shows a confirmation message like "Imported 247 items." Compare this to your old Bitwarden vault count (visible in the item list sidebar).
- Open 3–5 logins at random and confirm usernames, passwords, URLs, and notes are intact.
- Test autofill by installing the Bitwarden browser extension (it is fully compatible with Vaultwarden) and pointing the Server URL to
https://vault.yourdomain.com. Log in and confirm autofill works on a test site. - Check that collections and folders appear correctly.
- Verify TOTP seeds: if any items have TOTP stored, confirm the codes generate correctly.
You should see: Item count in the new Vaultwarden instance equal to or greater than (if you have org items) the count in the old Bitwarden instance.
Step 6: Harden and Lock Down Vaultwarden
Once migration is confirmed, update docker-compose.yml:
SIGNUPS_ALLOWED: "false"
INVITATIONS_ALLOWED: "false"
Then restart:
docker compose up -d
Disable the admin panel token if you don't need ongoing admin access, or rotate it to a new hash. Enable fail2ban on your host to block brute-force login attempts against the Vaultwarden login endpoint.
Recommended Tools to Complement Your Self-Hosted Setup
Self-hosting gives you control, but it also puts maintenance and uptime on you. If you're managing credentials for a team — especially in a regulated environment — a managed solution can offload audit logging, MFA enforcement, and breach monitoring.
1Password is worth evaluating for teams who want zero infrastructure overhead. 1Password uses AES-256-GCM encryption with PBKDF2-SHA256 at 650,000 iterations, adds a Secret Key as a second factor for account recovery, and supports WebAuthn/FIDO2, TOTP, and hardware keys (YubiKey, Titan). Pricing: $2.99/user/month (Individual, billed annually), $4.99/user/month (Families, up to 5 users), $7.99/user/month (Teams Starter, up to 10 users), $19.95/user/month (Business, billed annually, no seat minimum). 1Password is headquartered in Toronto, Canada (PIPEDA jurisdiction) and completed a SOC 2 Type II audit by Prescient Assurance in 2023. If your team is in healthcare, our Best Password Manager for Healthcare & HIPAA Compliance in 2026 review covers how 1Password handles BAAs.
Try 1Password — best choice if your team outgrows what a single Vaultwarden instance can practically support.
Keeper Security is the stronger pick for businesses needing detailed audit trails and role-based access controls that Vaultwarden's admin panel doesn't fully replicate. Keeper uses AES-256-GCM with PBKDF2-SHA256 at 1,000,000 iterations, supports WebAuthn, TOTP, Duo, RSA SecurID, and hardware keys. Pricing: $4.99/user/month (Personal, billed annually), $6.25/user/month (Family, up to 5 users), $4.99/user/month (Business Starter, minimum 5 users), $6.00/user/month (Enterprise, minimum 5 users, billed annually — contact sales for volume). Keeper is headquartered in Chicago, Illinois (SOC 2 Type II audited by Schellman in 2024, FedRAMP Authorized). See our Best Enterprise Password Manager Review (2026) for a full breakdown.
Try Keeper Security — ideal if you need compliance-grade audit logs your Vaultwarden instance can't easily produce.
Troubleshooting
Error: "Invalid master password" during import
This happens when you exported an encrypted JSON but are trying to import it without entering the master password in the import dialog, or when the account email on the new Vaultwarden differs from the one the export was encrypted for. Fix: ensure the import account email matches the original, and enter the original master password in the import dialog's password field.
Error: "Failed to deserialize: missing field 'reprompt'"
Occurs when importing a Bitwarden export from version 2023.x or earlier into Vaultwarden 1.31+. Fix: open the JSON in a text editor, search for "type": 1, and confirm items have a "reprompt" field. If missing, add "reprompt": 0 to each item block. A Python one-liner can automate this: python3 -c "import json,sys; d=json.load(open('export.json')); [i.setdefault('reprompt',0) for i in d['items']]; json.dump(d,open('fixed.json','w'))".
Container starts but web UI returns a blank page
Usually a WebSocket misconfiguration. Confirm your Caddyfile routes /notifications/hub to port 3012, not port 80. After editing the Caddyfile, run docker compose restart caddy.
Vaultwarden admin panel returns "Incorrect admin token"
Vaultwarden 1.30+ requires a bcrypt or Argon2id hash, not a plain-text token. Re-generate with docker run --rm vaultwarden/server /vaultwarden hash --preset owasp and update ADMIN_TOKEN in your compose file, then docker compose up -d.
Send features and premium attachments not working
Vaultwarden enables most premium features for all users by default, but you must explicitly set ORG_GROUPS_ENABLED=true and confirm SENDS_ALLOWED=true in your environment block. Restart the container after any environment change.
FAQ
Is Vaultwarden safe to use for production password management in 2026?
Vaultwarden is safe for production use when properly configured — it implements the same AES-256-CBC/GCM vault encryption and PBKDF2-SHA256 key derivation as the official Bitwarden server, and all crypto happens client-side. The risk difference from official Bitwarden is operational: you're responsible for keeping the Docker image updated, patching the host OS, and maintaining backups. As of 2026, Vaultwarden has no known critical CVEs in its release history, though it has not undergone an independent third-party security audit the way the official Bitwarden server has (audited by Cure53 in 2022). Self-hosters in regulated industries should factor this audit gap into their risk assessment.
Can I migrate back from Vaultwarden to official Bitwarden self-hosted?
Yes. The migration is reversible because Vaultwarden uses the same Bitwarden client API and export format. Log into your Vaultwarden web vault, go to Tools → Export Vault, export as Bitwarden JSON (encrypted or unencrypted), then import that file into a fresh official Bitwarden self-hosted instance using the same import path. Organization vaults require a separate export/import step. Attachments, as with the forward migration, must be manually re-uploaded because they are not included in JSON exports from either platform.
Will my Bitwarden browser extension and mobile apps work with Vaultwarden without reinstalling?
Yes. The Bitwarden browser extensions (Chrome, Firefox, Safari, Edge) and mobile apps (iOS, Android) all support custom server URLs. In the extension, click the region selector or settings icon and enter your Vaultwarden domain under "Self-hosted server URL." You do not need a separate Vaultwarden-specific client — every official Bitwarden client is compatible. The only features that differ are admin-panel controls and a few enterprise SSO options that Vaultwarden implements partially. TOTP, WebAuthn, and hardware key support work correctly.
What happens to shared Organization vaults and Collections during the migration?
Organization vaults and Collections are not included in a personal vault export — you must export them separately from the Organization admin console. In Vaultwarden, create the Organization first, invite members, then import the Organization export under the Organization's Tools section. User permissions and Collection assignments are preserved in the JSON export structure. Group-based permissions (an enterprise Bitwarden feature) require ORG_GROUPS_ENABLED=true in your Vaultwarden environment variables; otherwise, group assignments are dropped silently and you'll need to reassign Collection access manually.
**How much does it cost to run Vaultwarden compared to official Bitwarden