Knowledge Base

Preserving for the future: Shell scripts, AoC, and more

My Vaultwarden backup process

I have decided to turn my pre-production-worthy instance of Vaultwarden to a production-worthy one. That means I needed backups.

So I wrote my own quick-and-dirty shell script to handle that for me. The first part backups up the sqlite database in the proper fashion. The main script collects that bup database file, and the other relevant files for Vaultwarden, and tarballs them to the correct location!

files/2023/01/listings/bup-vw-db.sh (Source)

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
#!/bin/sh
# File: vm4:/home/vaultwarden/bup-vw-db.sh
# Location: vm4
# Author: bgstack15
# Startdate: 2023-01-02-2 16:54
# Title: Bup Vaultwarden database
# Project: bup-vw
# Purpose: Backup Vaultwarden database
# History:
# Usage: called by bup-vw.sh
# Reference:
#    https://github.com/dani-garcia/vaultwarden/wiki/General-%28not-docker%29
#    https://stackoverflow.com/questions/25675314/how-to-backup-sqlite-database/25684912#25684912
# Improve:
# Dependencies:
#    sqlite3
#    must run as root!
# Documentation: see bup-vw.sh
INDB=/home/vaultwarden/vw/bitwarden/db.sqlite3
test -z "${LOCALOUTDIR}" && LOCALOUTDIR=/home/vaultwarden/bup
test -z "${OUTFILE}" && OUTFILE="${LOCALOUTDIR}/vw.$( date "+%F" ).sq3"
echo ".backup ${OUTFILE}" | sqlite3 "${INDB}"
# the main script will tarball it with the relevant files
#gzip "${OUTFILE}"
chown vaultwarden:vaultwarden "${OUTFILE}"
echo "${OUTFILE}"
files/2023/01/listings/bup-vw.sh (Source)
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
#!/bin/sh
# File: vm4:/home/vaultwarden/bup-vw.sh
# Location: vm4
# Author: bgstack15
# Startdate: 2023-01-02-2 16:54
# Title: Bup Vaultwarden
# Project: bup-vw
# Purpose: Backup Vaultwarden contents
# History:
# Usage: called by cron: 70_vaultwarden_cron
# Reference:
#    https://github.com/dani-garcia/vaultwarden/wiki/General-%28not-docker%29
#    photorprism/bup-pp-db.sh
# Improve:
# Dependencies:
#    sudo access for user vaultwardern to run bup-vw-db.sh, /etc/sudoers.d/70_vaultwarden_bup_sudo
# Documentation:
#    README-vw-bup.md

workdir="$( dirname "$( readlink -f "${0}" 2>/dev/null )" 2>/dev/null || echo "${PWD}" )"
#echo "workdir=${workdir}"
test -z "${CONFFILE}" && CONFFILE="${workdir}/bup-vw.conf"
test -e "${CONFFILE}" && . "${CONFFILE}"
test -z "${LOGFILE}" && LOGFILE="/mnt/public/Support/Systems/vm4/var/log/vaultwarden/bup-vw.$( date "+%F" ).log"

_return() {
   return ${1}
}

main() {
   export OUTDIR=/mnt/public/Support/Systems/vm4/vw/vaultwarden
   export LOCALOUTDIR=/home/vaultwarden/bup
   export OUTFILE="${LOCALOUTDIR}/vw.$( date "+%F" ).sq3"
   export OUTTARBALL="${OUTDIR}/vw.$( date "+%F" ).tgz"
   # fail early if network mount is not there
   if ! test -w "$( dirname "${OUTFILE}" )" ;
   then
      echo "Fatal! Unable to write to directory for ${OUTTARBALL}: Aborted."
      exit 1
   fi
   # run the bup-vw-db.sh script, collect other things, make a tarball
   generated_file="$( sudo /home/vaultwarden/bup-vw-db.sh )"
   if ! test -f "${generated_file}" ;
   then
      echo "Fatal! Unable to find exported database file ${OUTFILE}: Aborted."
      exit 1
   fi
   relative_generated_file="bup/$( basename "${generated_file}" )"
   tar -zcf "${OUTTARBALL}" -C /home/vaultwarden vw/docker-compose.yml vw/.env vw/bitwarden "${relative_generated_file}"
   find "${OUTTARBALL}"
}

# Determine if this script was dot-sourced
sourced=0
if [ -n "$ZSH_EVAL_CONTEXT" ]; then 
  case $ZSH_EVAL_CONTEXT in *:file) sourced=1;; esac
elif [ -n "$KSH_VERSION" ]; then
  [ "$(cd $(dirname -- $0) && pwd -P)/$(basename -- $0)" != "$(cd $(dirname -- ${.sh.file}) && pwd -P)/$(basename -- ${.sh.file})" ] && sourced=1
elif [ -n "$BASH_VERSION" ]; then
  (return 0 2>/dev/null) && sourced=1 
else # All other shells: examine $0 for known shell binary filenames
  # Detects `sh` and `dash`; add additional shell filenames as needed.
  case ${0##*/} in sh|dash) sourced=1;; esac
fi

# So, if not dot-sourced, and this is run by cron, add logging
if test $sourced -eq 0;
then
   if echo " ${@} " | grep -q cron ;
   then 
      main 2>&1 | plecho | tee -a "${LOGFILE}"
      response=$?
      printf '\n' | tee -a "${LOGFILE}"
   else
      main
      response=$?
   fi
fi
_return ${response}

Cron entry

30 06  *  *  *  vaultwarden  /home/vaultwarden/bup-vw.sh cron 1>/dev/null 2>&1

I don't have any rotation processes set up yet, so I need to check in a few months and built a retention plan.

References

  1. https://github.com/dani-garcia/vaultwarden/wiki/General-%28not-docker%29

Comments