#!/bin/sh # A poor man backup # version 0.3 # A simple wrapper script to create a safe and redundant backup. # Requires: bash, GnuPG, duplicity, rdiff-backup, ssh, figlet # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. # See the GNU General Public License for more details. # You should have received a copy of the GNU General Public License # along with this program. If not, see . # # The script attempts 3 differents backup: # To a SD card via duplicity, encrypted with gnupg. It prevents ransom-ware. # To a remote Pc via duplicity and ssh, encrypted with gnupg. It prevents lost or damage. # To a remote Pc with encrypted disk via rdiff-backup. Plain mirror for easy recovering. # # +-------------------------------+ +-------------+ # | HOME | | SD CARD | # | |---> duplicity | # | | | encrypted | # +-------------------------------+ +-------------+ # | | # | | # +--v--------------+ +------v-----------+ # | REMOTE SSH PC1 | | REMOTE SSH PC2 | # | duplicity | | rdiff-backup | # | encrypted | | plain mirror | # +-----------------+ +------------------+ # # Optional: copies selected config files in $HOME/backups # # It is recommended to do a full backup every now and then, therefore # the script ask for a full backup every 6 months, and ask to delete # the old full backup every 7 months. Make sure you have enough space # for 2 full backups in your destination drive. A full backup takes # time, you better allow it before going to sleep # # Important: please remember to backup your gpg-private key separately # because you will need it to access the encrypted backup. # # The script verifies that gpg-agent is running and mount the SD card, # it is supposed to be well-commented and intentionally is all manual. # In case you wants to automatize you need ssh and gpg passwordless and # add the script to cron. # # my poor's man backup: hope you find this useful # To make it yours you need to customize your paths and your shouts # in the section below: VARIABLES # Good luck and may you never need to recover. # # Comments? Kudos? Curses? Advices? Thank you! # dan [at] autistici.org ############### # Invariables # ############### # We don't need to change anything here USER=`whoami` DATE=`date -I` ## only date w/o hours and minutes HOST=`hostname` ############# # Variables # ############# # Here you Define your variables: # BUINT is where you want to save a copy of your modified config files. # BUEXT is your removable memory, perhaps an unmounted SD card. # BUREM1 is the first remote file system, non-encrypted. Thus backup goes encrypted there. # BUREM2 is the second remote file system, encrypted. Thus backup goes un-encrypted there. # BUSSH is the ssh-key # BUNO is the exclude list txt file # BUGPG is the encrypt and sign-key key-id BUINT=$HOME/backups BUEXT=/mnt/sd BUREM1=zora ## the name of a remote FS as defined in ~/.ssh/config BUREM2=zelda ## another BUSSH=$HOME/.ssh/id_rsa BUNO=$HOME/.exclude BUGPG=Key-ID ########################################################### # There should be no need to change anything from now on, # # but all that has been written with the goal to be read # ########################################################### ######################### # Because it looks good # ######################### figlet "backup time" echo " " date echo " " ######################################## # Optional: local backup system config # ######################################## ######################################################### # I want to copy those modified config files in my HOME # # before to backup the whole $HOME # # Here you can name as many as you want. # ######################################################### echo "Salvate i quadri! Copio quei file di sistema" echo "Save the paintings! Let's save a copy of those system files" # Personally i like the italian echo version and cannot live without cat /etc/fstab > $BUINT/$HOST-etc-fstab ; cat /etc/hosts > $BUINT/$HOST-etc-hosts ; cat /etc/hosts.deny > $BUINT/$HOST-etc-hosts-deny ; cat /etc/hosts.allow > $BUINT/$HOST-etc-hosts-allow ; cat /etc/motd > $BUINT/$HOST-etc-motd ; crontab -l > $BUINT/$HOST-$USER-crontab # Keep track of the installed software echo "List installed software and copying sources.list" dpkg --get-selections | grep -vi kernel > $BUINT/$HOST-dpkg-sw-list.conf ; cat /etc/apt/sources.list > $BUINT/$HOST-etc-apt-sources.list ; cat /etc/apt/preferences.d/preferences > $BUINT/$HOST-etc-apt-preferences.d-preferences ; ls -lhp /usr/local/bin > $BUINT/$HOST-sw-in-usr-local-bin.txt ; echo " " ################################# # Check if gpg-agent is running # ################################# echo " " echo "calling gpg-agent:" gpg-agent if ! gpg-agent 2>/dev/null; then echo 'Per fare un backup, ci vuole un gpg-agent' echo "You need a gpg-agent running" echo "Aborting execution - Exit" exit 5 else echo " " fi ######################################################################################## # You can launch gpg-agent with: # # eval $(gpg-agent --daemon) # # but it should really start at login # # On my box i have in ~/config/openbox/autostart # # gpg-agent --daemon --enable-ssh-support --write-env-file "${HOME}/.gpg-agent-info" & # ######################################################################################## ####################################################################################### # To be safe from ransonware, I keep my removable backup offline. # # the if-statement check the exit code of grep, which indicates if there was a match. # # I don't want the output displayed, so i redirect it to /dev/null # ####################################################################################### ##################### # Mount the SD card # ##################### echo "Calling $BUEXT:" if mount | grep $BUEXT > /dev/null; then echo "$BUEXT is already mounted and available" else echo 'Per fare un tavolo, ci vuole un legno..' echo 'Per fare un backup, ci vuole una memoria' echo 'We need a memory.' echo "Mounting $BUEXT:" sudo mount $BUEXT sleep 2 fi # Verify that external storage is mounted if mount | grep $BUEXT > /dev/null; then echo " " else echo "$BUEXT DID NOT MOUNT" echo "Aborting execution - Exit" echo " " exit 5 fi ####################################### # Encrypted backup on external memory # ####################################### echo "Nessun impedimento. Questo backup s'ha da fare." echo "Backup on $BUEXT via duplicity and gpg (y/n)" read input if [ "$input" = "y" ]; then echo " " echo "Go go go with first backup. A full one every 6 months" echo "Vai col primo backup" echo " " duplicity --encrypt-sign-key $BUGPG --use-agent --full-if-older-than 6M --exclude-filelist $BUNO $HOME/ file:///$BUEXT/backups sleep 1 echo "Let me erase backups older than 7 month from $BUEXT" echo " " duplicity remove-all-but-n-full 2 --encrypt-sign-key $BUGPG --force file:///$BUEXT/backups echo " " else echo "(N)o backup on $BUEXT" echo " " fi ########################### # Umount external storage # ########################### echo "Umount $BUEXT (y/n)" read input if [ "$input" = "y" ]; then sudo umount $BUEXT sleep 2 else echo "(N)o, exit and not umounting $BUEXT" exit 5 fi ################################################ # Verify that the external memory got umounted # ################################################ if mount | grep $BUEXT > /dev/null; then echo "$BUEXT DID NOT UMOUNT" echo " " exit 5 else echo "(Y) Umounted $BUEXT" fi ################################# # Check if ssh-agent is running # ################################# if [ -z "$SSH_AUTH_SOCK" ] ; then echo "calling ssh-agent" eval `ssh-agent` ; ssh-add $BUSSH else echo " " fi #################################################### # Backup with duplicity and GPG on BUREM1 via ssh # #################################################### echo "Signora Ceccarelli ne facciamo un'altra?" echo "Backup on $BUREM1 via ssh, duplicity and gpg (y/n)" read input if [ "$input" = "y" ]; then echo " " echo "Go go go with second backup. A full one every 6 months" echo "Vai col secondo backup" echo " " duplicity --encrypt-sign-key $BUGPG --use-agent --full-if-older-than 6M --exclude-filelist $BUNO $HOME/ sftp://$USER@$BUREM1//home/$USER/backups sleep 1 echo "Let me erase backups older than 7 month from $BUREM1" echo " " duplicity remove-all-but-n-full 1 --encrypt-sign-key $BUGPG --force sftp://$USER@$BUREM1//home/$USER/backups else echo "(N)o backup su $BUREM1" echo " " fi ######################################################################## # Backup unencrypted with rdiff-backup on BUREM2 (encrypted hard disk) # ######################################################################## echo " " echo "Signora Ceccarelli!" echo "Andiamo su non faccia la manfrina, ne facciamo un'altra." echo "Backup plain mirror on $BUREM2 with rdiff-backup via ssh (y/n)" read input if [ "$input" = "y" ]; then echo " " echo "Go go go with third backup" echo "Vai col terzo backup" rdiff-backup --exclude-filelist $BUNO $HOME/ $BUREM2::/home/$USER/backup/$USER echo " " echo "Let me erase backups older than 1 year from $BUREM2" rdiff-backup --remove-older-than 52W $BUREM2::/home/$USER/backup/$USER echo " " echo "So Long, and Thanks for All the Fish" echo " " else echo "(N)o backup on $BUREM2" echo " " exit 5 fi