Skip to content

Instantly share code, notes, and snippets.

@ParanoidAndroid77
Forked from anonymous/bash_profile.example
Last active January 4, 2016 21:39
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save ParanoidAndroid77/8681990 to your computer and use it in GitHub Desktop.
Save ParanoidAndroid77/8681990 to your computer and use it in GitHub Desktop.
This is the debugged version of SPARTACUS - the Slightly PARanoid bACkUp Script. In my foolishness, I forgot to debug thoroughly and several errors escaped me in the original, anonymous gist. This is the updated version. I might open a git repo for this, if there's sufficient interest and if I can get the remaining kinks worked out.
# backup configuration variables fot SPARTACUS #
# this is a simple shell script that will be
# sourced by spartacus.sh in order to
# configure certain user-set parameters,
# which are defined below.
# this file should be placed in the
# /etc folder as /etc/spartacus.cfg,
# so spartacus will be able to find it.
# system profile (/ assumed)
SYSTEMDISKS=()
# home profile
HOMEDISKS=()
HOMEDIR=/home/<user>
# docs profile
DOCSDISKS=()
DOCSDIR=/home/<user>/docs
# keyfile to be used to encrypt and decrypt
# backups, in addition to passphrase provided
# at creation. Note that in this case, there
# is no benefit to assigning a binary
# keyfile to a disk already encrypted with
# a simple passphrase, so the easiest
# solution is to create a keyfile
# that has only a single line consisting
# of your original passphrase.
SPARTACUS_KEYFILE='/usr/local/bin/backup.keyfile'
# set backup time parameters.
# TIME is the format used by the date command
# to name your snapshots with (see man date for more
# information on the format options for date).
# INT is the interval to use to determine what the last
# backup timestamp was. Set this to either week, day,
# or hour. This is parsed by the date command as:
#
# date +$SPARTACUS_TIME -d "1 $SPARTACUS_INT ago"
#
# to generate the needed past-timestamp.
# OLD is an optional parameter that
# specifies how far back you wish to keep
# snapshots based on INT. If OLD is unset
# or otheriwse evaluates as a null string,
# then it will be ignored and spartacus will
# keep backups indefinitely until your disk
# runs out of space. For this reason, it is
# recommended that you set it to something sensible.
#
# MAKE SURE that TIME and INT agree, otherwise
# your snapshots will get mangled.
SPARTACUS_TIME="%Y-%m-%d_%H"
SPARTACUS_INT="hour"
#SPARTACUS_OLD=""
#!/usr/bin/bash
# SPARTACUS: the Slightly PARanoid minimalisT bACUp Script
# Written by ParanoidAndroid on Sat Jan 28 14:33:43 MST 2014
#
# this script is free and open-source software under the
# terms of the GNU General Public License v3:
# https://gnu.org/licenses/gpl-3.0-standalone.html
#
# this script comes with ABSOLUTELY NO WARRANTY,
# explicit or implied. If you break something using
# it, it's on you.
# define functions #
function usage {
cat << EOF
usage: spartacus PROFILE
This script will create or update a lovely, hardlinked, snapshot-style backup
tree within a LUKS-encrypted drive partition for PROFILE, leveraging
cryptsetup and the power of rsync with its --link-dest option. If the backup
tree doesn't exist or if there is no previous backup to link to (i.e. you are
using a new disk) then spartacus will make a full backup.
This help message can be displayed by passing 'help' as the profile name,
i.e. 'spartacus help'
EOF
}
function mksnapshot {
mkdir -p /mnt/backup/$PROFILE\_snapshot/$SNAPSHOT_TIMESTAMP
sync
rsync --progress --human-readable --numeric-ids --inplace --verbose --archive --delete-after --hard-links --xattrs --delete --compress --exclude={/sys/*,/mnt/*,/proc/*,/dev/*,/lost+found,/media/*,/tmp/*,/opt/*,/run/*}$PROFILEDIR/* /mnt/backup/$PROFILE\_snapshot/$SNAPSHOT_TIMESTAMP/ --link-dest=/mnt/backup/$PROFILE\_snapshot/$SNAPSHOT_LAST
sync
}
function new_backup {
mkdir -p /mnt/backup/$PROFILE\_snapshot
mkdir -p /mnt/backup/$PROFILE\_snapshot/$SNAPSHOT_TIMESTAMP
sync
rsync --progress --human-readable --numeric-ids --inplace --verbose --archive --delete-after --hard-links --xattrs --delete --compress --exclude={/sys/*,/mnt/*,/proc/*,/dev/*,/lost+found,/media/*,/tmp/*,/opt/*,/run/*} $PROFILEDIR/* /mnt/backup/$PROFILE\_snapshot/$SNAPSHOT_TIMESTAMP/
sync
}
function cleanup {
# check to see if SNAPSHOT_OLD variable is set
# if so, delete the snapshot it describes, if it exists.
if [ ! -z $SNAPSHOT_OLD ]; then
if [ -d /mnt/backup/$PROFILE\_snapshot/$SNAPSHOT_OLD ]; then
rmdir /mnt/backup/$PROFILE\_snapshot/$SNAPSHOT_OLD
else
echo -e "snapshot $SNAPSHOT_OLD for $PROFILE does \n\
not exist!\nskipping cleanup routine..."
fi
else
echo -e "no cleanup necessary ($SPARTACUS_OLD\
not set)."
fi
}
function backup_profile {
for disk in "${USEDISKS[@]}"
do
:
if [ -e $disk ]; then
cryptsetup luksOpen $disk backup --key-file=$KEYFILE
mount /dev/mapper/backup /mnt/backup
if [ -d /mnt/backup/$PROFILE\_snapshot/$SNAPSHOT_LAST ]; then
mksnapshot
elif [ -d /mnt/backup/$PROFILE\_snapshot/$SNAPSHOT_TIMESTAMP ]; then
echo -e "snapshot for $SNAPSHOT_TIMESTAMP already exists.\n\n\
this script is designed to make backups once per hour, as\n\
per the needs of the author, and will abort if attempts are \n\
made to back up a profile multiple times in the same hour.\n\n\
you can make it work down to the minute or second\n\
with a few simple edits to the SNAPSHOT_TIMESTAMP, \n\
SNAPSHOT_OLD, and SNAPSHOT_LAST environment variables, but hourly \n\
or daily should serve as a sane default for most home users."
else
echo -e "no previous snapshots found.\n\
Creating new backup..."
new_backup
fi
cleanup
umount /dev/mapper/backup
cryptsetup luksClose /dev/mapper/backup
else
echo "disk $disk not online. Skipping..."
fi
done
}
########## main ##########
# Make sure the script is running as root
if [[ $EUID -ne 0 ]]; then
usage
echo "This script must be run as root" 1>&2
exit 1
fi
# parse argument
if [ "$1" == "help" ]; then
usage
else
PROFILE=$1
fi
# parse the SPARTACUS configuration variables
# from /etc/spartacus.cfg
. /etc/spartacus.cfg
SNAPSHOT_TIMESTAMP=$(date +$SPARTACUS_TIME)
SNAPSHOT_LAST=$(date +$SPARTACUS_TIME -d "1 $SPARTACUS_INT ago")
SNAPSHOT_OLD=$(date +$SPARTACUS_TIME -d "$SPARTACUS_OLD $SPARTACUS_INT ago")
KEYFILE=$SPARTACUS_KEYFILE
# check to make sure variables are set
if [ -z $SPARTACUS_INT ]; then
echo "ERROR: config variable $SPARTACUS_INT unset!"
exit 1
elif [ -z $SPARTACUS_TIME ]; then
echo "ERROR: config variable $SPARTACUS_TIME unset!"
exit 1
elif [ -z $SPARTACUS_KEYFILE ]; then
echo "ERROR: config variable $SPARTACUS_KEYFILE unset!"
exit 1
else
echo "configuration file /etc/spartacus.cfg parsed correctly."
fi
# create mountpoint, if it doesn't exist.
# chown it to root and chmod 0744 as cautionary measure
mkdir -p /mnt/backup
chown root /mnt/backup
chmod 0744 /mnt/backup
if [ -z $PROFILE ]; then
usage
echo -e "no profile specified.\
\nUse the -p flag to specify a profile.
\n\nmust be one of:\n\tall\
\n\tsystem\n\thome\n\tdocs"
exit
else
if [ $PROFILE == "system" ]; then
unset PROFILEDIR
USEDISKS=$SYSTEMDISKS
backup_profile
echo -e "\nbackup complete"
exit
elif [ $PROFILE == "home" ]; then
PROFILEDIR=$HOMEDIR
USEDISKS=$HOMEDISKS
backup_profile
echo -e "\nbackup complete."
exit
elif [ $PROFILE == "docs" ]; then
PROFILEDIR=$DOCSDIR
USEDISKS=$HOMEDISKS
backup_profile
echo -e "\nbackup complete."
exit
else
echo "ERROR: invalid profile."
exit
fi
fi
#!/usr/bin/bash
# Make sure the script is running as root
if [[ $EUID -ne 0 ]]; then
echo "This script must be run as root" 1>&2
exit 1
fi
# source the /etc/spartacus config file
. /etc/spartacus.cfg
cryptsetup luksFormat -v -s 512 -y -h sha512 -c aes-xts-plain64 $1 && \
cryptsetup luksOpen $1 nbackup && \
mkfs.ext4 /dev/mapper/nbackup && \
cryptsetup luksClose /dev/mapper/nbackup
# check for an optional keyfile:
if [ -z $SPARTACUS_KEYFILE ]; then
echo -e "no keyfile specified for backups.\n\
skipping adding keyfile..."
elif [ ! -z $SPARTACUS_KEYFILE ]; then
cryptsetup luksAddKey $1 $SPARTACUS_KEYFILE
fi
echo 'add the following in double quotes to the \
appropriate array in /etc/spartacus.cfg:'
echo "/dev/disk/by-uuid/$(blkid $1 | sed -n 's/.* UUID=\"\([^\"]*\)\".*/\1/p')"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment