Vaultwarden Backup
This role backs up Vaultwarden (self-hosted Bitwarden) password vault using the official Bitwarden CLI.
Vaultwarden Backup Role
Overview
This role backs up Vaultwarden (self-hosted Bitwarden) password vault using the official Bitwarden CLI. It downloads the CLI temporarily, authenticates with API credentials, exports the vault as encrypted JSON, and stores it on dual NAS storage. The role automatically manages retention by keeping only the last 5 backups per NAS.
Purpose
- Password Vault Protection: Backs up all passwords, notes, and vault items
- Encrypted Export: Vault exported in encrypted format for security
- Disaster Recovery: Restore vault after data loss or corruption
- Migration Support: Transfer vault to new Vaultwarden instance
- Dual Redundancy: Backs up to two separate NAS devices (Synology DS418 and Proxmox OMV)
- Automated Process: Handles authentication, sync, export, and cleanup automatically
Requirements
- Ansible 2.9 or higher
- Vaultwarden server accessible via HTTPS
- Vaultwarden API credentials (client ID and secret)
- Master password for vault
- Export password for encrypted backups
- NAS mount points must be accessible and writable
unzippackage (installed by role if missing)
What is Vaultwarden?
Vaultwarden is an unofficial Bitwarden-compatible server written in Rust. It provides:
- Self-hosted password vault
- Multi-device synchronization
- Password generation
- Secure notes and file attachments
- Two-factor authentication
- Compatible with official Bitwarden clients
Role Variables
Required Variables
| Variable | Required | Description |
|---|---|---|
vault_vaultwarden_api_client_id | Yes | Vaultwarden API client ID (stored in Ansible Vault) |
vault_vaultwarden_api_client_secret | Yes | Vaultwarden API client secret (stored in Ansible Vault) |
vault_vaultwarden_master_password | Yes | Vault master password (stored in Ansible Vault) |
vault_vaultwarden_backup_export_password | Yes | Password for encrypting the export (stored in Ansible Vault) |
Optional Variables
| Variable | Default | Description |
|---|---|---|
vaultwarden_backup_url | https://server.homelab | Vaultwarden instance URL |
vaultwarden_backup_ca_file | "" (system CA bundle) | Custom CA certificate file path |
vaultwarden_backup_syno_mount_point | /mnt/synology-ds418/vaultwarden | Synology NAS backup destination |
vaultwarden_backup_prxmxomv_mount_point | /mnt/prxmx-omv/vaultwarden | Proxmox OMV NAS backup destination |
Variable Details
API Credentials (vault_vaultwarden_api_client_id and vault_vaultwarden_api_client_secret)
API credentials for programmatic access to Vaultwarden.
How to create API credentials in Vaultwarden:
- Log into Vaultwarden web vault
- Go to Settings → Security → Keys
- Click “View API Key”
- Enter master password
- Copy client_id and client_secret
Example vault variables:
vault_vaultwarden_api_client_id: "user.abc123def-456-789-ghi-jkl012mno345"
vault_vaultwarden_api_client_secret: "pqr678stu901vwx234yz..."
Master Password (vault_vaultwarden_master_password)
Your Vaultwarden master password. Required to unlock the vault.
Example vault variable:
vault_vaultwarden_master_password: "YourVerySecureMasterPassword123!"
Export Password (vault_vaultwarden_backup_export_password)
Password used to encrypt the exported JSON file. Should be different from master password for defense in depth.
Example vault variable:
vault_vaultwarden_backup_export_password: "DifferentSecureExportPassword456!"
Custom CA Certificate (vaultwarden_backup_ca_file)
Path to custom CA certificate file if using self-signed certificates.
Example:
vaultwarden_backup_ca_file: "/etc/ssl/certs/custom-ca.crt"
Dependencies
This role has no dependencies on other Ansible roles, but requires:
- Vaultwarden server running and accessible
- Valid Vaultwarden account with API access
- NAS mounts configured (see
nas_mountornas_mount_systemdroles) - Internet access to download Bitwarden CLI
Example Playbook
Basic Usage
---
- name: Backup Vaultwarden Vault
hosts: localhost
become: true
roles:
- vaultwarden_backup
With Custom Configuration
---
- name: Backup Vaultwarden with Custom Settings
hosts: localhost
become: true
vars:
vaultwarden_backup_url: "https://passwords.example.com"
vaultwarden_backup_ca_file: "/etc/ssl/certs/my-ca.crt"
roles:
- vaultwarden_backup
Scheduled Backup with Cron
---
- name: Schedule Weekly Vaultwarden Backup
hosts: localhost
become: true
tasks:
- name: Create cron job for weekly vault backup
ansible.builtin.cron:
name: "Weekly Vaultwarden Vault Backup"
minute: "0"
hour: "3"
weekday: "0" # Sunday
job: "ansible-playbook /path/to/vaultwarden_backup.yml"
What This Role Does
- Ensures backup directories exist on both NAS mount points
- Creates temporary directory for Bitwarden CLI
- Downloads Bitwarden CLI from official source
- Ensures unzip is installed (for extracting CLI)
- Extracts Bitwarden CLI binary
- Sets executable permissions on CLI binary
- Configures server URL for Vaultwarden instance
- Logs in with API credentials (using environment variables)
- Unlocks vault with master password
- Extracts session key for authenticated operations
- Syncs vault to ensure latest data
- Exports vault as encrypted JSON to Synology NAS
- Exports vault as encrypted JSON to Proxmox OMV NAS
- Locks vault (clears session)
- Logs out from Vaultwarden
- Displays success message
- Cleans up temporary CLI directory
- Removes old backups, keeping only the 5 most recent per NAS
Bitwarden CLI Workflow
1. Download and Setup
# Download CLI
wget https://bitwarden.com/download/?app=cli&platform=linux -O bw-linux.zip
# Extract
unzip bw-linux.zip
# Make executable
chmod +x bw
2. Configure Server
bw config server https://server.homelab
3. Login with API Key
export BW_CLIENTID="client_id"
export BW_CLIENTSECRET="client_secret"
bw login --apikey
4. Unlock Vault
export BW_PASSWORD="master_password"
BW_SESSION=$(bw unlock --passwordenv BW_PASSWORD --raw)
5. Sync and Export
bw sync --session $BW_SESSION
bw export --format encrypted_json --password 'export_password' --output backup.json --session $BW_SESSION
6. Cleanup
bw lock
bw logout
Backup Format
File Naming
vaultwarden_backup_YYYYMMDD_HHMMSS.json
Examples:
vaultwarden_backup_20260107_143022.jsonvaultwarden_backup_20260107_190530.json
Note: Uses underscore instead of ‘T’ for better readability.
JSON Content
The backup is an encrypted JSON file containing:
- All vault items (logins, notes, cards, identities)
- Folders and organization
- Attachments metadata (not files)
- Encrypted with the export password
Format:
{
"encrypted": true,
"passwordProtected": true,
"salt": "...",
"kdfIterations": 100000,
"kdfType": 0,
"encKeyValidation_DO_NOT_EDIT": "...",
"data": "...encrypted data..."
}
Backup Content
The backup includes:
- All vault items (logins, secure notes, cards, identities)
- Folders and collections
- Custom fields
- URIs and match detection settings
- TOTP secrets (2FA seeds)
- Attachments metadata (filenames, not actual files)
The backup does NOT include:
- File attachments (actual file content)
- Trash/deleted items
- Vault history
- Organization settings (if using organizations)
Backup Security
The exported JSON is doubly encrypted:
- Bitwarden Encryption: Vault items are encrypted with your master password (always)
- Export Encryption: The export file is encrypted with the export password
To decrypt, you need:
- Bitwarden CLI
- Export password
- Master password (to access items after import)
Backup Retention
The role implements automatic retention management:
- Keeps: Last 5 backups per NAS
- Deletes: Backups older than the 5th most recent
- Per-NAS logic: Each NAS independently maintains 5 backups
This ensures you have:
- 5 backups on Synology DS418
- 5 backups on Proxmox OMV
- Total: Up to 10 backup copies across both devices
Restoration
Import via Bitwarden CLI
# Configure server
bw config server https://server.homelab
# Login
bw login admin@example.com
# Unlock
export BW_SESSION=$(bw unlock --raw)
# Import encrypted backup
bw import bitwardenencjson vaultwarden_backup_20260107_143022.json \
--importsecurepassword 'export_password' --session $BW_SESSION
Import via Web Vault
- Log into Vaultwarden web vault
- Go to Tools → Import Data
- Select format: “Bitwarden (json) - Encrypted”
- Choose file
- Enter export password
- Click “Import”
Security Considerations
- Credentials Protected: All sensitive values marked with
no_log: true - Vault Storage: All credentials must be in Ansible Vault
- Double Encryption: Export is encrypted separately from vault encryption
- Temporary CLI: Downloaded and cleaned up automatically
- Session Management: Vault locked and logged out after export
- File Permissions: Backup files should be readable only by authorized users
- Consider Encryption at Rest: Encrypt NAS volumes for additional security
Tags
This role does not define any tags. Use playbook-level tags if needed:
- hosts: localhost
roles:
- vaultwarden_backup
tags:
- backup
- vaultwarden
- passwords
- security
Notes
- Downloads official Bitwarden CLI from bitwarden.com
- CLI is temporary and removed after backup
- Requires internet access to download CLI
- Export includes vault metadata but not actual attachment files
- Role uses shell module for password handling (more secure than command)
- Supports custom CA certificates for self-signed SSL
Troubleshooting
”Authentication failed” or login errors
Verify API credentials:
- Check client ID and secret are correct
- Regenerate API key in Vaultwarden if needed
- Ensure account is active and not locked
”Invalid master password”
Check:
- Master password is correct (case-sensitive)
- Account hasn’t been locked due to failed attempts
- Test login via web vault
”Failed to export”
Common causes:
- Export password is weak (needs to meet minimum requirements)
- Insufficient disk space on NAS
- Permission issues on destination directory
”Connection refused” or SSL errors
Verify:
- Vaultwarden is running and accessible
- URL is correct
- SSL certificates are valid (or use custom CA)
- Network connectivity
”Command not found” for unzip
The role installs unzip, but if it fails:
# Debian/Ubuntu
sudo apt-get install unzip
# RedHat/CentOS
sudo yum install unzip
Large vault takes long time
Normal for vaults with:
- Thousands of items
- Many attachments (metadata)
- Slow network connection
Typical times:
- Small vault (< 100 items): ~10-15 seconds
- Medium vault (< 1000 items): ~30-60 seconds
- Large vault (1000+ items): ~1-3 minutes
Performance Considerations
- CLI download: ~5MB, takes 1-5 seconds
- Login and unlock: ~2-3 seconds
- Sync: Variable (depends on vault size)
- Export: Variable (depends on vault size and NAS speed)
Total time: Usually 20-60 seconds for average vault
Bitwarden/Vaultwarden Compatibility
- Bitwarden CLI: Works with both official Bitwarden and Vaultwarden
- Vaultwarden: Compatible with all Bitwarden CLI versions
- Export Format: Standard across Bitwarden/Vaultwarden
Best Practices
- Use strong export password (different from master password)
- Schedule regular backups (weekly minimum)
- Test restoration periodically
- Encrypt NAS volumes for additional security
- Keep export password secure (store in Ansible Vault)
- Monitor backup job for failures
Alternative: Database Backup
For additional safety, also backup the Vaultwarden database:
# Backup SQLite database (if using SQLite)
- name: Backup Vaultwarden database
ansible.builtin.copy:
src: /path/to/vaultwarden/db.sqlite3
dest: /mnt/nas/vaultwarden/db_backup.sqlite3
remote_src: true
This provides a low-level backup in addition to the encrypted export.
License
MIT
Author
Created for homelab infrastructure management.