#!/bin/bash # Vaultwarden restore — companion to backup.sh (kb#192). # # Restores a snapshot produced by backup.sh (db_*.sqlite3, config.json, # rsa_key*, attachments/, sends/) into a Vaultwarden data directory. # Defaults to the live container/data dir, but every target is overridable # via env vars so the same script can be pointed at a throwaway # container + scratch data dir for a dry-run restore test. # # Usage: # ./restore.sh /mnt/backups/vaultwarden/ # # Env overrides (defaults = live service): # CONTAINER=vaultwarden # DATA_DIR=/mnt/ssd/dbs/vw-data # # WARNING: this overwrites the target's live vault database. Never run # against the "vaultwarden" container / /mnt/ssd/dbs/vw-data unless you # intend a real disaster recovery — for testing, point CONTAINER/DATA_DIR # at a throwaway container and a scratch directory instead. set -euo pipefail CONTAINER="${CONTAINER:-vaultwarden}" DATA_DIR="${DATA_DIR:-/mnt/ssd/dbs/vw-data}" if [ $# -lt 1 ]; then echo "Usage: $0 " >&2 echo " e.g. $0 /mnt/backups/vaultwarden/20260728-0200" >&2 exit 1 fi SRC="$(realpath "$1")" DB_FILE="$(find "$SRC" -maxdepth 1 -name 'db_*.sqlite3' | head -n1)" if [ -z "$DB_FILE" ] || [ ! -f "$DB_FILE" ]; then echo "Error: no db_*.sqlite3 file found in $SRC" >&2 exit 1 fi echo "Restoring into '$CONTAINER' (data dir: $DATA_DIR) from $SRC" docker stop "$CONTAINER" > /dev/null mkdir -p "$DATA_DIR" cp "$DB_FILE" "$DATA_DIR/db.sqlite3" [ -f "$SRC/config.json" ] && cp "$SRC/config.json" "$DATA_DIR/" [ -f "$SRC/rsa_key.pem" ] && cp "$SRC"/rsa_key* "$DATA_DIR/" 2>/dev/null || true [ -d "$SRC/attachments" ] && rsync -a --delete "$SRC/attachments/" "$DATA_DIR/attachments/" [ -d "$SRC/sends" ] && rsync -a --delete "$SRC/sends/" "$DATA_DIR/sends/" docker start "$CONTAINER" > /dev/null echo "Waiting for Vaultwarden to come up..." for i in $(seq 1 30); do if docker exec "$CONTAINER" test -f /data/db.sqlite3 > /dev/null 2>&1; then break fi sleep 1 done echo "Verifying restored database..." docker exec "$CONTAINER" sh -c ' if command -v sqlite3 >/dev/null 2>&1; then echo "users row count: $(sqlite3 /data/db.sqlite3 "SELECT COUNT(*) FROM users;")" else echo "(sqlite3 CLI not present in image; file size check only)" ls -la /data/db.sqlite3 fi ' echo "Restore complete: $CONTAINER"