Deployment guide

Migrate from Bitwarden Cloud to Vaultwarden on a VPS

Deploy on a VPS Cloud →

Tutorial

Migrate from Bitwarden Cloud to Vaultwarden on a VPS

Security & Monitoring10 min read6 steps

Bitwarden's price increase in early 2026 pushed many developers to finally self-host their password manager. Vaultwarden is the open-source implementation of the Bitwarden server, compatible with all official clients, running in under 50 MB of RAM. Migration from Bitwarden cloud is achievable in an hour — provided you don't underestimate what the standard JSON export doesn't include.

Contents· Why migrate to self-hosted Vaultwarden1/8
  1. 01Why migrate to self-hosted Vaultwarden
  2. 02What Vaultwarden offers over Bitwarden cloud
  3. 03Prerequisites before starting
  4. 04Migrating from Bitwarden cloud to Vaultwarden: complete procedure
  5. 05Post-migration configuration
  6. 06Encrypt the export file before storing it
  7. 07Troubleshooting: common errors
  8. 08Your self-hosted vault is operational

Why migrate to self-hosted Vaultwarden

Bitwarden raised its prices by approximately 98% in early 2026 on individual and family plans. This increase made the cost question concrete for a tool that had previously remained affordable. But cost is not the only reason to migrate.

Vaultwarden is a Rust rewrite of the Bitwarden server. It exposes the same API as the official service, meaning all Bitwarden clients — browser extension, mobile app, CLI — work without any modifications, simply by pointing to your own domain. Team vaults, organizations, collections, TOTP, and two-factor authentication are available on the self-hosted instance, whereas they require paid plans on the official cloud service.

Verify this on github.com/dani-garcia/vaultwarden: the project has over 40,000 stars and an active community, with regular migration discussions including a 200+ comment thread opened in 2026 on export/import techniques.

What Vaultwarden offers over Bitwarden cloud

  • Fixed monthly cost: the price of your VPS, not a per-user or per-feature subscription.
  • Organization vaults and collections at no extra cost: available from installation, not reserved to a premium plan.
  • Built-in TOTP: two-factor authentication codes stored in Vaultwarden, no Bitwarden Premium plan required.
  • Data on your infrastructure: no third party has access to your encrypted vault or connection logs.
  • Full compatibility with official Bitwarden clients: no change in habits for your users.
  • Very low resource usage: less than 50 MB of RAM at rest, runs on the smallest VPS alongside other services.

Prerequisites before starting

Vaultwarden already deployed. This guide covers data migration only. If your Vaultwarden instance is not yet set up, start by deploying Vaultwarden on your VPS: Docker, reverse proxy, SSL, and SMTP configuration are detailed there.

Bitwarden CLI installed at a recent version. Version 2024.x or later is recommended. Check with bw --version. Install via npm install -g @bitwarden/cli or by downloading the binary from bitwarden.com/help/cli.

SMTP configured on Vaultwarden. Organization invitations require a working SMTP server. Without it, the organization import step fails silently: invited members never receive their email and remain blocked. Environment variables to check in your docker-compose.yml or Vaultwarden .env file:

SMTP_HOST=smtp.example.com
[email protected]
SMTP_PORT=587
SMTP_SECURITY=starttls
[email protected]
SMTP_PASSWORD=yourpassword

An active admin account on your Vaultwarden. You will need it to manually create organizations after import.

Time estimate. Allow 30 to 60 minutes depending on data volume and number of organizations. The longest part is manually downloading attachments.

Migrating from Bitwarden cloud to Vaultwarden: complete procedure

  1. Authenticate to Bitwarden cloud with the CLI

    Open a terminal and log in to your Bitwarden cloud account. The CLI authenticates to the official server by default — do not change the server target yet; this command must target Bitwarden cloud, not your Vaultwarden:

    bw login

    Enter your email and master password. If you have TOTP or a security key enabled, the CLI will prompt you. Once authenticated, unlock the vault and export the session key:

    export BW_SESSION=$(bw unlock --raw)

    The --raw flag is essential: without it, bw unlock displays a multi-line formatted message instead of the raw key, and subsequent commands using $BW_SESSION will return an authentication error. This is one of the most common errors in this process.

    Verify the session is valid:

    bw status

    The response should show "status": "unlocked".

  2. Export your personal vault in Bitwarden JSON format

    Exporting in the native Bitwarden JSON format (bitwardenjson) preserves all metadata: entry types, custom fields, URIs, notes, TOTP. Do not use CSV format, which loses this information.

    bw export --format bitwardenjson --output ./bitwarden-personal.json

    Attention : This file does not contain your attachments. This is the most significant gap in the standard export. Attachments must be downloaded separately, entry by entry (step 4). Note that credit card credentials, identities, and secure notes are included in this export.

    The JSON file is client-side encrypted — it contains your data in cleartext (protected only by file permissions). Store it in a private directory and delete it after import.

  3. Export each organization separately

    Organization data is not included in the personal vault export. Each organization must be exported with its own identifier.

    First list your organizations to retrieve their identifiers:

    bw list organizations

    For each organization displayed, note its id and export it:

    bw export --organizationid <organization-id> --format bitwardenjson --output ./bitwarden-org-<name>.json

    Repeat this command for each organization. If you have three organizations, you will get three separate JSON files.

    If the command returns a permission error, verify that you are the owner or administrator of the organization in the Bitwarden web interface. A member without export rights cannot use this command.

  4. Download attachments

    This is the step most guides skip. The JSON export lists entries but does not contain attached files — neither their content nor even their name.

    For each entry that has an attachment, use the bw get attachment command:

    bw list items | jq '.[] | select(.attachments != null) | {id, name, attachments}'

    This command lists entries with attachments. For each attachment, download it by specifying the item identifier and the file name:

    bw get attachment <file-name> --itemid <entry-id> --output ./attachments/

    Replace <file-name> with the exact attachment name as it appears in the JSON list, and <entry-id> with the corresponding Bitwarden entry id.

    If you have many attachments, this bash script automates the download:

    mkdir -p ./attachments
    bw list items | jq -c '.[] | select(.attachments != null)' | while read item; do
      ITEM_ID=$(echo $item | jq -r '.id')
      ITEM_NAME=$(echo $item | jq -r '.name')
      echo $item | jq -c '.attachments[]' | while read att; do
        ATT_ID=$(echo $att | jq -r '.id')
        ATT_NAME=$(echo $att | jq -r '.fileName')
        bw get attachment "$ATT_NAME" --itemid "$ITEM_ID" --output "./attachments/${ITEM_ID}_${ATT_NAME}"
      done
    done

    Note: jq must be installed on your machine (apt install jq or brew install jq).

  5. Import into Vaultwarden

    First redirect the CLI to your Vaultwarden instance. This is the irreversible operation in this procedure: the CLI can only point to one server at a time.

    bw config server https://vault.yourdomain.com

    Authenticate to Vaultwarden:

    bw logout
    bw login
    export BW_SESSION=$(bw unlock --raw)

    Import the personal vault:

    bw import bitwardenjson ./bitwarden-personal.json

    For organizations, you must first create the organization in the Vaultwarden web interface, then retrieve its identifier:

    bw list organizations

    Then import each organization file with the newly created identifier:

    bw import bitwardenjson ./bitwarden-org-<name>.json --organizationid <new-id>

    Finally, manually re-attach downloaded attachments to their entries through the Vaultwarden web interface: navigate to the entry, click "Edit", then add the attachment from the ./attachments/ directory.

  6. Verify the import and update clients

    Before considering the migration complete, perform these checks:

    In the Vaultwarden web interface, verify:
    - the number of entries matches that of Bitwarden cloud;
    - custom fields are present on a few reference entries;
    - TOTP codes work (test a code);
    - organizations and their collections are visible.

    On Bitwarden clients (browser extension, mobile app):
    - log out of the Bitwarden cloud account;
    - in the client settings, change the server URL to https://vault.yourdomain.com;
    - log back in with the same credentials.

    Wait for full sync before deleting anything on the old cloud account. Keep access to Bitwarden cloud active for at least 48 hours after migration to verify if in doubt.

Post-migration configuration

Automatic backups. Unlike the cloud service, backing up your self-hosted instance is your responsibility. The Vaultwarden data file is data/db.sqlite3 (or the full data/ directory). A daily cron job is sufficient:

0 3 * * * tar -czf /backup/vaultwarden-$(date +%Y%m%d).tar.gz /opt/vaultwarden/data/ 2>/dev/null

Organization invitations. If you manage organizations with multiple members, each member must be re-invited from the Vaultwarden admin interface. The invitation is sent by email (hence the importance of SMTP). The member accepts, you confirm from the administration. The procedure is identical to Bitwarden cloud.

Two-factor authentication. Set up 2FA on your self-hosted Vaultwarden account at first login. Vaultwarden supports TOTP, Duo, WebAuthn (FIDO2 keys), and email. Access to the admin interface (/admin) should be protected by a token defined in ADMIN_TOKEN.

Encrypt the export file before storing it

The Bitwarden JSON export contains your passwords in cleartext. If you need to keep this file temporarily (during post-migration verification), encrypt it with GPG or your secrets manager before putting it on a disk or sending it anywhere:

gpg --symmetric --cipher-algo AES256 bitwarden-personal.json
rm bitwarden-personal.json

Delete the unencrypted file immediately. A Bitwarden JSON file forgotten in a temporary folder is a direct security breach.

Troubleshooting: common errors

Session expired during export. Symptom: Not logged in or Session key is invalid mid-procedure. The Bitwarden CLI session expires after a few minutes of inactivity. Solution:

export BW_SESSION=$(bw unlock --raw)

Re-export the variable each time you resume work after a break.

--raw missing from bw unlock. Without --raw, bw unlock displays a formatted message including the command to run, not just the raw key. If you copy-paste directly into export BW_SESSION=, you get an incorrect value and all subsequent commands return an authentication error. Always use bw unlock --raw.

bw export --organizationid returns You do not have permission. You are not the owner or administrator of the organization. In the Bitwarden web interface, go to organization settings and check your role. Only the Owner can export.

Import fails with already exists. The Bitwarden CLI refuses to overwrite existing entries during import. If you rerun an import after a partial attempt, you will get duplicates or errors. Solution: clear the Vaultwarden vault via the web interface (Settings → Danger Zone → Purge Vault) before re-running the import.

TOTP codes don't work after import. The Bitwarden JSON export includes encrypted TOTP seeds. If they don't appear on Vaultwarden, verify that you used the bitwardenjson format (not csv, which doesn't support TOTP). If the issue persists, manually re-enter TOTP seeds from your original authenticator apps.

Attachments missing after import. Reminder: the standard JSON export does not contain attachments. They must be downloaded via bw get attachment (step 4) and re-attached manually through the Vaultwarden web interface.

Your self-hosted vault is operational

Migration from Bitwarden cloud to Vaultwarden comes down to six steps if you prepared your instance and SMTP in advance: personal export, per-organization exports, attachment download, CLI reconfiguration, imports, verification.

The two points not to overlook are the bitwardenjson format (not csv) and the attachments step, which is not part of any automatic export. With this procedure, no data remains on Bitwarden's servers unless you decide to leave it there.

To go further in securing the VPS hosting your Vaultwarden, see the Linux hardening checklist and the guide on automatic security updates.

Activate Vaultwarden on your VPS

Deploy Vaultwarden in minutes on a VPS with root access, dedicated IPv4, and OS choice. Your passwords stay on your infrastructure.

Need help?

Browse our help center and FAQ, or reach our team — callback, WhatsApp or email. Support in French, English and Arabic.

Message us on WhatsAppopens in a new tab