Backup automatici locali e remoti con rsnapshot

rsnapshot-backuprsnapshot è un programma di utilità di backup incrementale e questo tutorial illustrerà come è possibile creare diversi backup a rotazione con rsnapshot, creando un primo backup completo e backup successivi dei soli i file modificati.

Il vero potere di rsnapshot è la sua capacità di utilizzare hard link tra ogni backup: ogni backup sembrerà essere un backup completo, in realtà ogni nuovo backup è costituito dai soli file appena creati o aggiornati.

rsnapshot può essere utilizzato in locale, su una rete LAN o anche su server remoti e può essere eseguito da cron.

Procedura per installare e configurare rsnapshot:

1) Installare rbackup dal repository EPEL

yum install rsnapshot

2) Installare perl-Lchown dal repository rpmforge

yum install perl-Lchown

3) editare il file /etc/rsnapshot.conf e decommentare alcuni comandi come da esempio e indicando i propri percorsi di backup.
Per rendere più agevole la comprensione delle varie sezioni sono state aggiunte alcune  traduzioni.

#################################################
# 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.
# Tutti gli snapshot vengono salvati nella cartella indicata come snapshot_root.
#
#snapshot_root	/.snapshots/
snapshot_root		/mnt/hd_esterno/backup/

# 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 or USB drive.
# Se no_create_root è impostato a 1, rsnapshot non creerà
# automaticamente la cartella snapshot_root se questa non esiste.
# Questa funzione è particolarmente utile quando si eseguono backup
# su supporti rimovibili, come hard disk USB o FireWire in quanto evita che,
# nel caso il disco esterno non sia montato, che venga creata
# la directory di lavoro e venga eseguito il backup sul disco fisso.
#
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. This is the only command that
# must be enabled.
#
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 the path to "du" for disk usage checks.
# If you have an older version of "du", you may also want to check the
# "du_args" parameter below.
#
cmd_du		/usr/bin/du

# Uncomment this to specify the path to rsnapshot-diff.
#
#cmd_rsnapshot_diff	/usr/local/bin/rsnapshot-diff

# Specify the path to a script (and any optional arguments) to run right
# before rsnapshot syncs files
#
#cmd_preexec	/path/to/preexec/script

# Specify the path to a script (and any optional arguments) to run right
# after rsnapshot syncs files
#
#cmd_postexec	/path/to/postexec/script

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

# I nomi degli intervalli (weekly = settimanale, monthly = mensile, …)
# sono solo nomi e non hanno nessun effetto sulla reale durata
# dell’intervallo. I numeri impostano la quantità di snapshot da
# conservare per ogni intervallo (weekly.0, weekly.1, …).
# La lunghezza dell’intervallo viene impostato dall’intervallo temporale
# tra due esecuzioni di rsnapshot <nome intervallo>, generalmente
# tramite cron. Sentitevi liberi di adattare i nomi degli intervalli, e di
# conseguenza il file /etc/cron.d/rsnapshot secondo le vostre
# esigenze. L’unica vincolo è che gli intervalli devono essere elencati
# in ordine ascendente.
# La configurazione proposta è per avere 7 backup giornalieri, 4 settimanali
# 3 mensili e tralascia i backup orari.

#interval	hourly	6
interval	daily	7
interval	weekly	4
interval	monthly	3

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

# 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      Everything
# Questo parametro imposta il livello di indicazioni che verranno
# scritte nel file di log: si consiglia di impostare 3 o 5.
verbose		3

# 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.
# Se attivato (decommentato) sarà scritto un file di log nella 
# directory indicata.
logfile	/var/log/rsnapshot

# 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	/var/run/rsnapshot.pid

# Default rsync args. All rsync commands have at least these options set.
#
#rsync_short_args	-a
rsync_long_args	–-stats	--delete --numeric-ids --relative --delete-excluded

# ssh has no args passed by default, but you can specify some here.
# Cambiare numero porta se SSH utilizza una diversa porta da quella di default.
ssh_args	-p 22

# Default arguments for the "du" program (for disk space reporting).
# The GNU version of "du" is preferred. See the man page for more details.
# If your version of "du" doesn't support the -h flag, try -k flag instead.
#
#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

# 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
# separate line. Please look up the --include and --exclude options in the
# rsync man page for more details on how to specify file name patterns. 
# Parametri di inclusione / esclusione, se abilitato, passati direttamente
# a rsync. Se si dispone di più includere / escludere, mettere ognuno su un
# riga separata. Si prega di leggere le opzioni --include e --exclude 
# nella guida rsync per avere maggiori dettagli.
# In questo esempio sono escluse tutte le directory denominate logs/
# 
#include	???
#include	???
exclude	logs/
#exclude	???

# 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

# 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).
#
#link_dest	0

# When sync_first is enabled, it changes the default behaviour of rsnapshot.
# Normally, when rsnapshot is called with its lowest interval
# (i.e.: "rsnapshot hourly"), it will sync files AND rotate the lowest
# intervals. With sync_first enabled, "rsnapshot sync" handles the file sync,
# and all interval calls simply rotate files. See the man page for more
# details. The default is 0 (off).
# sync_first dovrebbe essere impostata su ON in modo che venga effettuato
# prima il backup e dopo ruotate le istantanee. In questo modo si può sempre
# vedere sul vostro disco fisso, se i backup sono ancora in esecuzione
# come previsto. 
# Nell'opzione OFF saranno PRIMA ruotate le istantanee, anche se non vi è alcun
# backup eseguito, con il rischio di perdere tutte le vecchie istantanee. 
#
# comment sync_first on your dryrun, and your first real run, then re-enable
# decommentare sync_first dopo il primo backup
# sync_first	1 

# If enabled, rsnapshot will move the oldest directory for each interval
# to [interval_name].delete, then it will remove the lockfile and delete
# that directory just before it exits. The default is 0 (off).
#
#use_lazy_deletes	0

# Number of rsync re-tries. If you experience any network problems or
# network card issues that tend to cause ssh to crap-out with
# "Corrupted MAC on input" errors, for example, set this to a non-zero
# value to have the rsync operation re-tried
#
#rsync_numtries 0

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

# LOCALHOST

backup		/var/www/vhosts/	localhost/
#backup	/home/		localhost/
#backup	/usr/local/	localhost/
#backup	/var/log/rsnapshot		localhost/
#backup	/etc/passwd	localhost/
#backup	/home/foo/My Documents/		localhost/
#backup	/foo/bar/	localhost/	one_fs=1, rsync_short_args=-urltvpog
#backup_script	/usr/local/bin/backup_pgsql.sh	localhost/postgres/

# EXAMPLE.COM
#backup_script	/bin/date "+ backup of example.com started at %c"	unused1
#backup	root@example.com:/home/	example.com/	+rsync_long_args=--bwlimit=16,exclude=core
#backup	root@example.com:/etc/	example.com/	exclude=mtab,exclude=core
#backup_script	ssh root@example.com "mysqldump -A > /var/db/dump/mysql.sql"	unused2
#backup	root@example.com:/var/db/dump/	example.com/
#backup_script	/bin/date	"+ backup of example.com ended at %c"	unused9

# CVS.SOURCEFORGE.NET
#backup_script	/usr/local/bin/backup_rsnapshot_cvsroot.sh	rsnapshot.cvs.sourceforge.net/

# RSYNC.SAMBA.ORG
#backup	rsync://rsync.samba.org/rsyncftp/	rsync.samba.org/rsyncftp/

Attenzione a non sbagliare la sintassi: tra un parametro è l’altro deve esserci un TAB e non uno spazio, altrimenti rsnapshot non funzionerà. In ogni caso è meglio testare la configurazione con:

rsnapshot configtest

che in caso positivo ci restituire il messaggio Syntax OK e con il comando:

rsnapshot –t daily

che restituirà l’elenco delle operazioni che verrebbero eseguite senza eseguirle realmente (dry run).

4) Pianificare i backup giornalieri, settimanali e mensili

Sistemata la configurazione, si può pensare alla schedulazione dei backup servendoci di cron.
Digitando il comando crontab -e ed inserendo le righe desiderate, come ad esempio per programmare l’esecuzione del backup giornaliero tutti i giorni dal lunedì al sabato alle ore 20.30:

30 20 * * 1-6 rsnapshot daily

per programmare l’esecuzione del backup settimanale tutte le domeniche alle ore 20.30:

30 20 * * 7 rsnapshot weekly

per programmare l’esecuzione del backup mensile nel primo giorno del mese alle ore 20.30:

30 20 1 * * rsnapshot monthly

ATTENZIONE: nel caso si decommenti # sync_first (da fare solo dopo il primo backup) è necessario far precedere il comando rsnapshot sync && 

30 20 * * 1-6 rsnapshot sync && rsnapshot daily
30 20 * * 7 rsnapshot sync && rsnapshot weekly
30 20 1 * * rsnapshot sync && rsnapshot monthly

Creare un Report delle operazioni di backup:

E’ possibile generare un report riassuntivo del backup con invio ad una email, per questo utilizzeremo un file il perl che andrà corretto in quanto quello di default è adatto per una versione di rsnapshot obsoleta.

1) Ricopiare il file rsnapreport.pl che si trova nella cartella /usr/share/doc/ nella cartella /usr/local/bin/ e configurare i permessi di esecuzione:

# cp /usr/share/doc/rsnapshot-1.3.1/utils/rsnapreport.pl /usr/local/bin
# chmod +x /usr/local/bin/rsnapreport.pl

editare il file /usr/local/bin/rsnapreport.pl e sostituire le righe indicate con – con quelle contrassegnate con +:

 	foreach my $source (sort keys %bkdata){
 		if($bkdata{$source} =~ /error/i) { print "ERROR $source $bkdata{$source}"; next; }
-		my $files = $bkdata{$source}{'files'};
-		my $filest = $bkdata{$source}{'files_tran'};
-		my $filelistgentime = $bkdata{$source}{'file_list_gen_time'};
-		my $filelistxfertime = $bkdata{$source}{'file_list_trans_time'};
-		my $bytes= $bkdata{$source}{'file_size'}/1000000; # convert to MB
-		my $bytest= $bkdata{$source}{'file_tran_size'}/1000000; # convert to MB
+		my $files = $bkdata{$source}{'files'} || "N/A";
+		my $filest = $bkdata{$source}{'files_tran'} || "N/A";
+		my $filelistgentime = $bkdata{$source}{'file_list_gen_time'} || "N/A";
+		my $filelistxfertime = $bkdata{$source}{'file_list_trans_time'} || "N/A";
+		my $bytes= $bkdata{$source}{'file_size'}/1000000 || "0"; # convert to MB
+		my $bytest= $bkdata{$source}{'file_tran_size'}/1000000 || "0"; # convert to MB
 		$source =~ s/^[^\@]+\@//; # remove username

In questo caso l’evento pianificato dovrà essere il seguente (esempio per backup giornaliero):

30 20 * * 1-6 rsnapshot daily | \/usr/local/bin/rsnapreport.pl | mail -s "Report rsnapshot" casella@dominio.xx

ATTENZIONE: utilizzando la funzione rsnapreport.pl bisogna assicurarsi che nel file di configurazione /etc/rsnapshot.conf sia presente il parametro —stats nella riga:

rsync_long_args --stats	--delete --numeric-ids --relative --delete-excluded

ATTENZIONE: dopo il tag rsync_long_args è necessario che il primo parametro sia staccato con un TAB (non con uno spazio)  e i successivi con uno spazio (e non con una TAB):

rsync_long_args<TAB>–stats<SPAZIO>–delete<SPAZIO>–numeric-ids<SPAZIO>–relative<SPAZIO>–delete-excluded

Purtroppo la documentazione di rsnapshot in questo caso è molto lacunosa…

Backup rsnapshot remoti

E’ possibile eseguire backup di server remoti su un PC (o un server) destinato a conservare i backup. Per questo è necessario configurare dapprima il server remoto e successivamente il PC locale come da procedura indicata di seguito:

A) Operazioni da eseguirsi sul server remoto (quello dove si trovano le cartelle e i file di produzione)

1) Creare un utente di backup, ad esempio xxxbackup (o altro nome utente che non sia di facile individuazione) e creando la home directory e assegnandogli /bin/bash come shell:

useradd -s /bin/bash -m xxxbackup

2) Creare un wrapper /usr/local/bin/rsync_wrapper.sh con all’interno:

#!/bin/sh
/usr/bin/sudo /usr/bin/rsync "$@";

e impostiamo i permessi:

chmod 755 /usr/local/bin/rsync_wrapper.sh

3) Creare il file /home/xxxbackup/validate-rsync.sh con al suo interno uno script per limitare l’uso di ssh:

#!/bin/sh
case "$SSH_ORIGINAL_COMMAND" in
  *\&*)
    echo "Rejected 1"
    ;;
  *\;*)
    echo "Rejected 2"
    ;;
  /usr/local/bin/rsync_wrapper*)
    $SSH_ORIGINAL_COMMAND
    ;;
  *true*)
    echo $SSH_ORIGINAL_COMMAND
    ;;
  *)
    echo "Rejected 3"
    ;;
esac

e impostiamo anche permessi e owner dello script:

chown xxxbackup:xxxbackup /home/xxxbackup/validate-rsync.sh
chmod 755 /home/xxxbackup/validate-rsync.sh

4) Configurare sudo per permettere l’utilizzo di rsync (e solo rsync) con permessi di root, aggiungendo nel file  /etc/sudoers la riga:

xxxbackup ALL = NOPASSWD: /usr/bin/rsync

B) Operazioni da eseguirsi sul sul PC locale (quello dove saranno riposti i backup)

1) Generare le chiavi (pubblica e privata) per l’accesso remoto:

ssh-keygen -t rsa

e rinominarla per evitare che possa venire sovrascritta:

mv /root/.ssh/id_rsa.pub /root/.ssh/id_rsa_rsnapshot_server01.pub
mv /root/.ssh/id_rsa /root/.ssh/id_rsa_rsnapshot_server01

C) Copia della chiave pubblica sul server remoto, e configurazione per consentire autenticazione senza password

1) Da root, passare all’utente xxxbackup e utilizzare per la prima volta ssh, in modo che venga creata la directory .ssh con i permessi corretti:

su – xxxbackup

e successivamente lanciare il comando ssh 0 e rispondere yes:

# ssh 0
The authenticity of host ‘0 (0.0.0.0)’ can’t be established.
ECDSA key fingerprint is ba:fc:1d:c0:95:01:39:35:01:3a:b4:d1:f7:cb:1b:b3.
Are you sure you want to continue connecting (yes/no)? yes

e ritornare all’utente root con exit:

# exit

2) Copiare la chiave pubblica del pc locale /root/.ssh/id_rsa_rsnapshot_server01.pub nella directory /home/xxxbackup/.ssh del server remoto, quindi inserirla inserire all’interno del file authorized_keys e successivamente rimuovere la chiave pubblica in quanto non più necessaria.

cat /home/xxxbackup/.ssh/id_rsa_rsnapshot_server01.pub >>/home/xxxbackup/.ssh/authorized_keys
rm /home/xxxbackup/.ssh/id_rsa_rsnapshot_server01.pub

e configurare i permessi corretti:

chown xxxbackup:xxxbackup /home/xxxbackup/.ssh/authorized_keys
chmod 600 /home/xxxbackup/.ssh/authorized_keys

3) Aggiungere limitazioni all’autenticazione senza password, in modo da imporre l’utilizzo del file validate_rsync.sh creato in precedenza così che non sia possibile eseguire altri comandi, quindi editare il file authorized_keys e aggiungere prima di ssh-rsa:

from="xxx.xxx.xxx.xxx",command="/home/xxxbackup/validate-rsync.sh"

(per xxx.xxx.xxx.xxx indicare l’IP del server di backup)

D) Test collegamento SSH senza password

1) Per semplicità salvare i dati di connessione sul server di backup in modo da semplificare e abbreviare i comandi, creando il file (se non esiste) /root/.ssh/config inserendo all’interno del file il seguente codice:

Host server01
HostName xxx.xxx.xxx.xxx
User xxxbackup
IdentityFile ~/.ssh/id_rsa_rsnapshot_server01

(Sostituire xxx.xxx.xxx.xxx con l’ip del server remoto)

2) Testare la connessione:

# ssh server01
Rejected 3
Connection to xxx.xxx.xxx.xxx closed.

Il wrapper funziona correttamente: siamo riusciti ad autenticarci senza password dal server di backup al server remoto ma ci viene risposto Rejected 3, come da impostato nel wrapper sul server remoto.

Se proviamo ad utilizzare rsync con autenticazione senza password, ad esempio chiedendo di trasferire un file inesistente, si dovrebbe ricevere un messaggio di errore di rsync come il seguente:

# ssh server01 /usr/local/bin/rsync_wrapper.sh ciao pippo
rsync: link_stat “/home/rbackup/ciao” failed: No such file or directory (2)
rsync error: some files/attrs were not transferred (see previous errors) (code 23) at main.c(1070) [sender=3.0.9]

Se invece si riceve la risposta:

sudo: sorry, you must have a tty to run sudo

è necessario aggiungere all’interno del file /etc/sudoers 

Defaults:xxxbackup !requiretty

E) Configurazione rsnapshot.conf per backup server remoto

1) A questo punto possiamo inserire nel file /etc/rsnapshot.conf il percorso del backup del server remoto @server01:

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

# LOCALHOST

backup		/var/www/vhosts/	localhost/

# EXAMPLE.COM

backup	xxxbackup@server01:/var/www/vhosts/	server01/	+rsync_long_args=--rsync-path=/usr/local/bin/rsync_wrapper.sh

Ovviamente questo è solo un esempio, si dovranno indicare il proprio user@host e i percorsi di backup.

Ripristino backup

Per ripristinare i backup di cui sopra, useremo (ovviamente indicando i percorsi corretti!):

rsync -a /mnt/backup/localhost/monthly.0/localhost/. /var/www/vhosts/
rsync -a /mnt/backup/localhost/weekly.0/localhost/. /var/www/vhosts/
rsync -a /mnt/backup/localhost/daily.0/localhost/. /var/www/vhosts/

 

APPROFONDIMENTI:

1) E’ possibile lanciare rsnapshot in modo che utilizzi una configurazione diversa da quella di default, così da poter avere diverse sessioni differenziate di backup. Tuttavia, se si è decommentato nel file di configurazione il parametro:

lockfile	/var/run/rsnapshot.pid

potrà essere attiva una sola sessione di rsnapshot per volta.

Per lanciare rsnapshot con una configurazione dedicata usare l’opzione -c 

rsnapshot -c /etc/rsnapshot/rsnapshot-server01.conf daily

(in questo caso il file di configurazione dedicato è /etc/rsnapshot/rsnapshot-web107.conf)

2) Per evitare di creare più cron per backup separati (file configurazione dedicato), così anche da evitare che il successivo sia lanciato prima che il precedente sia terminato causandone il fallimento, si possono raggruppare i comandi cron in uno solo, separandoli con il ; come ad esempio:

rsnapshot daily | \/usr/local/bin/rsnapreport.pl | mail -s "Report Backup rsnapshot localhost" email@mia.xx ; rsnapshot -c /etc/rsnapshot/rsnapshot-server01.conf daily | \/usr/local/bin/rsnapreport.pl | mail -s "Report Backup rsnapshot server01" email@mia.xx

3) rsnapshot supporta anche backup di tipo più complessi, è infatti possibile specificare uno script da far girare prima di effettuare il backup. Tutti i file creati nella directory di lavoro dello script stesso, verranno trattati come contenuti della directory sorgente e copiati nell’opportuna directory destinazione.

Ad esempio, per backuppare uno o più database MySQL, possiamo modificare il file rsnapshot.conf inserendo in esso la stringa:

 backup_script /sbin/backup_mysql.sh mysql/

In questo modo rsnapshot eseguirà /sbin/backup_mysql.sh. Nel nostro caso, tale script contiene:

 #!/bin/bash

USER="root"
HOST="fileserver.testrsnapshot.local"
PORT="2022" # ssh su porta non standard
CREDENTIALS="/root/.my.cnf"
DB_NAME="database_db”
for DB in $DB_NAME; do
ssh $USER@$HOST -p$PORT /usr/bin/mysqldump
--defaults-extra-file=$CREDENTIALS $DB > $DB.sql
/bin/chmod 600 $DB.sql
done

le credenziali di accesso sono state inserite nel file /root/.my.cnf come da esempio (naturalmente indicare il proprio user e password ed eventualmente dell’host):

 [client]
user = root
password = password
host = localhost

Lanciando rsnapshot daily sarà eseguito anche il dump del database remoto e portarlo in locale.

 

Lascia un commento