rsnapshot backup solution

In order to backup my systems I have choosen rsnapshot because it stores all files as normal files on the hard disk using links between different backup dates to reduce the file size of the complete backup. This enables me to check directly in the file system for old files. Normally I do not restore a complete backup but use to check for specific files only.
To simplify things further on I found a description to use rsync on the client machines and a server certificate, so that no interaction with the client is needed. The server may connect using his certificate and start a local rsync server on the client which handles the backup itself. And now to the steps required to setup the system on the client:

CLIENT
First we need rsync installed:

aptitude install rsync

then we need to create a special backup user:

useradd backupuser -c "Backup" -m -u 4210

Within the home folder of the new user we need to store the server certificate as .ssh/authorized_keys

mkdir .ssh
scp /home/backupuser/.ssh/authorized_keys

Now we need a special script which starts the rsync programm on the client listening for incoming requests:

scp /home/backupuser/

Finally some tweaking for the permissions:

chown backupuser:backupuser
chmod 755

We also need to allow the new user to execute rsync, so we adjust sudo for this by editing /etc/sudoers:

Defaults:backupuser !requiretty
Defaults:backupuser !visiblepw
backupuser ALL:NOPASSWD: /usr/bin/rsync

Thats it!
I also wrote a simple script to show a list of available rsnapshot config files stored on the backup server and start the backup for this script meaning backing up a specific system.
Here are the relevant scripts:
First the wrapper script which simply logs the current date and starts rsync using the command line options from rsnapshot remote config:


#!/bin/sh

/usr/bin/logger "BACKUP: Start backup at `/bin/date` ";
/usr/bin/sudo /usr/bin/rsync "$@";
/usr/bin/logger "BACKUP: Backup finalized at `/bin/date` ";

And here is the console script to start the backup:


#!/bin/sh
#
DIALOG="/usr/bin/dialog"
RSNAPSHOT="/usr/bin/rsnapshot"
CONFIGDIR=""
BACKUPDIR=""
CONFIGFILES=""

##### Check if Backupdisk is connected and correctly mounted ################
check_for_backup_dir() {
if [ ! -e $BACKUPDIR/ps2 ]
then
if [ $# -ne 0 ]
then
$DIALOG --clear --title "rsnapshot config" --msgbox "The backup disk is not connected to the machine!" 10 52
else
echo "The backup disk is not connected to the machine!"
fi
exit
fi
}

##### main ######
# choose dialog interface or command line parameter
if [ $# -ne 0 ]
then
if [ $# -gt 1 ]
then
echo "Usage: backup.sh or backup.sh "
echo " too many arguments on command line"
exit
fi
check_for_backup_dir
# command parameter available so no dialog interface used
if [ ! -e $CONFIGDIR/$1 ]
then
echo "No config file for system $1"
exit
else
COMMAND="$RSNAPSHOT -q -c $CONFIGDIR/$1 weekly"
$COMMAND
fi
else
check_for_backup_dir dialog
# no parameter available on command line so using dialog for choosing configuration
for file in $CONFIGDIR/*
do # create one variable including all available configs
CONFIGFILES="$CONFIGFILES $file ! "
done
TEMPFILE=`tempfile 2>/dev/null` || TEMPFILE=/tmp/test$$
trap "rm -f $TEMPFILE" 0 1 2 5 15
$DIALOG --clear --title "rsnapshot config" --menu "Choose rsnapshot configuration:" 18 50 10 $CONFIGFILES 2> $TEMPFILE
RUECKGABE=$?
case $RUECKGABE in
0)
AUSWAHL=`cat $TEMPFILE`
COMMAND="$RSNAPSHOT -q -c $AUSWAHL weekly" ### execute backup command
$COMMAND
;;
1)
echo "Backup canceled!"
;;
255)
echo "ESC pressed!"
;;
esac

trap "rm -f $TEMPFILE" 0 1 2 5 15

fi
# clean up and exit after all work is done
exit

The rsnapshot config files always look like the original ones delivered with rsnapshot except for the ssh section which starts the remote wrapper script shown above:


#################################################
# rsnapshot.conf - rsnapshot configuration file #
#################################################
# #
# PLEASE BE AWARE OF THE FOLLOWING RULES: #
# #
# This file requires tabs between elements #
# #
# Directories require a trailing slash: #
# right: /home/ #
# wrong: /home #
# #
#################################################
#
#######################
# CONFIG FILE VERSION #
#######################

config_version 1.2

###########################
# SNAPSHOT ROOT DIRECTORY #
###########################

# All snapshots will be stored under this root directory.
snapshot_root

# If no_create_root is enabled, rsnapshot will not automatically create the
# snapshot_root directory. This is particularly useful if you are backing
# up to removable media, such as a FireWire drive.
#
no_create_root 1

#################################
# EXTERNAL PROGRAM DEPENDENCIES #
#################################

# LINUX USERS: Be sure to uncomment "cmd_cp". This gives you extra features.
# EVERYONE ELSE: Leave "cmd_cp" commented out for compatibility.
#
# See the README file or the man page for more details.
#
cmd_cp /bin/cp

# uncomment this to use the rm program instead of the built-in perl routine.
cmd_rm /bin/rm

# rsync must be enabled for anything to work.
cmd_rsync /usr/bin/rsync

# Uncomment this to enable remote ssh backups over rsync.
cmd_ssh /usr/bin/ssh

# Comment this out to disable syslog support.
cmd_logger /usr/bin/logger

# Uncomment this to specify a path to "du" for disk usage checks.
cmd_du /usr/bin/du

#########################################
# BACKUP INTERVALS #
# Must be unique and in ascending order #
# i.e. hourly, daily, weekly, etc. #
#########################################

# The interval names (hourly, daily, ...) are just names and have no influence
# on the length of the interval. The numbers set the number of snapshots to
# keep for each interval (hourly.0, hourly.1, ...).
# The length of the interval is set by the time between two executions of
# rsnapshot , this is normally done via cron.
# Feel free to adapt the names, and the sample cron file under /etc/cron.d/rsnapshot
# to your needs. The only requirement is that the intervals must be listed
# in ascending order. To activate just uncomment the entries.

interval weekly 5

############################################
# GLOBAL OPTIONS #
# All are optional, with sensible defaults #
############################################

# If your version of rsync supports --link-dest, consider enable this.
# This is the best way to support special files (FIFOs, etc) cross-platform.
# The default is 0 (off).
# In Debian GNU cp is available which is superior to link_dest, so it should be
# commented out (disabled).
#
#link_dest 0

# Verbose level, 1 through 5.
# 1 Quiet Print fatal errors only
# 2 Default Print errors and warnings only
# 3 Verbose Show equivalent shell commands being executed
# 4 Extra Verbose Show extra verbose information
# 5 Debug mode More than you care to know
#
verbose 2

# Same as "verbose" above, but controls the amount of data sent to the
# logfile, if one is being used. The default is 3.
loglevel 3

# If you enable this, data will be written to the file you specify. The
# amount of data written is controlled by the "loglevel" parameter.
logfile

# The include and exclude parameters, if enabled, simply get passed directly
# to rsync. If you have multiple include/exclude patterns, put each one on a
# seperate line. Please look up the --include and --exclude options in the
# rsync man page for more details.
#

exclude /dev
exclude /lost+found
exclude /media
exclude /mnt
exclude /proc
exclude /run
exclude /sys
exclude /tmp

# The include_file and exclude_file parameters, if enabled, simply get
# passed directly to rsync. Please look up the --include-from and
# --exclude-from options in the rsync man page for more details.
#
#include_file /path/to/include/file
#exclude_file /path/to/exclude/file

# Default rsync args. All rsync commands have at least these options set.
#
rsync_long_args -v --numeric-ids --relative -ev --rsync-path=/home/backupuser/rsync-wrapper.sh

# ssh has no args passed by default, but you can specify some here.
#
ssh_args -i

# Default arguments for the "du" program (for disk space reporting).
# The GNU version of "du" is preferred. See the man page for more details.
#
du_args -csh

# If this is enabled, rsync won't span filesystem partitions within a
# backup point. This essentially passes the -x option to rsync.
# The default is 0 (off).
#
#one_fs 0

# If enabled, rsnapshot will write a lockfile to prevent two instances
# from running simultaneously (and messing up the snapshot_root).
# If you enable this, make sure the lockfile directory is not world
# writable. Otherwise anyone can prevent the program from running.
#
lockfile /path-to-pid-file

###############################
### BACKUP POINTS / SCRIPTS ###
###############################

# LOCALHOST
backup @:/ root/

SERVER
We have already seen the backup script that I use to keep an overview on all my systems and choosing a specific system to backup. For this to run of course we need rsnapshot, rsync and dialog.

aptitude install rsync rsnapshot dialog

The a dedicated user is required which I will call backupserver:

useradd backupserver -c "Backup user on server" -m

For this user we need to create a certificate for ssh:

ssh-keygen

Follow the instructions and do not give a password because we would need to showup this password all the times taking a backup.
Now we are able to spread the public part of the certificate to all client machines and we are done.
Finally I installed screen and used that as the default shell for the backupserver user in order to close – detache – the current connection to my headless backup server while the backup is running in back.

aptitude install screen

I also add the following to /etc/screenrc which gives me a normal bash in debian when using screen:

shell /bin/bash

Just for my own insufficiency:

Use the correct ownership and rights for the backup folder in order to allow the backupserver user to write the backup in the folder and always use this user when performing backups. Do not use the root user for that because it will destroy the rights structure in the backup folder and does not function with the certificate created earlier.

connect to TCP port using bash only

The device /dev/tcp// may be used to access the TCP stack

here is an example using redirects to connect to a specific service

exec 7<>/dev/tcp/www.google.com/80; cat <&5 & cat >&5; exec 5>&-

exec is used to redirect to a new file descriptor 7 whereas the cat redirects descriptor 7 to STDOUT. And finally the descriptor is cleaned up with the last exec.

Checking a remote port with just cat
cat < /dev/tcp//