https://github.com/nikhilbadyal/bitwarden-backup
Bitwarden Vault Backup Script
https://github.com/nikhilbadyal/bitwarden-backup
backup backup-script bash bitwarden cloudflare rclone
Last synced: about 2 months ago
JSON representation
Bitwarden Vault Backup Script
- Host: GitHub
- URL: https://github.com/nikhilbadyal/bitwarden-backup
- Owner: nikhilbadyal
- Created: 2025-04-26T06:33:11.000Z (about 1 year ago)
- Default Branch: main
- Last Pushed: 2025-04-26T15:20:39.000Z (about 1 year ago)
- Last Synced: 2025-04-26T16:19:17.594Z (about 1 year ago)
- Topics: backup, backup-script, bash, bitwarden, cloudflare, rclone
- Language: Shell
- Homepage: http://www.nikhilbadyal.com/bitwarden-backup/
- Size: 22.5 KB
- Stars: 0
- Watchers: 1
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
Awesome Lists containing this project
README
# VaultSync

**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.**
## π Quick Start (TL;DR)
### 1. Generate Rclone Config
```bash
# 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
```
### 2. Minimal Configuration
Create a `.env` file with these **5 required variables**:
```bash
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
```
### Optional: Organization Export Support
To also backup organization vaults, add these optional variables:
```bash
# Enable organization exports
EXPORT_ORGANIZATIONS=true
# Optional: list organization IDs to export (comma-separated, no spaces)
# If omitted, all accessible organizations are auto-discovered and exported
# Get org IDs manually with: bw list organizations --session $BW_SESSION
BW_ORGANIZATION_IDS=12345678-1234-1234-1234-123456789012,87654321-4321-4321-4321-210987654321
```
**π Backup Format Compatibility:**
- **Personal-only backups** (default): Uses standard Bitwarden export format
- **Organization backups**: Uses consolidated format when organizations are exported
- **Restore script**: Automatically detects and handles both formats
### 3. Run Backup
**β‘ Fastest (No cloning required):**
```bash
docker run --rm --env-file .env --pull always \
-e BITWARDENCLI_APPDATA_DIR=/tmp/bw_appdata \
nikhilbadyal/bitwarden-backup:latest
```
**Or with Docker Compose:**
```bash
git clone https://github.com/nikhilbadyal/bitwarden-backup.git
cd bitwarden-backup
# Copy your .env file here
docker-compose up --build --no-cache
# Added --no-cache to ensure latest image is always pulled.
```
**Or with scripts:**
```bash
./setup-rclone.sh && ./scripts/backup.sh
```
That's it! Your vault will be backed up to all configured remotes with encryption and compression.
**π₯οΈ Want a Web UI?** See the [Management Interface](#-management-interface) section below for the complete web dashboard setup!
## π Management Interface
This project includes both a **modern web UI** and **REST API** for managing your Bitwarden backups through an intuitive interface or programmatic access.
### Quick Setup
**π₯οΈ Web UI + API (Recommended):**
```bash
# Start everything (UI + API + Redis + Nginx)
docker-compose -f docker-compose.full.yml up -d --build --no-cache
# Added --build --no-cache to ensure latest image is always pulled and rebuilt.
# Access the complete application
# - Web UI: http://localhost:80
# - API Docs: http://localhost:80/api/v1/docs
```
**π API Only:**
```bash
# Run the API with Docker
./run-api.sh
# Access the API
# - API Root: http://localhost:5050/
# - Documentation: http://localhost:5050/api/v1/docs
```
For detailed API setup instructions, Docker configuration, and usage examples, see:
**π [API.md](API.md) - Complete API Setup Guide**
The API provides endpoints for:
- π System health and monitoring
- π Backup file management and listing
- βοΈ Remote storage provider management
- π Advanced search and filtering capabilities
## π₯οΈ Web UI Dashboard
This project includes a **modern React-based web interface** for managing your Bitwarden backups through an intuitive dashboard.
### β¨ UI Features
- **π Real-time System Health** - Monitor API status, Redis connectivity, and Rclone availability
- **βοΈ Remote Management** - View and manage all configured cloud storage remotes
- **π Backup Browser** - Browse backup history with detailed metadata and logs
- **π§ Rclone Config Tool** - Convert and manage rclone configurations through the web interface
- **π Secure Authentication** - Token-based authentication with session management
- **π± Responsive Design** - Works on desktop, tablet, and mobile devices
### π Quick UI Setup
**Option 1: Full Stack (Recommended)**
```bash
# Start everything (API + UI + Redis + Nginx)
docker-compose -f docker-compose.full.yml up -d
# Access the complete application
# - Web UI: http://localhost:80
# - API: http://localhost:80/api (proxied through Nginx)
```
**Option 2: Manual Development Setup**
```bash
# 1. Start the API backend
uvicorn api.main:app --host 0.0.0.0 --port 5050
# 2. In another terminal, start the UI
cd ui
npm install
npm start
# Access:
# - UI: http://localhost:3000
# - API: http://localhost:5050
```
**Option 3: Docker Compose (Separate Services)**
```bash
# Start API only
docker-compose -f docker-compose.api.yml up -d --build --no-cache
# Added --build --no-cache to ensure latest image is always pulled and rebuilt.
# Start UI only (in another terminal)
docker-compose -f docker-compose.ui.yml up -d --build --no-cache
# Added --build --no-cache to ensure latest image is always pulled and rebuilt.
# Access:
# - UI: http://localhost:3000
# - API: http://localhost:5050
```
### π§ UI Configuration
The UI requires these environment variables for proper API connectivity:
| Variable | Description | Default | Docker Example |
|:--------------------|:----------------|:------------------------|:--------------------------|
| `VITE_API_BASE_URL` | API backend URL | `http://localhost:5050` | `/api` (with Nginx proxy) |
**For development:**
```bash
# In ui/.env file
VITE_API_BASE_URL=http://localhost:5050
```
**For Docker with Nginx (recommended):**
The full Docker Compose setup automatically configures Nginx to:
- Serve the UI on port 80
- Proxy `/api/*` requests to the backend
- Handle CORS and routing properly
### π¨ UI Development
The web interface is built with modern technologies:
- **Frontend**: React 19 + Vite
- **UI Framework**: Material-UI (MUI) v7
- **Routing**: React Router v7
- **Build Tool**: Vite (fast HMR and builds)
- **Styling**: Emotion + MUI theming
**Development Commands:**
```bash
cd ui
# Install dependencies
npm install
# Start development server (with hot reload)
npm start # or npm run dev
# Build for production
npm run build
# Preview production build
npm run preview
# Lint and format code
npm run lint
npm run format
```
### π Authentication
The UI uses token-based authentication:
1. **First Visit**: You'll be redirected to the login page
2. **Enter API Token**: Use the same `API_TOKEN` from your `.env` file
3. **Persistent Session**: Token is stored in localStorage for convenience
4. **Logout**: Click the logout button to clear the session
### π± UI Screenshots & Features
**System Health Dashboard:**
- Real-time component status (Redis, Rclone)
- System uptime and version information
- One-click cache clearing
- Color-coded health indicators
**Remote Storage Management:**
- View all configured rclone remotes
- Test remote connectivity
- Storage usage and configuration details
**Backup Browser:**
- Chronological backup listing
- Detailed backup metadata (size, date, remote)
- Download and restoration options
- Search and filtering capabilities
**Rclone Configuration:**
- Web-based config converter
- Base64 encoding/decoding
- Configuration validation
### π UI Development Notes
**Full Disclosure**: The web interface was "vibe coded" due to limited frontend expertise - it's fully functional but could use some design polish! π
**Contributing**: If you're a frontend developer and want to contribute design improvements, we'd be incredibly grateful! The codebase is contribution-friendly and uses modern React patterns.
**Known Limitations**:
- Basic responsive design (works but could be enhanced)
- Minimal animations and transitions
---
## π Detailed Documentation
### What This Does
This repository provides a **"configure once, forget forever"** solution for Bitwarden vault backups:
1. `setup-rclone.sh`: Configures rclone from a base64-encoded configuration to support **ANY rclone-compatible storage service**
2. `backup.sh`: Performs automated backup, validates, compresses, encrypts, and uploads to **ALL configured remotes** simultaneously
3. `generate-rclone-base64.sh`: Helper script to generate base64-encoded rclone configurations
4. `restore-backup.sh`: Decrypt and restore backup files back to plain JSON format
### Prerequisites
- A Bitwarden account with API access enabled (works with both official Bitwarden and self-hosted servers)
- Docker installed (recommended) OR `bw`, `jq`, `gzip`, `openssl`, `rclone` CLI tools installed
- Access to one or more cloud storage services with rclone support
### Alternative Installation Methods
**π§ Full Setup (Clone Repository):**
```bash
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
```
## π§ Configuration
### Required Environment Variables
| 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...` |
### API Configuration (Required for API service)
| 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` |
| `API_ALLOW_BACKUP_DECRYPTION` | Enables sensitive download/restore operations | `false` |
| `API_ALLOWED_HOSTS` | Trusted host allow-list (comma-separated) | `localhost,127.0.0.1,api.example.com` |
| `API_CORS_ORIGINS` | Explicit CORS origins (comma-separated) | `http://localhost,http://localhost:3000` |
| `API_CORS_ALLOW_CREDENTIALS` | CORS credential support (`true/false`) | `true` |
| `API_CORS_ALLOW_METHODS` | Explicit CORS methods (comma-separated) | `GET,POST,PUT,DELETE,OPTIONS` |
| `API_CORS_ALLOW_HEADERS` | Explicit CORS request headers (comma-separated) | `Authorization,Content-Type,Accept` |
| `API_CORS_EXPOSE_HEADERS` | CORS response headers exposed to browser (comma-separated) | `X-Request-ID,X-Response-Time,X-API-Version` |
| `API_STREAM_TOKEN_TTL_SECONDS` | Short-lived SSE stream token TTL in seconds | `120` |
### Self-Hosted Bitwarden Support
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:**
```bash
# 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:**
- Leave these variables empty or unset to use the official Bitwarden service
- `BW_SERVER` is the recommended approach for most self-hosted installations
- Individual service URLs (`BW_API`, `BW_IDENTITY`, etc.) override `BW_SERVER` if both are set
- All existing backup functionality works identically with self-hosted servers
### Export Configuration Variables
| Variable | Description | Default | Example |
|:-----------------------|:--------------------------------------------------------------------------|:--------|:----------------------------|
| `EXPORT_PERSONAL` | Export personal vault | `true` | `true` or `false` |
| `EXPORT_ORGANIZATIONS` | Export organization vaults | `false` | `true` or `false` |
| `BW_ORGANIZATION_IDS` | Optional org IDs to export; empty means auto-discover all accessible orgs | None | `12345678-...,87654321-...` |
| `EXPORT_ORGANIZATIONS_FAIL_FAST` | Fail immediately when any org export fails (`true`) or continue with partial success (`false`) | `false` | `true` or `false` |
**Format Details:**
- When `EXPORT_ORGANIZATIONS=false` (default): Uses standard Bitwarden export format
- When `EXPORT_ORGANIZATIONS=true`: Uses consolidated format with `personal` and `organizations` sections
- When `EXPORT_ORGANIZATIONS_FAIL_FAST=false` (default): Organization export failures are logged and remaining orgs continue
- Restore script automatically detects format and provides extraction options
### Optional Variables (Advanced)
Click to expand optional configuration
| Variable | Description | Default |
|:-------------------------|:-------------------------------------------|:-------------------|
| `BACKUP_DIR` | Temporary directory for backup files | `/tmp/bw_backup` |
| `BACKUP_PATH` | Remote path/bucket for storing backups | `bitwarden-backup` |
| `MIN_BACKUP_SIZE` | Minimum backup size in bytes | `1024` |
| `COMPRESSION_LEVEL` | Gzip compression level (1-9) | `9` |
| `RETENTION_COUNT` | Number of backups to keep per remote | `240` |
| `BW_UNLOCK_RETRIES` | Number of vault unlock attempts | `3` |
| `BW_UNLOCK_RETRY_DELAY` | Seconds to wait between retry attempts | `5` |
| `PBKDF2_ITERATIONS` | PBKDF2 iterations for encryption | `600000` |
| `BITWARDEN_SYNC_TIMEOUT` | Bitwarden sync timeout in seconds | `60` |
| `PARALLEL_THRESHOLD` | Min remotes needed for parallel processing | `3` |
| `MAX_PARALLEL_JOBS` | Maximum parallel jobs for pruning | `4` |
| `APPRISE_URLS` | Notification URLs (space-separated) | None |
| `BW_SERVER` | Self-hosted Bitwarden server URL | None |
| `BW_WEB_VAULT` | Custom web vault URL (advanced) | None |
| `BW_API` | Custom API URL (advanced) | None |
| `BW_IDENTITY` | Custom identity URL (advanced) | None |
| `BW_ICONS` | Custom icons service URL (advanced) | None |
| `BW_NOTIFICATIONS` | Custom notifications URL (advanced) | None |
| `BW_EVENTS` | Custom events URL (advanced) | None |
| `BW_KEY_CONNECTOR` | Key Connector URL (for organizations) | None |
**Important Notes:**
- `BACKUP_PATH`: For S3-compatible services, this becomes the bucket name. For other services, this is the folder path where backups are stored.
- `MIN_BACKUP_SIZE`: Backups smaller than this are considered invalid and the script will exit with an error.
- `PBKDF2_ITERATIONS`: Changes only affect new backups. Restore script automatically detects iteration count for backward compatibility.
- All scripts automatically load variables from `.env` file if it exists in the project root.
### π What You Get (Features)
**Backup Features:**
- **Multi-Remote Support**: Backup to multiple cloud services simultaneously
- **Strong Encryption**: AES-256-CBC encryption with PBKDF2 (configurable, default 600,000 iterations) using your password
- **Zero-Disk Security**: Uses secure pipe-based processing - unencrypted vault data never touches disk
- **Smart Change Detection**: Only uploads when vault actually changes (SHA256 comparison)
- **Detailed Notifications**: Per-remote status in final notifications (success/failed/up-to-date)
- **Automatic Retries**: Handles network issues and API rate limiting for Bitwarden unlock
- **Secure Cleanup**: Logs out of Bitwarden and cleans temporary files
- **Cross-platform**: Supports Linux and macOS (different SHA256 utilities)
**Restore Features:**
- **Multi-Source Restore**: Decrypt local files or download from any remote
- **Backup Browsing**: List and browse backups across all storage services
- **Verification Pipeline**: Multi-stage validation (decryption β decompression β JSON validation)
---
## ποΈ Detailed Documentation
### Supported Cloud Storage Services
This backup solution supports **ALL rclone-compatible storage services**, including:
**Object Storage:**
- Amazon S3, Google Cloud Storage, Azure Blob Storage
- Cloudflare R2, Backblaze B2, Wasabi, MinIO
- IBM Cloud Object Storage, Oracle Cloud Storage
**Consumer Cloud Storage:**
- Google Drive, Dropbox, OneDrive, Box
- pCloud, Mega, Yandex Disk, Mail.ru Cloud
**Enterprise Storage:**
- SFTP, FTP, WebDAV, HTTP
- Swift (OpenStack), Ceph, QingStor
**And many more!** See the [rclone documentation](https://rclone.org/) for the complete list.
## Example Multi-Remote Setup
Your rclone configuration can include multiple remotes:
```ini
[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:
1. Detect all 4 remotes
2. Upload your backup to ALL of them
3. Maintain separate retention policies for each
4. Track changes independently per remote
### Usage Examples
Click to expand usage examples
**Manual Backup (Scripts):**
```bash
./setup-rclone.sh && ./scripts/backup.sh
```
**Automated with Cron:**
```crontab
# Daily backup at 3:00 AM
0 3 * * * /path/to/bitwarden-backup/setup-rclone.sh && /path/to/bitwarden-backup/scripts/backup.sh >> /var/log/bitwarden_backup.log 2>&1
```
**Docker Compose:**
```bash
docker-compose up --build
```
**Automated Docker Compose with Cron:**
For automated backups using Docker Compose with cron scheduling, you have several options:
Add this to your host system's crontab:
```crontab
# Daily backup at 3:00 AM using Docker Compose
0 3 * * * cd /path/to/bitwarden-backup && docker-compose up --build --force-recreate >> /var/log/bitwarden_backup.log 2>&1
# Weekly backup (Sundays at 2:00 AM)
0 2 * * 0 cd /path/to/bitwarden-backup && docker-compose up --build --force-recreate >> /var/log/bitwarden_backup.log 2>&1
# Multiple daily backups (every 6 hours)
0 */6 * * * cd /path/to/bitwarden-backup && docker-compose up --build --force-recreate >> /var/log/bitwarden_backup.log 2>&1
```
**Cron Schedule Examples:**
```crontab
# Every day at 3:00 AM
0 3 * * *
# Every 12 hours (noon and midnight)
0 */12 * * *
# Every Monday at 2:00 AM
0 2 * * 1
# Every 1st day of the month at 1:00 AM
0 1 1 * *
# Every 15 minutes (for testing)
*/15 * * * *
# Multiple times per day (6 AM, 2 PM, 10 PM)
0 6,14,22 * * *
```
**GitHub Actions Automation:**
1. Fork this repository
2. Add your environment variables as a repository secret named `BITWARDEN_BACKUP_ENV`
3. Automatic daily backups run at 2:00 AM UTC with free GitHub infrastructure
4. Includes pre-commit checks (shellcheck) and log artifact storage
## π Backup Restoration
The `restore-backup.sh` script allows you to decrypt and restore your encrypted backups back to plain JSON format.
### Quick Restore Examples
```bash
# 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
```
### Restore Options
| 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` |
### Restoration Process
1. **π Validation** - Checks file existence and encryption password
2. **π Decryption** - Decrypts using AES-256-CBC with your password
3. **π¦ Decompression** - Extracts gzip compressed data
4. **β
JSON Validation** - Ensures valid Bitwarden vault format
5. **πΎ Secure Save** - Saves with secure file permissions (600)
6. **π§Ή Cleanup** - Removes temporary files
### Security Notes
- Restored JSON files contain **unencrypted vault data** - handle with care
- Files are created with secure permissions (owner read/write only)
- Temporary files are automatically cleaned up
- **Delete restored files** when no longer needed
- The same `ENCRYPTION_PASSWORD` from backups is required
### Advanced Features
Click to expand advanced features
**Detailed Backup Features:**
- **Multi-Remote Support**: Backup to multiple cloud storage services simultaneously (S3, Google Drive, Dropbox, OneDrive, Cloudflare R2, and 40+ others supported by rclone)
- **Base64 Configuration**: Accepts rclone config as base64 to avoid typing errors and enable easy deployment
- **Isolated Configuration**: Uses project-specific rclone config to avoid interfering with your global rclone setup
- **Multi-Stage Validation**: JSON validation, size checks, compression verification, and encryption testing
- **Encryption Verification**: Tests decryption and validates gzip format before upload
- **Intelligent Change Detection**: SHA256 hashing to avoid unnecessary uploads when vault hasn't changed
- **Independent Retention Management**: Per-remote retention policies based on configurable count
- **Optional Apprise Notifications**: Success and failure notifications
- **Automatic Retry Logic**: Handles transient network issues and API rate limiting for Bitwarden vault unlock
- **Robust Error Handling**: Individual remote failures don't stop the entire process
- **Secure Cleanup**: Logs out of Bitwarden and unsets sensitive environment variables
**Detailed Restore Features:**
- **Multi-Source Restore**: Decrypt local files or download directly from any configured remote
- **Backup Browsing**: List and browse available backups across all your cloud storage services
- **Verification Pipeline**: Multi-stage validation (decryption β decompression β JSON validation)
- **Secure Processing**: Temporary files with secure permissions and automatic cleanup
- **Flexible Output**: Custom output file names and locations
- **Download-Only Mode**: Download encrypted backups without decrypting (for manual processing)
## Logging and Monitoring
### Exit Codes
| Code | 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 |
### Notifications
Configure [Apprise](https://github.com/caronc/apprise) for notifications:
```bash
# Multiple notification services
APPRISE_URLS="mailto://user@example.com 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
```
## Security Considerations
- **`.env` File**: Contains sensitive credentials. Set permissions to `chmod 600 .env`.
- **Backup Directory**: Set secure permissions `chmod 700` on backup directory.
- **Encryption Password**: Store securely and separately from backups. **Losing this password means losing access to your backups.**
- **Rclone Configuration**: Contains cloud storage credentials. The base64 encoding is for convenience, not security.
- **Multi-Remote Security**: Each remote should have appropriate access controls and encryption.
## Migration from R2-Only Version
If you're upgrading from the R2-only version:
1. **Keep your existing `.env`** - the new version is backward compatible
2. **Generate rclone config**: Use `./generate-rclone-base64.sh` to create `RCLONE_CONFIG_BASE64`
3. **Add the new variable** to your `.env` file
4. **Optional**: Remove old R2-specific variables (they're ignored now)
5. **Run the backup** - it will work with your existing R2 setup plus any new remotes
## Troubleshooting
### Common Issues
**"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**
```bash
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)**
```bash
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:**
- Ensure `RCLONE_CONFIG_BASE64` is properly set
- Test your config: `./generate-rclone-base64.sh --test`
**Upload failures:**
- Check remote credentials and permissions
- Verify network connectivity
- Review rclone configuration syntax
**Permission errors:**
- Ensure scripts are executable: `chmod +x *.sh scripts/*.sh`
- Check backup directory permissions
**Bitwarden unlock failures:**
The script includes automatic retry logic for vault unlock failures. If you're experiencing frequent unlock issues:
- **Increase retry attempts**: Set `BW_UNLOCK_RETRIES=5` (default: 3)
- **Increase retry delay**: Set `BW_UNLOCK_RETRY_DELAY=10` (default: 5 seconds)
- **Check network connectivity** to Bitwarden servers
- **Verify your master password** is correct in the `BW_PASSWORD` variable
- **Check for API rate limiting** if running frequent backups
**π Universal Architecture Support:**
The Docker image is built for **2 main architectures** and works universally:
- β
**linux/amd64** (Intel/AMD 64-bit: Most desktops, servers, cloud instances)
- β
**linux/arm64** (ARM 64-bit: Apple Silicon, Raspberry Pi 4/5, AWS Graviton)
**Manual Installation (without Docker):**
If running scripts directly on any system, install Bitwarden CLI via npm:
```bash
# 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:
```bash
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:
```bash
# 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.
### Getting Help
1. **Check logs**: Review script output for specific error messages
2. **Test rclone**: Use `rclone ls remote:` to test connectivity
3. **Validate config**: Use the `--test` flag with the helper script
4. **Check dependencies**: Ensure all required tools are installed
## Contributing
Contributions are welcome! Please feel free to submit pull requests or open issues for bugs and feature requests.
## License
This project is open source. Please check the license file for details.