Created
February 28, 2024 17:58
-
-
Save AlexTMjugador/bbaab84e630986b75d534a5cb6deab1c to your computer and use it in GitHub Desktop.
Backup scripts for personal Bitwarden vaults, storing the results to a password-encrypted LUKS file volume. Perfect for simple and secure off-site backups of Bitwarden vaults where a little human interaction for providing key material is warranted.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/bin/sh -eu | |
# Backs up a personal Bitwarden vault to an encrypted LUKS file store. | |
. ./bw-common | |
echo '> Exporting personal vault to JSON file...' | |
bw export --format json --output "$WORKDIR"/backup/export.json | |
echo '> Exporting attachments...' | |
IFS="$(printf '\t')" | |
bw list items | \ | |
jq -r '.[] | | |
select(.attachments) | | |
[.id, foreach .attachments[] as $attachment (null; $attachment.id + "," + $attachment.fileName)] | | |
@tsv' | \ | |
while read -r item_with_attachments; do | |
item_id="$(echo "$item_with_attachments" | cut -d "$IFS" -f1 -)" | |
for attachment in $(echo "$item_with_attachments" | cut -d "$IFS" -f2- -); do | |
attachment_id="${attachment%%,*}" | |
attachment_file_name="${attachment#*,}" | |
echo "> Exporting attachment $attachment_id ($attachment_file_name) for item $item_id..." | |
mkdir -p "$WORKDIR/backup/attachments/$item_id" | |
bw get attachment "$attachment_id" \ | |
--itemid "$item_id" \ | |
--output "$WORKDIR/backup/attachments/$item_id/$attachment_file_name" | |
done | |
done | |
echo 'Backup done, have a nice day!' |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# shellcheck shell=sh | |
# Required non-POSIX binaries: | |
# - cryptsetup | |
# - sudo | |
# - fallocate | |
# - curl | |
# - jq | |
# - mkfs.ext4 | |
# - funzip | |
# - GNU find (i.e., with -delete option) | |
# The following three constants are parameters that can be changed | |
readonly SERVER='https://vault.bitwarden.eu' | |
readonly BW_CLI_VERSION='2024.2.0' | |
readonly BACKUP_STORE_SIZE=128M | |
WORKDIR="$(mktemp -d -t bitwarden.XXX)" | |
readonly WORKDIR | |
trap ' | |
if [ -d "$WORKDIR/backup" ]; then | |
sudo umount "$WORKDIR/backup" || true | |
sudo cryptsetup luksClose bw_backup || true | |
fi | |
rm -rf "$WORKDIR/appdata" | |
find "$WORKDIR" -delete | |
sync | |
' EXIT INT TERM | |
export PATH="$WORKDIR:$PATH" | |
export BITWARDENCLI_APPDATA_DIR="$WORKDIR/appdata" | |
if ! [ -f 'backup' ]; then | |
echo "> Creating encrypted backup store (size: $BACKUP_STORE_SIZE)..." | |
fallocate -l "$BACKUP_STORE_SIZE" backup | |
sudo cryptsetup -y luksFormat backup | |
created_backup_file=1 | |
else | |
created_backup_file= | |
fi | |
echo '> Opening encrypted backup store...' | |
sudo cryptsetup luksOpen backup bw_backup | |
if [ -n "$created_backup_file" ]; then | |
sudo mkfs -t ext4 /dev/mapper/bw_backup | |
fi | |
echo '> Mounting encrypted backup store...' | |
mkdir -p "$WORKDIR/backup" | |
sudo mount /dev/mapper/bw_backup "$WORKDIR/backup" | |
if [ -n "$created_backup_file" ]; then | |
sudo chmod ugo+rwx "$WORKDIR/backup" | |
fi | |
echo '> Downloading Bitwarden CLI...' | |
curl -L "https://github.com/bitwarden/clients/releases/download/cli-v${BW_CLI_VERSION}/bw-linux-${BW_CLI_VERSION}.zip" | \ | |
funzip > "$WORKDIR/bw" | |
chmod +x "$WORKDIR/bw" | |
echo '> Logging in to Bitwarden...' | |
bw config server "$SERVER" | |
BW_SESSION=$(bw login --raw) | |
export BW_SESSION |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/bin/sh -eu | |
# Mounts a personal Bitwarden vault backup at an encrypted LUKS file store, and | |
# drops to a shell in the mount point for interactive manipulation. | |
. ./bw-common | |
CWD="$PWD" | |
cd "$WORKDIR"/backup | |
$SHELL | |
cd "$CWD" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/bin/sh -eu | |
# Restores a personal Bitwarden vault backup from an encrypted LUKS file store. | |
. ./bw-common | |
echo '> Importing personal vault from JSON file...' | |
bw import bitwardenjson "$WORKDIR"/backup/export.json | |
# Importing attachments doesn't work reliably because item IDs can be | |
# randomized on import, so the following won't be able to add attachments | |
# to unexisting item IDs: | |
# echo '> Importing attachments...' | |
# for item_path in "$WORKDIR"/backup/attachments/*; do | |
# for attachment_path in "$item_path"/*; do | |
# item_id="${item_path#"$WORKDIR"/backup/attachments/}" | |
# bw create attachment --itemid "$item_id" --file "$attachment_path" | |
# done | |
# done | |
echo 'Restore done, remember to sync any logged-in clients. Have a nice day!' |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment