Why migrate now
Since March 27, 2026, the 1Password Individual plan billed annually has gone from {{$35.88/yr}} to {{$47.88/yr}}, a 33% increase. In January 2026, Bitwarden.com had already raised its Premium plan from $9.99 to $19.80 per year — nearly double. Both increases happening simultaneously made self-hosting economically obvious for developers who already have a VPS: Vaultwarden runs on less than 50 MB of RAM, with no software license fee, at a fixed monthly cost equal to an entry-level VPS.
The most common objection — "managing my own password manager is risky" — does not hold against Vaultwarden's architecture. Encryption is done entirely client-side, using AES-256-CBC with PBKDF2 or Argon2id key derivation: the server never sees your passwords in plaintext, even in the event of a full machine compromise.
What Vaultwarden brings to a developer
- AES-256-CBC client-side encryption — your passwords never leave your device in plaintext, regardless of the server configuration.
- Full compatibility with all official Bitwarden clients: browser extensions, iOS, Android, desktop apps and CLI, without any modifications.
- Lightweight memory footprint — the Vaultwarden process alone uses 10 to 30 MB of RAM; less than 100 MB with the Docker container.
- Fixed cost — a 1 vCPU / 512 MB VPS is enough for personal use or a small team, with no variable SaaS subscription.
- Full data control — backup, restore, datacenter choice and retention period remain in your hands.
- Multi-profile and organization support — Vaultwarden supports organization management and vault sharing, just like Bitwarden.com.
- Decoupled updates — you choose when to update the server; official Bitwarden clients manage their own release cycle.
Prerequisites before you start
Before starting the migration, make sure you have all of the following.
Server side: a VPS with at least 1 vCPU and 512 MB of RAM, Docker and Docker Compose installed, a domain name pointing to the server IP, and a reverse proxy (Caddy or Nginx) configured for TLS termination. The Vaultwarden deployment itself is covered in the article Deploy Vaultwarden on a VPS — this guide assumes your instance is already online and accessible over HTTPS.
Local workstation: 1Password v8 or later installed (required to export in .1pux format), Bitwarden CLI (bw) installed via npm (npm install -g @bitwarden/cli) or the official binary, and Node.js ≥ 18 if installing via npm.
Step 1 — Export your 1Password vault
Open the export dialog
On macOS, open 1Password and go to File → Export. On Windows, click the ellipsis (…) at the top of the sidebar, then Export. Select the account to export — if you have multiple vaults, you can export the entire account in a single operation.
Choose the 1PUX format
In the dialog box, enter your 1Password account password to confirm the operation. Then select the 1Password Unencrypted Export (.1pux) format. This JSON-based format preserves the full structure — custom fields, secure notes, identities, application passwords — unlike CSV, which truncates metadata.
Save the file somewhere safe
Choose an encrypted local folder (FileVault or BitLocker enabled) to store the .1pux file. This file contains all your secrets in structured plaintext — do not leave it in a downloads folder or send it by email. Once the migration is complete, delete it securely.
Step 2 — Import with Bitwarden CLI
Point the CLI to your Vaultwarden instance
By default, bw points to bitwarden.com. Redirect it to your instance before anything else:
bw config server https://vault.your-domain.comVerify the response: the CLI should confirm Saved setting 'serverUrl'.
Log in and unlock the vault
Authenticate with your Vaultwarden credentials (email + master password set during initial setup):
bw login [email protected]The CLI will prompt for your master password interactively. Once logged in, unlock the vault and export the session key:
export BW_SESSION=$(bw unlock --raw)All subsequent commands use this variable implicitly to access the decrypted vault.
Run the .1pux import
Import your 1Password export using the 1password1pux format:
bw import 1password1pux /path/to/export.1puxThe CLI shows progress and a summary of imported items by type (logins, notes, identities, cards). If your 1Password account contained multiple vaults, they are all imported into a single Bitwarden vault — folders are recreated to preserve the structure.
If you see an Invalid format error, verify the file has the .1pux extension and that you are using a recent CLI version (bw --version).
Verify the import in a Bitwarden client
Open the Bitwarden browser extension or desktop app, point the server to your Vaultwarden instance, then log in. Browse your vaults and check a sample of passwords — in particular entries with custom fields, secure notes and identities, which are most likely to vary between password managers.
Step 3 — Vaultwarden on your VPS
If your Vaultwarden instance is not yet deployed, follow the guide Deploy Vaultwarden on a VPS, which covers the full Docker configuration. In summary, three points are non-negotiable before importing anything:
HTTPS required. Bitwarden clients refuse to connect to a server without valid TLS. Caddy or Nginx with Let's Encrypt (certbot) are sufficient; verify your domain is reachable over https:// before configuring the CLI.
Correct DOMAIN variable. In your docker-compose.yml, the variable DOMAIN=https://vault.your-domain.com must match exactly the URL you declared in bw config server — no trailing slash.
Volume backup before import. The import writes to Vaultwarden's SQLite database (/data/db.sqlite3). Take a snapshot of your Docker volume before running bw import, so you can roll back if the import goes wrong.
1Password vs Bitwarden.com vs Vaultwarden
| Criterion | 1Password | Bitwarden.com | Vaultwarden (self-hosted) |
|---|---|---|---|
| Annual cost (individual) | {{$47.88/yr}} since March 2026 | {{$19.80/yr}} since Jan. 2026 (Premium) | VPS cost only |
| Data control | 1Password servers | Bitwarden servers | Your VPS, your datacenter |
| Encryption | AES-256-CBC client-side | AES-256-CBC client-side | AES-256-CBC client-side (identical) |
| Official mobile clients | Dedicated 1Password apps | iOS, Android, desktop, extension | Official Bitwarden clients, unmodified |
| Browser extension | 1Password X | Bitwarden extension | Bitwarden extension (same binary) |
| Updates | Automatic (SaaS) | Automatic (SaaS) | Manual (you choose the timing) |
| Server RAM required | N/A (SaaS) | N/A (SaaS) | 10–30 MB (process), < 100 MB (Docker) |
Back up and test restoration
Once the import is complete, set up automated backups of the Vaultwarden volume before disabling your 1Password account. The guide Restic backups on a VPS covers a Docker-adapted 3-2-1 strategy: stop the container, snapshot the volume, send encrypted to remote storage, restart. Test restoration on a separate machine — not just the presence of the backup file — before considering the migration done. A password vault without a tested restore is not a backup.
Troubleshooting — common errors
Invalid format on import. The format expected by the CLI is exactly 1password1pux (no spaces, lowercase). Make sure you are not using 1password alone or 1pux — these names correspond to other formats (respectively the 1PIF format from 1Password 6 and an unrecognized alias). List available formats with bw import --formats | grep 1password.
ERR_CERT_AUTHORITY_INVALID in clients. Bitwarden clients require a TLS certificate signed by a recognized authority — a self-signed certificate is rejected. Verify that Let's Encrypt has issued a valid certificate for your domain and that it is not expired (bw config server shows a warning if the certificate is invalid).
Vault locked in migration mode. If you import from an existing Bitwarden.com account before switching to Vaultwarden, your items remain encrypted with the cloud account key. After bw config server pointing to your instance, create a new local account: the CLI does not migrate the encryption key between instances, only plaintext data transits via import.
Import stops on an SSH entry. A known regression in certain CLI versions blocked import of SSH keys in 1pux format (issue bitwarden/clients #20432). CLI version 2026.7.0 includes a fix. Update with npm install -g @bitwarden/cli@latest if you encounter this behavior.
Leaving 1Password with confidence
Once the import is verified on the Vaultwarden side — open each item type (logins, notes, identities, cards) in a Bitwarden client and check a representative sample — you can deactivate your 1Password account. Do not wait for your subscription to expire before deleting the local .1pux file: it contains all your secrets in structured plaintext.
To go further in securing your infrastructure, the articles Initial Linux server hardening and Passbolt for a team cover the next steps: port lockdown, SSH key management and secure sharing in a team context.