Contexte :

Je dispose d'un serveur avec beaucoup de To disponible pour stocker mes sauvegardes, mais celui-ci n'est pas accesible depuis l'internet (pas d'adresse IPV4 public). Ce serveur de stockage lui peut par contre accéder a l'internet à travers du NAT.

Les sauvegardes ne peuvent donc être initié qu'a partir du serveur de stocakge et non pas a partir des hosts à sauvegarder.

Je ne veux pas non plus faire tourner un dameon rsync sur chacun des hosts, pour un problème de sécurité.

Les deux intératifs a prendre en compte sont :

  • SSH n'ecoute pas forcement sur le port 22 (par default)
  • L'utilisateur backup n'a pas les droits de lecture du tous les fichiers a sauvegarder, pourtant il faudra bien les sauvegarders.

La solution TAR over SSH

La solution TAR over SSH, utilisée jusqu'a maintenant fonctionnait comme ceci :

  • L'utilisateur backup sur chacun des hosts a sauvegarder est présent dans le fichier /etc/sudoers
 Cmnd_Alias    TAR=/bin/tar
 backup ALL=NOPASSWD:TAR

Il peut ainsi a traver la commande TAR accèder en lecture à tous les fichiers.

Depuis le serveur de stocakge, il me suffit alors de lancer la commande suivante pour sauvegarder completement le repertoire /etc/ du server hosts à sauvegarder :

 ssh -p 22 backup@server_ip "/usr/bin/sudo tar zpcf - /etc/ " > /backup/etc.tgz
  • Nous pouvons choisir le port SSH
  • Grace a sudo nous pouvons acceder a tous les fichiers via la commande tar
  • Le résultat du TAR n'est pas ici renvoyé vers un fichier, mais vers la connexion SSH qui à l'autre bout va créer le fichier TGZ.

La solution RSYNC over SSH

La solution RSYNC over SSH, fonctionne comme ceci :

  • L'utilisateur backup sur chacun des hosts a sauvegarder est présent dans le fichier /etc/sudoers
 Cmnd_Alias    RSYNC=/bin/tar
 backup ALL=NOPASSWD:RSYNC

Il peut ainsi a traver la commande RSYNC accèder en lecture à tous les fichiers.

Depuis le serveur de stocakge, il me suffit alors de lancer la commande suivante pour sauvegarder completement le repertoire /etc/ du server hosts à sauvegarder :

 rsync -av --delete --inplace --rsync-path='sudo rsync' --rsh="ssh -p22" backup@server_ip:/etc/ /backup/etc/
  • Nous pouvons choisir le port SSH
  • Grace a sudo nous pouvons acceder a tous les fichiers via la commande RSYNC
  • L'avantage ici d'utiliser rsync, c'est qu'il ne transfert que les nouveaux fichiers, ceux qui ont été mis à jours, et efface ceux qui n'existe plus.

Mise en pace de la solution de sauvegarde avec RSYNC over SSH

Mise en place des accès SSH sans authentification

Sur le serveur de stocakge (depuis l'utilisateur root) :

 ssh-keygen -t dsa
 Generating public/private dsa key pair.
 Enter file in which to save the key (/root/.ssh/id_dsa):
 /root/.ssh/id_dsa already exists.
 Overwrite (y/n)? y
 Enter passphrase (empty for no passphrase):
 Enter same passphrase again:
 Your identification has been saved in /root/.ssh/id_dsa.
 Your public key has been saved in /root/.ssh/id_dsa.pub.
 The key fingerprint is:
 c7:4a:70:a4:de:eb:68:84:6f:f3:05:5f:09:dd:31:b5 backup02

Ne pas indiquer de passphrase, pour une authentification sans mot de passe. (dans ce cas seul la clef publique fera office d'identification)

Sur les hosts à sauvegarder :

Il nous suffit maintenant juste de copier le contenu du fichier /root/.ssh/id_dsa.pub du serveur de stocakge sur les hosts à sauvegader à la fin du fichier /home/backup/.ssh/authorized_keys. (Il se peut que ce fichier n'existe pas, il suffit de le créer).

Test :

Vous pouvez maintenant vous connecter en SSH sur les serveurs hosts avec l'utilisateur backup sans avoir à rentrer de mots de passe.

 ssh backup@server_ip -p 22

Mise en place des outils pour les sauvegardes

Sur les hosts à sauvegarder :

Installer rsync et sudo

 apt-get install rsync sudo

Editer le fichier /etc/sudoers pour y rajouter :

 Cmnd_Alias    RSYNC=/usr/bin/rsync
 exploit ALL=NOPASSWD:RSYNC

Notez qu'il vous faudra (même en root) changer les droits du fichier avant de l'éditer et les remettre avant de relancer sudo :

 chmod 700 /etc/sudoers

Editer le fichier

 chmod 440 /etc/sudoers
 /etc/init.d/sudo restart

Sur le serveur de stocakge :

Toutes les sauvegardes seront stocker dans le repertoire /backup comme ceci /backup/<host>/<date_YYYY-MM-DD>/

Pour lancer une sauvegarde manuellement :

 rsync -av --progress --inplace --rsync-path='sudo rsync' --rsh='ssh -p22' backup@:/etc/ /backup//2009-03-10/etc/

Voici maintenant un script bash permettant de gérer les sauvegardes :

Celui, regarde tout d'abort si une sauvegarde de la veille existe, et si c'est le cas, il copie les fichiers de la veille dans le repertoire du jours avant de lancer le rsync, ce qui permet de limiter l'utilisation de bande passante tout en gardant un historique de sauvegardes.

#!/bin/bash

LocalBackupBase="/backup"

#---------- La configuration des hosts a backup ce trouve en fin de fichier ----------#

DateToday=$(date +%Y-%m-%d)
DateYesterday=$(date --date='1 days ago' +%Y-%m-%d)
RSYNC="/usr/bin/rsync"

function BackupDir() {
        # Initialise Variables
        RemoteLogin=$1;
        RemoteHost=$2;
        RemotePort=$3;
        RemoteBackupDir=$4;
        LocalBackupDir="$LocalBackupBase/$RemoteHost/$DateToday/$RemoteBackupDir";
        echo " > [BACKUP-DIR] Backup $RemoteBackupDir on $RemoteHost to $LocalBackupDir"
        if [ ! -d "$LocalBackupBase/$RemoteHost/$DateToday/$RemoteBackupDir" ]; then
                echo "         | Today local backup directory not exist : $LocalBackupBase/$RemoteHost/$DateToday/$RemoteBackupDir";
                if [ ! -d "$LocalBackupBase/$RemoteHost/$DateYesterday/$RemoteBackupDir" ]; then
                        echo "         | Yesterday backup directory not exist : $LocalBackupBase/$RemoteHost/$DateYesterday/$RemoteBackupDir";
                        echo "         | Create today backup directory : $LocalBackupBase/$RemoteHost/$DateToday/$RemoteBackupDir";
                        mkdir -p $LocalBackupBase/$RemoteHost/$DateToday/$RemoteBackupDir
                        else
                        echo "         | Yesterday backup directory exist : $LocalBackupBase/$RemoteHost/$DateYesterday/$RemoteBackupDir";
                        echo "         | Create today backup directory : $LocalBackupBase/$RemoteHost/$DateToday";
                        mkdir -p $LocalBackupBase/$RemoteHost/$DateToday/
                        echo "         | Copy file from yesterday to today backup directory";
                        mkdir -p $LocalBackupBase/$RemoteHost/$DateToday/$RemoteBackupDir
                        cp -R $LocalBackupBase/$RemoteHost/$DateYesterday/$RemoteBackupDir $LocalBackupBase/$RemoteHost/$DateToday/$RemoteBackupDir
                        fi
                fi
        echo "         | Start at $(date +%Y-%m-%d) $(date +%H:%M:%S)"
        $RSYNC -av --inplace --rsync-path='sudo rsync' --rsh="ssh -p$RemotePort" $RemoteLogin@$RemoteHost:$RemoteBackupDir $LocalBackupDir >> $LocalBackupBase/$RemoteHost/$DateToday/rsync-$DateToday.log
        echo "         | Finish at $(date +%Y-%m-%d) $(date +%H:%M:%S)"
}

function DeleteOlderThan() {
        DayAgo=$1;
        DateRemove=$(date --date="$DayAgo days ago" +%Y-%m-%d)
        NumRemove=$(date --date="$DayAgo days ago" +%Y%m%d)
        echo " > [DEL] Remove backup directory older than $DayAgo - $DateRemove"
        for Host in `find $LocalBackupBase -maxdepth 1 -type d`; do
                if [ $Host != $LocalBackupBase ]; then
                        for line in `find $Host -maxdepth 1 -type d`; do
                                if [ $line != $Host ]; then
                                        DirDate=`echo "$line" | sed -e "s/\(.*\)\/\(.*\)\-\(.*\)\-\(.*\)/\2\3\4/"`
                                        if [ $DirDate -lt $NumRemove ]; then
                                                echo "         | Remove backup directory : $line";
                                                rm $line -Rf
                                        fi
                                fi
                        done
                fi
        done
  }


#---------- Parametrage des backups ----------#
#---------- Ne pas oublier d'installer sudo et rsync sur les hosts a backup ----------#

#On efface les backup de plus de 7 jours
DeleteOlderThan 7

#Backup du repertoire /tmp/ sur le host n°1 - accès SSH sur le port 22 (standard)
BackupDir backup  22 /tmp/

#Backup du repertoire /tmp/ sur le host n°2 - accès SSH sur le port 2222
BackupDir backup  2222 /tmp/