three utilities that i wrote from scratch; they are provided here
without restriction in the hope someone finds them useful.
* duplicate primary USB to identical or larger USB drive
* backup persistent contents to the Persistent Folder
* restore from backup above
i find the duplicate utility essential and recommend it be included in
Tails. I've had a few instances where my computer halted (battery ran
out) and the usb drive was completely ruined with all data
unrecoverable, my only luck was that i had actually run my duplicate
previously! phew!!!
also, installing these under ~/.local/share/applications helps too.
Install [note, i've only done this once and it worked; so the setup
procedures should be tested with other systems.]
Manually add the following mapping to the
/live/persistence/TailsData_unlocked/persistence.conf file:
/home/amnesia/.local source=local
Then reboot to establish persistence for these "local" customizations.
Next drop the attached files in the
/home/amnesia/.local/share/applications/ folder and the utilities will
magically show up in the menus under "Accessories"! The *.bash files
must have execute permission.
INFO:
The duplicate.bash script checks to see if the two USB's are identical,
and if so it does a dd copy of the entire drive; if not identical it
attempts to create matching partitions on the target drive and dd's the
two partitions separately. That way you SHOULD be able to duplicate a
drive to another usb that isn't identical, but is at least a little bigger.
The backup.bash and restore.bash scripts are identical and use the
filename to determine which function to perform; backup puts the backup
file in the /home/amnesia/Persistent folder then i manually move it to a
cloud or another computer and then i wipe the backup file to free up the
space. Ideally, it would prompt for a target network destination, maybe
i'll add that in the future.
These have been working for me, but more testing is surely necessary.
The dup utility has saved my ass more than once! one of my usb drives
was completely destroyed (can't even format it) when my PC ran out of
battery power and shutdown abruptly. i highly recommend a duplicate
feature be added to tails!!
let me know if you find these useful. good luck.
-a2
-------------------------------------------------
ONLY AT VFEmail! - Use our Metadata Mitigator to keep your email out of the NSA's hands!
$24.95 ONETIME Lifetime accounts with Privacy Features!
15GB disk! No bandwidth quotas!
Commercial and Bulk Mail Options! #!/bin/bash
# TESTMODE, comment out the following line to disable TESTMODE
# backup and restore will NOT run when TESTMODE=TRUE
#TESTMODE=TRUE
P=`basename $0`
D="`echo ~amnesia/Persistent`"
PATTERN="-backup.tbz2.gpg"
#SRC="~amnesia"
SRC=/live/persistence/TailsData_unlocked
#
# only root can run
#
if [ `whoami` != "root" ];then
zenity --title="Insufficient Permission" \
--info \
--text="Only root can run this command; aborting." \
--timeout=5 2>/dev/null
exit 1
fi
if [ "$P" = "backup.bash" ];then
MODE=BACKUP
else
MODE=RESTORE
fi
zenity --title="Close all programs" \
--info \
--text="It is strongly recommended you close all programs before running a ${MODE}.\nIt can take up to 30 minutes or more to complete.\n\nPlease close any running programs now and Click OK to continue." 2>/dev/null
if [ "$MODE" = "BACKUP" ];then
TODAY=`date +%Y-%m-%d`
BAKFILE="$D/${TODAY}${PATTERN}"
if [ -f "$BAKFILE" ];then
zenity --title="Overwrite Backup File?" \
--question \
--text="WARNING: backup file already exists!\nPlease confirm you want to overwrite the file:\n`ls \"$BAKFILE\"`" 2>/dev/null
if [ $? -ne 0 ];then
zenity --title="Backup Aborted." \
--info \
--text="Backup aborted, did NOT overwrite existing file." \
--timeout=5 2>/dev/null
exit 1
fi
fi
zenity --info \
--text="You are about to be prompted, twice, for a passphrase.\nRemember it because you will need it to restore from backup.\n\n ... be patient the backup takes several minutes ..." 2>/dev/null
if [ "$TESTMODE" = "TRUE" ];then
zenity --info --text="TEST Mode, $MODE skipped." 2>/dev/null
else
echo "Enter password (twice) and then wait for the $MODE to complete."
cd ${SRC}
tar --exclude "*${PATTERN}" -cjf - . |
gpg --cipher-algo AES -c - > "$BAKFILE"
chown amnesia.amnesia $BAKFILE
zenity --info \
--text="Backup complete.\n `ls \"$BAKFILE\"`" 2>/dev/null
fi
exit 0
elif [ "$MODE" = "RESTORE" ];then
cd ${D}
F=""
for f in `find . -name "*${PATTERN}" -print|tr ' ' '#'`;do
if [ "$F" = "" ];then
F="TRUE $f"
else
# If there are more than two USB drives, create a list
F="$F FALSE $f"
fi
done
if [ "$F" = "" ];then
zenity --title="Restore Aborted." \
--info \
--text="Restore aborted, could not find any backup files." \
--timeout=5 2>/dev/null
exit 1
fi
# select the restore file, set BAKFILE
BAKFILE=`zenity --title="Select Backup File" \
--list \
--separator=" " \
--radiolist \
--text="Select file to restore:" \
--column="Select" \
--column="Device" \
$F 2>/dev/null`
if [ $? -ne 0 ];then
zenity --title="Aborting..." \
--info \
--text="Restore Aborted, no restore file selected" \
--timeout=5 2>/dev/null
exit 1;
fi
BAKFILE="`echo "$BAKFILE"|tr '#' ' '`"
if [ -f "$BAKFILE" ];then
zenity --info --title="Starting Restore." \
--text="Restore: you will be prompted for the passphrase you provided when you created this backup.\nPlease be patient, the restore will take several minutes.\nClick OK to continue..." 2>/dev/null
if [ "$TESTMODE" = "TRUE" ];then
zenity --info --text="TEST Mode, $MODE skipped." 2>/dev/null
else
echo "Enter password and then wait for the $MODE to complete."
cd ${SRC}
gpg --cipher-algo AES -d "$BAKFILE" | tar -xjvf -
zenity --info \
--text="Restore Complete." 2>/dev/null
fi
exit 0
else
zenity --info \
--text="Invalid file: $BAKFILE. Restore aborted." 2>/dev/null
exit 1
fi
fi
#!/bin/bash
I_DEV=""
O_DEV=""
OUSB=""
IUSB=""
#
# only root can run
#
if [ `whoami` != "root" ];then
zenity --title="Insufficient Permission" \
--info --text="Only root can run this command; aborting." --timeout=5 2>/dev/null
exit 1
fi
zenity --title="Close all programs" \
--info \
--text="It is strongly recommended you close all programs before starting the duplication process.\nIt typically takes 30 minutes or more to complete.\n\nPlease close any running programs now and Click OK to continue." 2>/dev/null
#
# Find USB drives.
# default first one is the INPUT and the SECOND is backup
#
for d in `readlink -e /dev/disk/by-id/usb*0:0|sort`; do
if [ "$I_DEV" = "" ];then
I_DEV="TRUE $d"
else
# If there are more than two USB drives, create a list
I_DEV="$I_DEV FALSE $d"
fi
done
#
# select the input device, set IUSB
IUSB=`zenity --title="Select Source Device" \
--list \
--radiolist \
--text="Select Source USB Device" \
--column="Select" \
--column="Device" \
$I_DEV 2>/dev/null`
if [ $? -ne 0 ];then
zenity --title="Aborting..." \
--info \
--text="Duplication Aborted, no source device selected." --timeout=5 2>/dev/null
exit 1;
fi
#
# Confirm IUSB is the boot device!
#
udevadm info $IUSB |grep -q "^S: TailsBootDev"
if [ $? -ne 0 ];then
zenity --title="Invalid Source" \
--question \
--text="WARNING: Source Device, $IUSB, is not bootable.\nPlease confirm you want to duplicate another USB drive." 2>/dev/null
if [ $? -ne 0 ];then
zenity --title="Aborting..." \
--info --text="Aborted, did not confirm source device: $IUSB" --timeout=5 2>/dev/null
exit 1
fi
fi
## Now, get the Output device list
## excluding the selected one from the target
for d in `readlink -e /dev/disk/by-id/usb*0:0|sort`; do
if [ "$d" = "$IUSB" ];then
: ;
elif [ "$O_DEV" = "" ];then
O_DEV="TRUE $d"
else
# If there are more than two USB drives, create a list
O_DEV="$O_DEV FALSE $d"
fi
done
if [ "$O_DEV" = "" ];then
zenity --title="Aborting..." \
--info \
--text="Aborted, no valid target device found." \
--timeout=10 2>/dev/null
exit 1
fi
OUSB=`zenity --title="Select Target Device" \
--list \
--radiolist \
--text="Select Target USB Device" \
--column="Select" \
--column="Device" \
$O_DEV 2>/dev/null`
if [ $? -ne 0 ];then
zenity --title="Aborting..." \
--info \
--text="Duplication Aborted, no target device selected." \
--timeout=5 2>/dev/null
exit 1;
fi
##
## Check the SOURCE drive size, boot and data partition
##
ISIZ=`lsblk -dnb -o size ${IUSB}`
ISIZboot=`lsblk -dnb -osize ${IUSB}1 2>/dev/null`
ISIZdata=`lsblk -dnb -osize ${IUSB}2 2>/dev/null`
if [ "${ISIZboot}" = "" -o "${ISIZdata}" = "" ];then
zenity --title="Aborting... invalid Source." \
--info \
--text="Aborted, Missing boot or data partition on $IUSB" \
--timeout=10 2>/dev/null
exit 1;
fi
##
## Check the TARGET drive size, boot and data partitions
##
OSIZ=`lsblk -dnb -o size ${OUSB}`
OSIZboot=`lsblk -dnb -osize ${OUSB}1 2>/dev/null`
OSIZdata=`lsblk -dnb -osize ${OUSB}2 2>/dev/null`
if [ "${OSIZ}" = "" ];then
zenity --title="Aborting... invalid Target." \
--info \
--text="Aborted, Cannot determine size of Target: $IUSB" \
--timeout=10 2>/dev/null
exit 1
fi
udevadm info $OUSB |grep -q "^S: TailsBootDev"
if [ $? -eq 0 ];then
zenity --title="WARNING: Invalid Target" --question \
--text="WARNING: Target Device, $OUSB, is the current boot device.\nPlease confirm you want to clobber your current boot device!!!\n\nWARNING: NOT RECOMMENDED! Abort Recommended (click No)." 2>/dev/null
if [ $? -ne 0 ];then
zenity --title="Aborting..." --info \
--text="Aborted, did not confirm Target: $OUSB" \
--timeout=5 2>/dev/null
exit 1
fi
fi
## OK here we go
## First, USB Drives vary in exact size.
##
if [ 0${ISIZ} -ne 0${OSIZ} ];then
if [ 0${ISIZboot} -ne 0${OSIZboot} -o \
0${ISIZdata} -ne 0${OSIZdata} ];then
zenity --title="WARNING: Target Partitions" --question \
--text="WARNING! WARNING!! WARNING!!!\nBoot and data partitions do not match.\n\nClick 'Yes' to Create new boot and data Partitions on the ${OUSB}. All contents on ${OUSB} will be lost." 2>/dev/null
if [ $? -ne 0 ];then
zenity --title="Aborting..." --info \
--text="Aborted, did not confirm partitions." \
--timeout=10 2>/dev/null
exit 1
fi
##
## dump SOURCE partitions, apply to TARGET
##
PTAB=`sfdisk --dump ${IUSB} 2>/dev/null |
grep "^${IUSB}" |
sed "s;${IUSB};${OUSB};g"`
echo -e "label: gpt\n${PTAB}" | sfdisk ${OUSB}
if [ $? -ne 0 ];then
zenity --title="Aborting... partition error." --info \
--text="Aborted, failed to create boot and data partitions on ${OUSB}" \
--timeout=30 2>/dev/null
exit 1
fi
fi
CMD="dd status=progress if=${IUSB}1 of=${OUSB}1 bs=8M;dd status=progress if=${IUSB}2 of=${OUSB}2 bs=8M"
else
CMD="dd status=progress if=${IUSB} of=${OUSB} bs=8M"
fi
#
# Confirm , are you sure you want to proceed? really?
#
zenity --title="WARNING: Please confirm" \
--question \
--default-cancel \
--text="WARNING! WARNING!! WARNING!!! \n\nAll contents on $OUSB will be lost!\n\nClick 'Yes' to start duplication of $IUSB to $OUSB!\n" 2>/dev/null
if [ $? -ne 0 ];then
zenity --info \
--text="Duplication Aborted, no changes were made." \
--timeout=10 2>/dev/null
exit 1
fi
###
### Well, well, well. OK, HERE WE GO! Let the backup begin!!!
###
sync;
s=`date`
(sleep 3;eval ${CMD}) |
zenity --progress \
--title="Duplicating $IUSB to $OUSB in progress..." \
--pulsate \
--text="Please be patient.\nThe Duplication can take 30 minutes or more.\nStarted at: ${s}" \
--auto-kill --auto-close 2>/dev/null
DDRESULT=$?
e=`date`
###
### all done!
###
if [ ${DDRESULT} -eq 0 ];then
result="Succeeded."
else
result="Aborted, $OUSB very likely corrupted."
fi
# report the resulrts...
zenity --title="Duplication Complete" --info \
--text="Duplication ${result}\nStarted: ${s}\nEnded: ${e}" 2>/dev/null
exit 0
#!/bin/bash
# TESTMODE, comment out the following line to disable TESTMODE
# backup and restore will NOT run when TESTMODE=TRUE
#TESTMODE=TRUE
P=`basename $0`
D="`echo ~amnesia/Persistent`"
PATTERN="-backup.tbz2.gpg"
#SRC="~amnesia"
SRC=/live/persistence/TailsData_unlocked
#
# only root can run
#
if [ `whoami` != "root" ];then
zenity --title="Insufficient Permission" \
--info \
--text="Only root can run this command; aborting." \
--timeout=5 2>/dev/null
exit 1
fi
if [ "$P" = "backup.bash" ];then
MODE=BACKUP
else
MODE=RESTORE
fi
zenity --title="Close all programs" \
--info \
--text="It is strongly recommended you close all programs before running a ${MODE}.\nIt can take up to 30 minutes or more to complete.\n\nPlease close any running programs now and Click OK to continue." 2>/dev/null
if [ "$MODE" = "BACKUP" ];then
TODAY=`date +%Y-%m-%d`
BAKFILE="$D/${TODAY}${PATTERN}"
if [ -f "$BAKFILE" ];then
zenity --title="Overwrite Backup File?" \
--question \
--text="WARNING: backup file already exists!\nPlease confirm you want to overwrite the file:\n`ls \"$BAKFILE\"`" 2>/dev/null
if [ $? -ne 0 ];then
zenity --title="Backup Aborted." \
--info \
--text="Backup aborted, did NOT overwrite existing file." \
--timeout=5 2>/dev/null
exit 1
fi
fi
zenity --info \
--text="You are about to be prompted, twice, for a passphrase.\nRemember it because you will need it to restore from backup.\n\n ... be patient the backup takes several minutes ..." 2>/dev/null
if [ "$TESTMODE" = "TRUE" ];then
zenity --info --text="TEST Mode, $MODE skipped." 2>/dev/null
else
echo "Enter password (twice) and then wait for the $MODE to complete."
cd ${SRC}
tar --exclude "*${PATTERN}" -cjf - . |
gpg --cipher-algo AES -c - > "$BAKFILE"
chown amnesia.amnesia $BAKFILE
zenity --info \
--text="Backup complete.\n `ls \"$BAKFILE\"`" 2>/dev/null
fi
exit 0
elif [ "$MODE" = "RESTORE" ];then
cd ${D}
F=""
for f in `find . -name "*${PATTERN}" -print|tr ' ' '#'`;do
if [ "$F" = "" ];then
F="TRUE $f"
else
# If there are more than two USB drives, create a list
F="$F FALSE $f"
fi
done
if [ "$F" = "" ];then
zenity --title="Restore Aborted." \
--info \
--text="Restore aborted, could not find any backup files." \
--timeout=5 2>/dev/null
exit 1
fi
# select the restore file, set BAKFILE
BAKFILE=`zenity --title="Select Backup File" \
--list \
--separator=" " \
--radiolist \
--text="Select file to restore:" \
--column="Select" \
--column="Device" \
$F 2>/dev/null`
if [ $? -ne 0 ];then
zenity --title="Aborting..." \
--info \
--text="Restore Aborted, no restore file selected" \
--timeout=5 2>/dev/null
exit 1;
fi
BAKFILE="`echo "$BAKFILE"|tr '#' ' '`"
if [ -f "$BAKFILE" ];then
zenity --info --title="Starting Restore." \
--text="Restore: you will be prompted for the passphrase you provided when you created this backup.\nPlease be patient, the restore will take several minutes.\nClick OK to continue..." 2>/dev/null
if [ "$TESTMODE" = "TRUE" ];then
zenity --info --text="TEST Mode, $MODE skipped." 2>/dev/null
else
echo "Enter password and then wait for the $MODE to complete."
cd ${SRC}
gpg --cipher-algo AES -d "$BAKFILE" | tar -xjvf -
zenity --info \
--text="Restore Complete." 2>/dev/null
fi
exit 0
else
zenity --info \
--text="Invalid file: $BAKFILE. Restore aborted." 2>/dev/null
exit 1
fi
fi