-
-
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.
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
# 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="" |
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
#!/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 |
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
#!/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