Created
June 24, 2011 13:25
-
-
Save pajp/1044757 to your computer and use it in GitHub Desktop.
cryptsync - rsync a folder to an encrypted disk image
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
#!/bin/bash | |
# cryptsync.sh - a simple script for keeping an encrypted backup of a folder | |
# | |
# Author: Rasmus Sten <cryptsync@dll.nu> | |
# | |
# For example, to make an encrypted backup of my ~/Documents folder to Dropbox: | |
# | |
# ./cryptsync.sh --init ~/Documents/ ~/Dropbox/ | |
# | |
# Later, to update the backup, re-run th script without the --init option: | |
# | |
# ./cryptsync.sh ~/Documents/ ~/Dropbox/ | |
# | |
# The target path can be any directory or mount point, e.g. a USB flash drive, | |
# an NFS share or web service such as iDisk or DropBox. | |
# | |
# To examine the contents of the disk image, you can use the --leave-mounted | |
# option to prevent the script from unmounting it after synchronization. | |
# | |
# On Linux, the script requires cryptsetup and sudo privilege is required to | |
# setup the loopback interfaces and mount the LUKS image. | |
# On Mac, it should work on a base Mac OS X system with standard user | |
# privileges. | |
# | |
# Run the script without any parameters for more usage information. | |
# | |
# The script works on Linux and Mac OS X, but the disk images created on Linux | |
# cannot be used in Mac OS X and vice versa. On Linux, an ext3-formatted LUKS | |
# image called "encrypted.luks" is created, while on Mac it is a sparse native | |
# HFS+ disk image called "encrypted.sparseimage". The default size is 1 GB. | |
# | |
exiterror() { | |
echo "$*" >&2 | |
exit 1 | |
} | |
usage() { | |
echo "Usage:" | |
echo -e "\t$0 [--leave-mounted] [--init] <src-dir> <dst-dir>" | |
echo | |
echo " --leave-mounted don't unmount after synchronizing" | |
echo " --init create and format an encyptred disk image first" | |
echo | |
echo "Note: the order of options matters" | |
echo | |
echo "Examples:" | |
echo -e "\t$0 --init ~/Documents /mnt/usbdrive" | |
echo -e "\t\tWill create an encrypted disk image in /mnt/usbdrive with the" | |
echo -e "\t\tdirectory ~/Documents (and its contents) in its root folder" | |
echo | |
echo -e "\t$0 ~/important /Volumes/Thumbdrive" | |
echo -e "\t\tLocate an encrypted disk image in /Volumes/Thumbdrive and" | |
echo -e "\t\tsynchronize the directory ~/important onto it" | |
echo | |
exit 1 | |
} | |
mounted=false | |
found=false | |
lookedfor="" | |
tmpfile=`mktemp -t cryptsync.XXXXXX` | |
gigs=1 | |
leavemounted=false | |
if [ "$1" = "--leave-mounted" ] ; then | |
shift | |
leavemounted=true | |
fi | |
[ "$1" -a "$2" ] || usage | |
if [ "$1" = "--init" ] ; then | |
shift | |
src="$1" | |
dst="$2" | |
if [ `uname` = "Darwin" ] ; then | |
imgfile="${dst}/encrypted.sparseimage" | |
if [ -e "$imgfile" ] ; then | |
exiterror "$imgfile already exists" | |
fi | |
echo "Creating a sparse encrypted disk image in file $imgfile" | |
hdiutil create -attach -encryption AES-256 -type SPARSE -fsargs "-v cryptsync" -fs HFS+J -size ${gigs}g "$imgfile" > $tmpfile || exiterror "Failed to create the disk image" | |
# save mount point information for later | |
mv $tmpfile ${tmpfile}.tmp | |
grep -v ^created ${tmpfile}.tmp > $tmpfile | |
mounted=true | |
found=true | |
elif [ `uname` = "Linux" ] ; then | |
imgfile="${dst}/encrypted.luks" | |
if [ -f "$imgfile" ] ; then | |
exiterror "Cowardly refusing to overwrite $imgfile" | |
fi | |
echo "Creating $imgfile" | |
dd if=/dev/zero of="$imgfile" bs=$((1024*1024)) count=$(($gigs * 1024)) | |
dev=`sudo losetup -f` | |
sudo losetup $dev $imgfile || exiterror "Failed to setup loop device $dev for $imgfile" | |
sudo cryptsetup luksFormat -q $dev | |
mapname=cryptsync.$$ | |
sudo cryptsetup luksOpen $dev $mapname || exiterror "Failed to luksOpen $dev $mapname" | |
sudo mkfs.ext3 /dev/mapper/$mapname || exiterror "Failed to create a filesystem on $mapname" | |
mountpoint=`sudo mktemp -d /mnt/cryptsync.XXXXXX` | |
sudo mount /dev/mapper/$mapname $mountpoint || exiterror "failed to mount $dev on $mountpoint" | |
mounted=true | |
found=true | |
else | |
echo "This part not done for `uname` yet." | |
fi | |
else | |
src="$1" | |
dst="$2" | |
fi | |
# strip trailing slash | |
src=`echo "$src" | sed -e 's/\/$//'` | |
if ! $mounted ; then | |
if [ `uname` = "Darwin" ] ; then | |
for ext in dmg sparseimage ; do | |
f="$dst"/encrypted.$ext | |
lookedfor="$lookedfor $f" | |
if [ -e $f ] ; then | |
found=true | |
hdiutil attach $f > $tmpfile && mounted=true | |
break | |
fi | |
done | |
elif [ `uname` = "Linux" ] ; then | |
f="$dst"/encrypted.luks | |
lookedfor="$f" | |
if [ -f "$f" ] ; then | |
found=true | |
dev=`sudo losetup -f` | |
[ -z "$dev" ] && exiterror "Failed to acquire loopback device" | |
sudo losetup $dev $f | |
mapname=cryptsync.$$ | |
sudo cryptsetup luksOpen $dev $mapname | |
mountpoint=`sudo mktemp -d /mnt/cryptsync.XXXXXX` | |
sudo mount /dev/mapper/$mapname $mountpoint || exiterror "failed to mount $dev on $mountpoint" | |
mounted=true | |
fi | |
else | |
echo Unsupported OS: `uname` | |
exit 1 | |
fi | |
fi | |
if ! $found ; then | |
exiterror "Couldn't find any encrypted disk image. Looked for: $lookedfor" | |
fi | |
if ! $mounted ; then | |
echo Nothing mounted. | |
exit 1 | |
fi | |
if [ -z "$mountpoint" ] ; then | |
mountpoint=`tail -1 $tmpfile | awk 'BEGIN { FS = "\t" } { print $3 }'` | |
fi | |
if [ ! -d "$mountpoint" ] ; then | |
echo "Can't find supposed mount point $mountpoint" | |
exit 1 | |
fi | |
if [ `uname` = "Linux" ] ; then | |
sudo chown $USER $mountpoint | |
fi | |
echo "Synchronizing $src to $mountpoint" | |
rsync -az "$src" "$mountpoint" | |
if ! $leavemounted ; then | |
if [ `uname` = "Darwin" ] ; then | |
hdiutil detach "$mountpoint" | |
elif [ `uname` = "Linux" ] ; then | |
echo -n Cleaning up... | |
sudo umount $mountpoint || exiterror "Unmount of $mountpoint failed" | |
sudo rmdir $mountpoint || exiterror "Failed to remove mount point $mountpoint" | |
sudo cryptsetup luksClose /dev/mapper/$mapname || exiterror "Failed to luksClose" | |
sudo losetup -d $dev || exiterror "Failed to delete loop" | |
echo " OK." | |
else | |
echo "Don't know how to deal with `uname`" | |
fi | |
else | |
echo "Mounted on $mountpoint" | |
if [ `uname` = "Darwin" ] ; then | |
open "$mountpoint" | |
fi | |
fi | |
exit 0 |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment