Skip to content

Instantly share code, notes, and snippets.

@rhysrhaven
Created May 20, 2015 01:05
Show Gist options
  • Save rhysrhaven/e77122b878df4f07c86d to your computer and use it in GitHub Desktop.
Save rhysrhaven/e77122b878df4f07c86d to your computer and use it in GitHub Desktop.
wrapper around duplicity in bash
#!/bin/bash -eu
## Complicity: A wrapper for Duplicity backup tool
## Configure, Load into /etc/cron.daily/, done.
## Version 1.4
# Base directory Duplicity backs up
base_dir='/'
# Excluded directories from the base directory. Like /proc. ** is wildcard
exclude_dirs=('**')
# Directories that will be included even though you excluded them
include_dirs=('')
# Remote SFTP directory to store encrypted backup files
# ssh://user[:password]@other.host[:port]/some_dir
remote_dir="ssh://user:password@host.domain/RELATIVEdir"
# URL of GPG Public Key to encrypt files with. wget grabs this URL. Is only downloaded the first time.
# By default this should be a pub key only. To enable restoring, load the private key into the keyring.
# gpg --homedir=/location_to_archive_dir/gpg --import private.key should work
key_url='http://host.domain/key'
# You can use the same archive directory with multiple instances of this script if you
# use separate names for each script.
backup_name='Backup1'
# Local storage directory, /tmp/complicity is default
archive_dir='/tmp/complicity'
# This script always does incremental backups. It will make a full backup if it has
# been ${cycle_time} since the last full backup. See Duplicity man page, TIME FORMATS.
cycle_time='7D'
key_id=''
filespec=''
err() {
echo -n "$1"
echo ", Exiting."
exit 1
}
# Sanity checks to make sure directorys are there
if [ ! -w "${archive_dir}" ]; then
if [ ! -d "${archive_dir}" ]; then
mkdir -p "${archive_dir}" || err "Failed to create archive directory"
else
err "Archive directory is not writable"
fi
fi
if [ ! -d "${archive_dir}/gpg" ]; then
mkdir -p "${archive_dir}/gpg"
chmod 700 "${archive_dir}/gpg"
fi
# Download and import backupkey
if [ ! -f "${archive_dir}/gpg/backupkey.gpg" ]; then
wget -q ${key_url} -O "${archive_dir}/gpg/backupkey.gpg" || err "Failed to download GPG key"
gpg -q --homedir "${archive_dir}/gpg" --import "${archive_dir}/gpg/backupkey.gpg"
fi
# Have to extract KeyID since duplicity uses the GPG keyring to select keys.
key_id="$(gpg --with-colons "${archive_dir}/gpg/backupkey.gpg" | grep -E ^pub | cut -d ":" -f5)"
# We use our own keyring, sets all parameters passed to duplicity.
gpg_params="--gpg-options \"--homedir=${archive_dir}/gpg --trust-model=always\""
duplicity_params="--archive-dir \"${archive_dir}\" --name \"${backup_name}\" --encrypt-key ${key_id} ${gpg_params} --asynchronous-upload --full-if-older-than ${cycle_time}"
# properly escape and generate arguments from the include and exclude arrays
if [ -n "${include_dirs}" ]; then
for dir in "${include_dirs[@]}"; do
filespec+="--include \"${dir}\" "
done
fi
if [ -n "${exclude_dirs}" ]; then
for dir in "${exclude_dirs[@]}"; do
filespec+="--exclude \"${dir}\" "
done
fi
# Deletes any but the most recent full backup and its associated incrementals.
#eval duplicity remove-all-but-n-full ${duplicity_params} ${remote_dir}
# If this script is called with no arguments, like from cron, it will initiate backup
# If you want to use duplicity to manipulate things, all arguments are passed directly.
if [ $# -gt 0 ]; then
case $1 in
backup)
eval duplicity incremental ${duplicity_params} ${filespec} ${base_dir} ${remote_dir}
;;
status)
eval duplicity collection-status ${duplicity_params} ${remote_dir}
;;
list)
eval duplicity list-current-files ${duplicity_params} ${remote_dir}
;;
remove-count)
[ $# -gt 1 ] && delete_count=${2} || delete_count='1'
eval duplicity remove-all-but-n-full --force ${delete_count} ${duplicity_params} ${remote_dir}
;;
remove-time)
[ $# -gt 1 ] && delete_time=${2} || delete_time=${cycle_time}
eval duplicity remove-older-than --force ${delete_time} ${duplicity_params} ${remote_dir}
;;
restore)
[ $# -gt 1 ] && restore_files="$(basename ${2}) --file-to-restore ${2}" || restore_files="${PWD}/${backup_name}"
eval duplicity restore ${duplicity_params} ${remote_dir} ${restore_files}
;;
esac
else
${0} backup
${0} remove-count
fi
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment