Configure once, forget forever. Automated Bitwarden vault backups with multi-remote cloud storage support. Set up once and enjoy hands-free daily backups to multiple cloud services simultaneously (S3, Google Drive, Dropbox, OneDrive, Cloudflare R2, and 40+ others). Supports both official Bitwarden and self-hosted servers.
# If you have this repo cloned:
./generate-rclone-base64.sh
# Interactive mode (create new config):
./generate-rclone-base64.sh --interactive
# Test config and save to file:
./generate-rclone-base64.sh --test --output my-config.txt
# Or manually create base64 from existing rclone config:
base64 -w 0 < ~/.config/rclone/rclone.conf
Create a .env
file with these 5 required variables:
cat > .env << EOF
BW_CLIENTID=your_bitwarden_client_id
BW_CLIENTSECRET=your_bitwarden_client_secret
BW_PASSWORD=your_bitwarden_master_password
ENCRYPTION_PASSWORD=your_strong_encryption_password
RCLONE_CONFIG_BASE64=your_base64_encoded_rclone_config
EOF
โก Fastest (No cloning required):
docker run --rm --env-file .env --pull always \
-e BITWARDENCLI_APPDATA_DIR=/tmp/bw_appdata \
nikhilbadyal/bitwarden-backup:latest
Or with Docker Compose:
git clone https://github.com/nikhilbadyal/bitwarden-backup.git
cd bitwarden-backup
# Copy your .env file here
docker-compose up --build
Or with scripts:
./setup-rclone.sh && ./scripts/backup.sh
Thatโs it! Your vault will be backed up to all configured remotes with encryption and compression.
This project includes a REST API for managing your Bitwarden backups through a web interface or programmatic access.
For detailed API setup instructions, Docker configuration, and usage examples, see:
๐ API.md - Complete API Setup Guide
Quick Start:
# Run the API with Docker
./run-api.sh
# Access the API
# - API Root: http://localhost:5050/
# - Documentation: http://localhost:5050/api/v1/docs
The API provides endpoints for:
This repository provides a โconfigure once, forget foreverโ solution for Bitwarden vault backups:
setup-rclone.sh
: Configures rclone from a base64-encoded configuration to support ANY rclone-compatible storage servicebackup.sh
: Performs automated backup, validates, compresses, encrypts, and uploads to ALL configured remotes simultaneouslygenerate-rclone-base64.sh
: Helper script to generate base64-encoded rclone configurationsrestore-backup.sh
: Decrypt and restore backup files back to plain JSON formatbw
, jq
, gzip
, openssl
, rclone
CLI tools installed๐ง Full Setup (Clone Repository):
git clone https://github.com/nikhilbadyal/bitwarden-backup.git
cd bitwarden-backup
# Generate rclone config
./generate-rclone-base64.sh
# Create .env file (copy from env.example)
cp env.example .env
# Edit .env with your values
# Run backup
./setup-rclone.sh && ./scripts/backup.sh
Variable | Description | Example |
---|---|---|
BW_CLIENTID |
Your Bitwarden API Client ID | user.1234567890abcdef |
BW_CLIENTSECRET |
Your Bitwarden API Client Secret | abcdef1234567890 |
BW_PASSWORD |
Your Bitwarden Master Password | MySecretPassword123! |
ENCRYPTION_PASSWORD |
Strong password for backup encryption | BackupEncryption456! |
RCLONE_CONFIG_BASE64 |
Base64-encoded rclone configuration | W215LXMzXQp0eXBlID0gczMK... |
Variable | Description | Example |
---|---|---|
API_TOKEN |
Authentication token for API access | your_secure_api_token |
REDIS_URL |
Redis connection URL for caching | redis://localhost:6379/0 |
BACKUP_PATH |
Remote path/bucket for storing backups | bitwarden-backup |
This backup tool fully supports self-hosted Bitwarden servers! Configure your custom server using these optional environment variables:
Variable | Description | Example |
---|---|---|
BW_SERVER |
Primary server URL (recommended approach) | https://bitwarden.example.com |
BW_WEB_VAULT |
Custom web vault URL (advanced) | https://vault.example.com |
BW_API |
Custom API URL (advanced) | https://api.example.com |
BW_IDENTITY |
Custom identity URL (advanced) | https://id.example.com |
BW_ICONS |
Custom icons service URL (advanced) | https://icons.example.com |
BW_NOTIFICATIONS |
Custom notifications URL (advanced) | https://notify.example.com |
BW_EVENTS |
Custom events URL (advanced) | https://events.example.com |
BW_KEY_CONNECTOR |
Key Connector URL (for organizations) | https://keycon.example.com |
Quick Examples:
# For most self-hosted installations, just set BW_SERVER:
BW_SERVER="https://vault.mycompany.com"
# For Bitwarden EU cloud:
BW_SERVER="https://vault.bitwarden.eu"
# For complex custom setups (rarely needed):
BW_WEB_VAULT="https://vault.example.com"
BW_API="https://api.example.com"
BW_IDENTITY="https://identity.example.com"
Important Notes:
BW_SERVER
is the recommended approach for most self-hosted installationsBW_API
, BW_IDENTITY
, etc.) override BW_SERVER
if both are setBackup Features:
Restore Features:
This backup solution supports ALL rclone-compatible storage services, including:
Object Storage:
Consumer Cloud Storage:
Enterprise Storage:
And many more! See the rclone documentation for the complete list.
Your rclone configuration can include multiple remotes:
[aws-s3]
type = s3
provider = AWS
access_key_id = AKIAIOSFODNN7EXAMPLE
secret_access_key = wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY
region = us-east-1
[google-drive]
type = drive
client_id = 123456789.apps.googleusercontent.com
client_secret = abcdefghijklmnopqrstuvwx
token = {"access_token":"ya29.a0AfH6SMC..."}
[cloudflare-r2]
type = s3
provider = Cloudflare
access_key_id = your_r2_access_key
secret_access_key = your_r2_secret_key
endpoint = https://abc123.r2.cloudflarestorage.com
[dropbox-backup]
type = dropbox
token = {"access_token":"sl.B0abcdefghijklmnop..."}
The backup script will automatically:
The restore-backup.sh
script allows you to decrypt and restore your encrypted backups back to plain JSON format.
# Decrypt a local backup file
./restore-backup.sh bw_backup_20241218123456.json.gz.enc
# Download and decrypt latest backup from S3 remote
./restore-backup.sh -r s3-remote
# List all available backups from all configured remotes
./restore-backup.sh -l
# Decrypt with custom output filename
./restore-backup.sh -f backup.enc -o my_vault.json
Option | Description | Example |
---|---|---|
-f, --file |
Decrypt local backup file | --file backup.enc |
-r, --remote |
Download & decrypt from remote | --remote s3-backup |
-o, --output |
Custom output filename | --output vault.json |
-l, --list |
List backups from all remotes | --list |
--list-remote |
List backups from specific remote | --list-remote gdrive |
--download-only |
Download without decrypting | --download-only |
ENCRYPTION_PASSWORD
from backups is requiredCode | Meaning |
---|---|
0 |
Success |
1 |
Missing required environment variable |
2 |
Missing required dependency |
3 |
Backup directory issue |
4 |
Bitwarden login failed |
5 |
Bitwarden vault unlock failed |
6 |
Bitwarden data export failed |
7 |
Invalid backup file |
8 |
Compression or encryption failed |
99 |
Unexpected error during upload |
Configure Apprise for notifications:
# Multiple notification services
APPRISE_URLS="mailto://[email protected] tgram://bot_token/chat_id discord://webhook_id/webhook_token"
Enhanced Notification Details:
The final notification now includes detailed per-remote status:
Success Notification Example:
Bitwarden backup script completed successfully. New backup uploaded: bw_backup_20241218123456.json.gz.enc.
๐ Remote Status:
โ
aws-s3: Success
โ
google-drive: Up to date
โ dropbox-backup: Failed
โ
cloudflare-r2: Success
๐ Summary: ๐ค 2 uploaded, โ
1 up-to-date, โ 1 failed
No Changes Notification Example:
Bitwarden backup script completed successfully. No changes detected, no new backup uploaded.
๐ Remote Status:
โ
aws-s3: Up to date
โ
google-drive: Up to date
โ
cloudflare-r2: Up to date
Failure Notification Example:
Bitwarden backup script failed with exit code 8.
Reason: Compression or encryption failed. Check ENCRYPTION_PASSWORD.
โ ๏ธ Remote Status at time of failure:
โ
aws-s3: Success
โ google-drive: Failed
โธ๏ธ dropbox-backup: Not processed
.env
File: Contains sensitive credentials. Set permissions to chmod 600 .env
.chmod 700
on backup directory.If youโre upgrading from the R2-only version:
.env
- the new version is backward compatible./generate-rclone-base64.sh
to create RCLONE_CONFIG_BASE64
.env
fileโRCLONE_CONFIG_BASE64 contains invalid base64 dataโ (Docker Hub image only):
Thereโs a known issue with the Docker Hub image having stricter base64 validation than local builds. If your base64 works with local Docker Compose but fails with the Docker Hub image:
Workaround 1: Use local build instead
git clone https://github.com/nikhilbadyal/bitwarden-backup.git
cd bitwarden-backup
# Copy your .env file here
docker-compose up --build
Workaround 2: Regenerate base64 (may help)
base64 -w 0 < ~/.config/rclone/rclone.conf | tr -d '\n'
This issue is being investigated - the local build is currently more reliable.
No remotes found:
RCLONE_CONFIG_BASE64
is properly set./generate-rclone-base64.sh --test
Upload failures:
Permission errors:
chmod +x *.sh scripts/*.sh
Bitwarden unlock failures:
The script includes automatic retry logic for vault unlock failures. If youโre experiencing frequent unlock issues:
BW_UNLOCK_RETRIES=5
(default: 3)BW_UNLOCK_RETRY_DELAY=10
(default: 5 seconds)BW_PASSWORD
variable๐ Universal Architecture Support:
The Docker image is built for 2 main architectures and works universally:
Manual Installation (without Docker):
If running scripts directly on any system, install Bitwarden CLI via npm:
# Install Node.js and npm
sudo apt update && sudo apt install -y nodejs npm
# Install Bitwarden CLI globally
sudo npm install -g @bitwarden/cli
# Verify installation
bw --version
Read-only filesystem errors with Bitwarden CLI:
If you see errors like EROFS: read-only file system, open '/home/backupuser/.config/Bitwarden CLI/data.json'
:
This happens when the Docker container runs with a read-only filesystem but Bitwarden CLI needs to write configuration files. The Docker Compose file already handles this, but for manual Docker runs, add:
docker run --rm --env-file .env -e BITWARDENCLI_APPDATA_DIR=/tmp/bw_appdata nikhilbadyal/bitwarden-backup:latest
Using outdated Docker images:
Docker may use cached local images instead of pulling the latest from Docker Hub. To ensure youโre running the most recent version:
# Option 1: Use --pull always flag (recommended)
docker run --rm --env-file .env -e BITWARDENCLI_APPDATA_DIR=/tmp/bw_appdata --pull always nikhilbadyal/bitwarden-backup:latest
# Option 2: Manually pull first, then run
docker pull nikhilbadyal/bitwarden-backup:latest
docker run --rm --env-file .env -e BITWARDENCLI_APPDATA_DIR=/tmp/bw_appdata nikhilbadyal/bitwarden-backup:latest
Note: docker-compose
automatically handles this with pull_policy: always
in the compose file.
rclone ls remote:
to test connectivity--test
flag with the helper scriptContributions are welcome! Please feel free to submit pull requests or open issues for bugs and feature requests.
This project is open source. Please check the license file for details.