Files
media-server/vaultwarden_README.md
T

220 lines
10 KiB
Markdown

# Vaultwarden Backup & Restore Guide
> [!Note]
> The official backup and restore documentation for Vaultwarden is located on the [Vaultwarden GitHub Wiki](https://github.com/dani-garcia/vaultwarden/wiki/Backing-up-your-vault). The steps below are tailored specifically to our local Docker container setup and automated backup script.
---
# Script Architecture & Workflow
The custom backup script (`vaultwarden_backup.sh`) automates point-in-time snapshots of Vaultwarden while maintaining database integrity, supporting non-POSIX external backup drives (exFAT/NTFS), and providing real-time notification alerts.
```
+-------------------------------------------------------+
| Pre-flight Checks |
| (Mount point verify -> Data Dir check -> Docker running)
+---------------------------+---------------------------+
|
v
+-------------------------------------------------------+
| Step 1: Container DB Snapshot |
| `docker exec vaultwarden /vaultwarden backup` |
| (Generates db_YYYYMMDD_HHMMSS.sqlite3 safely in WAL) |
+---------------------------+---------------------------+
|
v
+-------------------------------------------------------+
| Step 2: Sync Snapshot DB |
| `rsync` snapshot -> `CURRENT_BACKUP_DIR/db.sqlite3` |
| (Deletes local temp snapshot file) |
+---------------------------+---------------------------+
|
v
+-------------------------------------------------------+
| Step 3: Sync Attachments & Data |
| `rsync` attachments, sends, RSA keys, config |
| (Excludes active live `db.sqlite3*`) |
+---------------------------+---------------------------+
|
v
+-------------------------------------------------------+
| Step 4: Update Path Pointer |
| Write `CURRENT_BACKUP_DIR` path -> `latest.txt` |
+---------------------------+---------------------------+
|
v
+-------------------------------------------------------+
| Step 5: Retention Cleanup |
| `find` & delete `backup_*` folders > 30 days |
+---------------------------+---------------------------+
|
v
+-------------------------------------------------------+
| ntfy Status Alert Sent |
+-------------------------------------------------------+
```
## Detailed Breakdown of Script Operations
### 1. Pre-flight Infrastructure Checks
Before modifying any data or making temporary local files, the script verifies three critical dependencies:
* **Mount Verification (`mountpoint -q`)**: Ensures `/mnt/5TB-Disk1` is an actively mounted filesystem. This prevents writing gigabytes of backup data to the local host root disk if the external drive gets disconnected.
* **Source Path Verification**: Confirms `/srv/docker/vaultwarden/data` exists.
* **Container State Check**: Verifies that the Vaultwarden Docker container is actively running using `docker ps`.
If any pre-flight test fails, the script sends an error payload to `ntfy` and exits immediately with status code `1`.
### 2. Database Snapshot Generation (Hot Backup)
Vaultwarden uses SQLite with Write-Ahead Logging (WAL). Directly copying `db.sqlite3` with standard filesystem tools (`cp`, `rsync`) while Vaultwarden is writing will produce a **corrupted database backup**.
To prevent corruption, the script invokes Vaultwarden's native backup CLI command inside the container:
```bash
docker exec vaultwarden /vaultwarden backup
```
* **How it works**: Vaultwarden issues an online SQLite backup API call that safely locks transactions briefly, creates a complete, uncorrupted database copy named `db_YYYYMMDD_HHMMSS.sqlite3` inside the host volume directory (`/srv/docker/vaultwarden/data`), and immediately releases the lock.
### 3. Isolated Target Snapshot & Normalization
Once generated, the script locates the newest `db_*.sqlite3` snapshot and copies it to the target backup folder as `db.sqlite3`:
* **Naming Standardization**: Renaming `db_YYYYMMDD_HHMMSS.sqlite3` to `db.sqlite3` at the destination creates a turnkey restoration layout matching Vaultwarden's default expectation.
* **Local Cleanup**: Immediately after copying, `rm -f "$LATEST_DB_BACKUP"` removes the temporary snapshot from host storage (`/srv/docker/vaultwarden/data/`) to prevent local disk exhaustion.
### 4. Asset Synchronization (`rsync`)
Attachments, user sends, encryption keys (`rsa_key*`), and server configurations (`config.json`) are synced using `rsync`:
```bash
rsync -av --no-owner --no-group --exclude='db.sqlite3*' /srv/docker/vaultwarden/data/ "$CURRENT_BACKUP_DIR/"
```
* **Flag Explanation**:
* `-a` (Archive mode): Preserves modification times, recursive directory structure, and file permissions.
* `--no-owner --no-group`: Prevents `rsync` from throwing permission warnings when backing up to filesystems (like exFAT or NTFS) that do not support POSIX user/group ownership mapping.
* `--exclude='db.sqlite3*'`: Prevents active WAL journal files (`db.sqlite3-wal`, `db.sqlite3-shm`) from being copied alongside the static `db.sqlite3` snapshot.
### 5. Filesystem-Agnostic "Latest" Pointer
On standard Linux filesystems (ext4/btrfs), scripts usually create a symbolic link (`ln -s`) to mark the latest backup folder. However, drives formatted as **exFAT, FAT32, or NTFS** reject symlinks with `Operation not permitted`.
To keep the script 100% compatible with any storage medium:
* The script writes the absolute path of the newest backup folder into a plain text file: `/mnt/5TB-Disk1/backup/services/vaultwarden/latest.txt`.
* Restores or external monitoring scripts can simply read `cat latest.txt` to discover the active backup location.
### 6. Retention Engine
Automatic backup rotation is performed using `find`:
```bash
find "$VAULTWARDEN_DESTINATION" -maxdepth 1 -type d -name "backup_*" -mtime +30 -exec rm -rf {} +
```
* `-maxdepth 1`: Restricts search depth to the top-level Vaultwarden backup directory to avoid recursing into subdirectories.
* `-name "backup_*"`: Filters strictly for directories generated by this script.
* `-mtime +30`: Identifies folders whose file modification time is strictly older than 30 days (720 hours).
* `-exec rm -rf {} +`: Deletes matching historical backup directories in a single batch operation.
### 7. Event Notifications via ntfy
All execution pathways (successes, container missing, unmounted drives, `rsync` failures) trigger an HTTP `POST` request to the defined `ntfy` server via `curl`, delivering real-time status updates directly to connected clients.
---
# Automated Backup Execution
## Cron Configuration
The backup script is executed automatically via root's crontab.
To view or edit the automated schedule:
```bash
sudo crontab -e
```
**Recommended Schedule (Every night at 2:30 AM):**
```cron
30 2 * * * /bin/bash /srv/docker/vaultwarden/vaultwarden_backup.sh >/dev/null 2>&1
```
## Manual Script Execution
To manually trigger a complete backup at any time:
```bash
sudo /srv/docker/vaultwarden/vaultwarden_backup.sh
```
---
# Manual Backup Procedure
If you need to perform a backup manually without using the script:
### 1. Generate Container Database Snapshot
```bash
sudo docker exec vaultwarden /vaultwarden backup
```
### 2. Copy Snapshot and Assets
```bash
# Define target directory
TARGET_DIR="/mnt/5TB-Disk1/backup/services/vaultwarden/manual_$(date +%Y-%m-%d_%H%M%S)"
mkdir -p "$TARGET_DIR"
# Locate and copy the generated DB snapshot
LATEST_DB=$(ls -t /srv/docker/vaultwarden/data/db_*.sqlite3 | head -n 1)
sudo rsync -av --no-owner --no-group "$LATEST_DB" "$TARGET_DIR/db.sqlite3"
# Remove the temporary snapshot from source
sudo rm -f "$LATEST_DB"
# Copy remaining assets (RSA keys, attachments, sends, config)
sudo rsync -av --no-owner --no-group --exclude='db.sqlite3*' /srv/docker/vaultwarden/data/ "$TARGET_DIR/"
```
---
# Restore Vaultwarden Procedure
> [!Caution]
> Always stop the Vaultwarden container before restoring files. Overwriting files on an active container can cause database locks or file corruption.
### Step 1: Identify Backup to Restore
Identify the backup directory path from `latest.txt` or list all available timestamped backups:
```bash
# View path to the most recent successful backup
cat /mnt/5TB-Disk1/backup/services/vaultwarden/latest.txt
# Or list all historical backup directories
ls -l /mnt/5TB-Disk1/backup/services/vaultwarden/
```
### Step 2: Stop Vaultwarden Container
```bash
sudo docker stop vaultwarden
# OR if using Docker Compose:
# cd /srv/docker/vaultwarden && sudo docker compose down
```
### Step 3: Restore Data Files
Rsync the database snapshot, attachments, sends, and RSA keys back to the host data directory.
> [!Note]
> Replace `/mnt/5TB-Disk1/backup/services/vaultwarden/backup_YYYY-MM-DD_HHMMSS` below with the target backup directory you wish to restore.
```bash
sudo rsync -av --delete /mnt/5TB-Disk1/backup/services/vaultwarden/backup_2026-10-03_101124/ /srv/docker/vaultwarden/data/
```
### Step 4: Verify Host File Permissions
Ensure the restored files match the container user's expected ownership (UID/GID `1000:1000` default):
```bash
sudo chown -R 1000:1000 /srv/docker/vaultwarden/data
```
### Step 5: Start Vaultwarden Container & Verify Logs
```bash
sudo docker start vaultwarden
# OR if using Docker Compose:
# cd /srv/docker/vaultwarden && sudo docker compose up -d
# Verify startup logs
sudo docker logs -f vaultwarden
```
---
## Authors and Acknowledgment
* **Vaultwarden Wiki**: https://github.com/dani-garcia/vaultwarden/wiki
* **Vaultwarden Repository**: https://github.com/dani-garcia/vaultwarden