Skip to content

Instantly share code, notes, and snippets.

@theobjectivedad
Created June 17, 2025 15:48
Show Gist options
  • Save theobjectivedad/ac8496b5a168527d1894498ba9f61971 to your computer and use it in GitHub Desktop.
Save theobjectivedad/ac8496b5a168527d1894498ba9f61971 to your computer and use it in GitHub Desktop.
Bitwarden Backup Script
#!/bin/bash
# Copyright (c) 2025, The Objective Dad
#
# Permission is hereby granted, free of charge, to any person obtaining a copy of this software and
# associated documentation files (the “Software”), to deal in the Software without restriction,
# including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense,
# and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so,
# subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in all copies or substantial
# portions of the Software.
#
# THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT
# LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
# IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
# SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#
#
# BitWarden vault backup script for the Linux CLI
#
# Setup:
#
# 1. Install the Bitwarden CLI tools
# 2. Install GnuPG
# 3. Ensure you are logged into BitWarden, you only need to do this once as the script will prompt to unlock
# 4. Run `bitwarden_backup.sh`
#
# (optional) Add the following to your ~/.bashrc / ~/.zshrc to auto-trigger
# Bitwarden backup every 7 days. Be sure to replace `FULL_PATH_TO_BITWARDEN_BACKUP_SCRIPT`
# with the actual full path to the script.
#
# ```shell
# BITWARDEN_BACKUP_TIMESTAMP="${HOME}/.bitwarden_last_backup"
# BITWARDEN_BACKUP_SCRIPT="FULL_PATH_TO_BITWARDEN_BACKUP_SCRIPT"
# BACKUP_INTERVAL_DAYS=7
# if [ -x "$BITWARDEN_BACKUP_SCRIPT" ]; then
# if [ ! -f "$BITWARDEN_BACKUP_TIMESTAMP" ] || \
# [ $(( ($(date +%s) - $(stat -c %Y "$BITWARDEN_BACKUP_TIMESTAMP")) / 86400 )) -ge $BACKUP_INTERVAL_DAYS ]; then
# echo "[Bitwarden Backup] It has been 7+ days since your last backup."
# echo "Starting backup now..."
# if "$BITWARDEN_BACKUP_SCRIPT"; then
# touch "$BITWARDEN_BACKUP_TIMESTAMP"
# echo "[Bitwarden Backup] Backup completed successfully."
# else
# echo "[Bitwarden Backup] Backup failed. It will retry next login."
# fi
# fi
# fi
# ```
set -euo pipefail
# === Configuration ===
BACKUP_DIR=${HOME}/bw_backups_local
GPG_CIPHER="AES256" # Use strongest available symmetric encryption algorithm
GPG_S2K_MODE="3" # Iterated and salted
GPG_S2K_DIGEST="SHA512" # Use strongest available hash
GPG_S2K_COUNT="65011712" # High iteration count
USE_UTC=true
FILENAME_PREFIX="BitWarden_"
REMOTE_SYNC_FOLDER=${HOME}/secure_remote
# === Functions ===
# Clean up session securely even if script exits early
cleanup() {
if [[ -n "${BW_SESSION:-}" ]]; then
unset BW_SESSION
bw lock >/dev/null 2>&1 || true
fi
}
trap cleanup EXIT
# Ensure backup directories
mkdir -p "$BACKUP_DIR"
mkdir -p "$REMOTE_SYNC_FOLDER"
# Generate timestamp in ISO8601 format
if [[ "$USE_UTC" == true ]]; then
TIMESTAMP=$(date -u +%Y%m%dT%H%M%S)
else
TIMESTAMP=$(date +%Y%m%dT%H%M%S)
fi
OUTPUT_FILE="${BACKUP_DIR}/${FILENAME_PREFIX}${TIMESTAMP}.json.gpg"
# === Main ===
# Unlock Bitwarden and get session token
echo "[INFO] Unlocking Bitwarden vault..."
export BW_SESSION=$(bw unlock --raw)
# Export vault in plaintext JSON and encrypt it using GPG
echo "[INFO] Exporting vault and encrypting to: $OUTPUT_FILE"
bw --raw --session "$BW_SESSION" export --format json | \
gpg --symmetric \
--cipher-algo "$GPG_CIPHER" \
--s2k-mode "$GPG_S2K_MODE" \
--s2k-digest-algo "$GPG_S2K_DIGEST" \
--s2k-count "$GPG_S2K_COUNT" \
--armor \
--output "$OUTPUT_FILE"
echo "[INFO] Copying backup to remote sync folder"
cp "${OUTPUT_FILE}" "${REMOTE_SYNC_FOLDER}"
echo "[SUCCESS] Bitwarden vault encrypted backup complete."
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment