<h2>But de ce document</h2>
<p class="spip">Ce document me sert de <strong class="spip">mémo</strong> pour installer et configurer un serveur de sauvegardes. Les sauvegardes seront effectuées sur des disques durs externes connectés en usb2. Chaque jour, le disque dur sera déconnecté, mis au coffre ignifugé et remplacé par un autre disque usb.</p>

<h2>Installation d’une Debian Testing (Etch) de Base</h2>
<p class="spip">J’ai choisi une Debian Testing (Etch) pour avoir une gestion des périphériques amovibles plus récente que celle actuellement disponible sous Debian Sarge.</p>

<p class="spip">J’ai donc commencé par installer ma Debian Testing en suivant ce mémo :
<br /></p>
<li> <a href="http://www.coagul.org/article.php3?id_article=158" class="spip_out">http://www.coagul.org/article.php3 ?id_article=158</a>
<h2>Montage du disque dur usb</h2>
<p class="spip">J’ai commencé par vérifier que mon disque dur était correctement reconnu par le système en regardant les messages lors de la connexion et déconnexion du disque dur. De plus, la lecture de ces messages permet de connaître le nom du périphérique qui est dans mon cas « <strong class="spip">/dev/sda</strong> » :</p>

<p class="spip"><code class='spip_code' dir='ltr'># tail -f /var/log/syslog</code></p>

<p class="spip">Cette commande permet de connaître les différentes partitions et le système de fichier utilisé :</p>

<p class="spip"><code class='spip_code' dir='ltr'># fdisk -l /dev/sda</code></p>

<p class="spip">Comme la partition « sda1 » était formatée en ntfs, j’ai commencé par la reformater en ext2</p>

<p class="spip"><code class='spip_code' dir='ltr'># mke2fs /dev/sda1</code></p>

<p class="spip"><strong class="spip">Remarque 1 </strong> : Je ne pense pas qu’un système de fichier journalisé comme ext3 soit nécessaire pour ce type d’utilisation :</p>

<p class="spip"><strong class="spip">Remarque 2</strong> : Le formatage d’un disque de 500Go prend plusieurs minutes.</p>

<p class="spip">Ensuite, j’ai créé un dossier pour recevoir le montage de la partition :</p>

<p class="spip"><code class='spip_code' dir='ltr'># mkdir /mnt/sda1</code></p>

<p class="spip">Et j’ai monté la partition :</p>

<p class="spip"><code class='spip_code' dir='ltr'># mount /dev/sda1 /mnt/sda1</code></p>

<p class="spip">Pour des raisons de sécurité, je souhaite laisser l’accès à cette partition uniquement au seul utilisateur du serveur (ex : tony). Pour cela, il faut définir les droits sur la partition une fois celle-ci montée :</p>

<div style='text-align: left;' class='spip_code' dir='ltr'><code># chown tony /mnt/sda1<br />
# chmod 700 /mnt/sda1</code></div>
<p class="spip"><strong class="spip">Remarque </strong> : Les commandes précédentes ne fonctionnent pas si le système de fichiers est de type « fat »</p>

<h2>Montage automatique du disque dur au démarrage de l’ordinateur</h2>
<p class="spip">Pour des raisons de sécurité, je ne souhaite pas que le montage automatique se fasse au moment de la connexion du disque, mais au moment du redémarrage de l’ordinateur. J’ai donc ajouté cette ligne dans le fichier « <strong class="spip">/etc/fstab</strong> » :</p>

<p class="spip"><code class='spip_code' dir='ltr'>/dev/sda1    /mnt/sda1    ext2    rw,auto        0       0</code></p>

<p class="spip"><strong class="spip">Remarque </strong> : J’ai volontairement précisé le type de système de fichiers (ext2) pour que le montage échoue en cas d’utilisation d’un disque non formaté en ext2.</p>

<p class="spip">Ensuite avant de lancer les sauvegardes, je lance un redémarrage de l’ordinateur automatique avec la crontab de root (crontab -e) pour être sur que tout est dans un fonctionnement optimum :</p>

<p class="spip"><code class='spip_code' dir='ltr'>50 17 * * * /sbin/reboot</code></p>

<h2>Installation du serveur SSH</h2>
<p class="spip">La sauvegarde des différents serveurs se fera uniquement en passant par ssh. De plus étant donné que ce serveur sera administré à distance, l’installation d’un serveur SSH est donc obligatoire :</p>

<p class="spip">Installation du serveur ssh :</p>

<p class="spip"><code class='spip_code' dir='ltr'># aptitude install openssh-server</code></p>

<p class="spip"><strong class="spip">Remarque </strong> : Lors de la mise au point de ce serveur de sauvegarde, j’ai comparé le temps de sauvegarde en passant par un partage Samba par rapport à l’envoi de fichiers via ssh et il s’est avéré que l’envoi via ssh était deux fois plus rapide. De plus, cette méthode est mieux sécurisée et est plus fiable, car j’ai rencontré quelques soucis de compatibilité entre les différentes versions de Samba de mes serveurs.</p>

<h2>Mise en place des clés publiques ssh sur le serveur de sauvegarde</h2>
<p class="spip">Pour pouvoir automatiser la sauvegarde via ssh, il faut éviter la saisie du mot de passe lors de la connexion. Pour cela, il faut mettre en place une clé privée sur le serveur à sauvegarder et la clé publique correspondante sur le serveur de sauvegarde.</p>

<p class="spip">Création d’une clé privée et d’une clé publique sur le serveur à sauvegarder :</p>

<p class="spip"><code class='spip_code' dir='ltr'># ssh-keygen -t dsa</code></p>

<p class="spip">Mise en place de la clé publique sur le serveur de sauvegardes depuis le serveur à sauvegarder :</p>

<p class="spip"><code class='spip_code' dir='ltr'># ssh-copy-id -i /root/.ssh/id_dsa.pub root@ServeurSauvegarde </code></p>

<p class="spip">Ensuite, il est possible de tester que la connexion au serveur de sauvegarde se fasse désormais sans la saisie du mot de passe :</p>

<p class="spip"><code class='spip_code' dir='ltr'># ssh root@ServeurSauvegarde </code></p>

<h2>Script de sauvegarde</h2>
<p class="spip">Voici le script que j’utilise pour sauvegarder les différents répertoires de mes serveurs. Dans cet exemple, je ne sauvegarde que les répertoires « /etc », « /home » et « /root » :</p>

<div style='text-align: left;' class='spip_code' dir='ltr'><code>#!/bin/bash<br />
<br />
function Save() {<br />
        Heure=`date +"%H:%M:%S"`<br />
        Taille=`du -sh $1 | cut -f1` #Taille du dossier à sauvegarder<br />
        echo "$Heure : Sauvegarde $1 ($Taille)"<br />
        J=`date +%w`<br />
        Serveur=`hostname`<br />
        Destination="/mnt/sda1/$J/$Serveur"<br />
        ssh tony@pglinux01 mkdir -p "$Destination"<br />
        tar czf - "$1" 2>>err.log | ssh tony@pglinux01 "cat ><br />
$Destination/$2.tgz"<br />
}<br />
<br />
rm err.log<br />
Heure=`date +"%H:%M:%S"`<br />
echo "$Heure : DEBUT DE LA SAUVEGARDE DU SERVEUR **********************"<br />
<br />
Save "/etc"     "etc"<br />
Save "/home"    "home"<br />
Save "/root"    "root"<br />
Heure=`date +"%H:%M:%S"`<br />
echo "$Heure : FIN DE LA SAUVEGARDE DU SERVEUR ************************"<br />
echo "** Détail des erreurs pendant la sauvegarde **"<br />
cat err.log</code></div>
<h2>Sauvegarde en automatique</h2>
<p class="spip">Pour automatiser la sauvegarde, j’ajoute simplement dans la crontab de root, la ligne suivante :</p>

<div style='text-align: left;' class='spip_code' dir='ltr'><code>30 20 * * 1-5 /root/MesDocuments/save_serveur_ssh.sh | mail -s "[`hostname`]<br />
Sauvegarde serveur" tg@monserveur</code></div>
<p class="spip">Cette ligne lance le programme de sauvegarde à 20H30 du lundi au vendredi et envoie par mail le résultat de celle-ci</p>

<h2>Sauvegarde et archivage des fichiers avec RSYNC</h2>
<p class="spip">Les sauvegardes précédentes ne concernaient que les fichiers systèmes. Pour les fichiers utilisateurs, il est préférable de garder un historique plus long que 5 jours.</p>

<p class="spip">Le programme « rsync » est tout approprié pour cette opération, car il permet de synchroniser un dossier source avec un dossier de destination tout en créant des backup des fichiers modifiés.</p>

<p class="spip">L’installation consiste à installer ce programme sur le serveur à sauvegarder (la source) et sur le serveur de sauvegarde (la destination) :</p>

<p class="spip"><code class='spip_code' dir='ltr'># aptitude install rsync</code></p>

<p class="spip">Ensuite comme précédemment, il faut :
<br /></p>
<li> Que le serveur de sauvegarde dispose d’un serveur ssh opérationnel
<br /><li> Que la clé publique du serveur à sauvegarder soit placée sur le serveur de sauvegarde pour éviter la saisie des mots de passe.
<p class="spip">Voici un exemple de script de sauvegardes utilisant rsync :</p>

<div style='text-align: left;' class='spip_code' dir='ltr'><code>#!/bin/bash<br />
<br />
Serveur=$1<br />
if [ "$Serveur" == "" ]<br />
then<br />
  echo "Serveur à sauvegarder obligatoire en paramètre"<br />
  exit<br />
fi<br />
<br />
Date=`date +%Y-%m-%d`<br />
Heure=`date +"%H:%M:%S"`<br />
echo "$Heure : Début de la sauvegarde des fichiers de $Serveur *********"<br />
<br />
Source=/mnt/Reseau/$Serveur/ <br />
Destination=/mnt/sda1/0/$Serveur/Fichiersµ<br />
DestinationBackup=/mnt/sda1/0/$Serveur/Backup/$Date-$Heure<br />
<br />
# ** Montage et test que la source est correctment montée ***************<br />
mount $Source<br />
Test=`df -h | grep $Serveur | wc -l`<br />
if [ $Test = 0 ]<br />
then<br />
  echo | mail -s "[$Serveur] Sauvegarde impossible " tony@mondomaine.com<br />
  exit<br />
fi<br />
# ***********************************************************************<br />
<br />
# Si le serveur est innacessible, un message est envoyé *****************<br />
ssh tony@pglinux01 mkdir -p "$Destination" 2>/dev/null<br />
ssh tony@pglinux01 mkdir -p "$DestinationBackup" 2>/dev/null<br />
if [ "$?" == "1" ]<br />
then<br />
  echo | mail -s "[$Serveur] Impossible de sauvegarder" tony@mondomaine.com<br />
else<br />
  rsync -rt --delete --backup --backup-dir=$DestinationBackup $Source<br />
tony@pglinux01:$Destination 2>/tmp/$Serveur.log<br />
fi<br />
cat /tmp/$Serveur.log</code></div>
<h2>Problèmes rencontrés avec rsync</h2>
<p class="spip">Rsync refusait de me faire un backup d’un dossier particulier alors que tout fonctionnait pour les autres dossiers. Après recherche, il s’est avéré que :
<br /></p>
<li> l’attribut lecture seule (Partition NTFS partagée en réseau) était activé
<br /><li> le propriétaire de ce dossier n’existait plus.
<p class="spip">L’attribut « a » est déconseillé en cas de sauvegarde sur un autre système de fichiers (ex ext3 vers fat), car rsync n’arrivera pas à sauvegarder tous les attributs et renverra des messages d’erreurs et en plus il fera un backup de tous les fichiers. Dans ce cas, il faut simplement utiliser « -rt »</p>

<p class="spip">En cas de sauvegarde d’un système ext3 sur un système fat,  il faut également ajouter  l’option « &mdash;modify-window=1 » pour laisser une tolérance d’une seconde entre la date du fichier source et la date du fichier sauvegardé, car un système FAT a une tolérance dans l’heure de deux secondes et un système ext3 d’une seconde.</p>

<p class="spip">Toujours dans le cas d’une sauvegarde d’un système « ext3 » sur un système « fat », certains caractères dans le nom des fichiers ne sont pas reconnus (ex : le signe ’ :’). dans ce cas, une solution consiste à renommer les fichiers avant de les sauvegarder avec par exemple cette commande :</p>

<p class="spip"><code class='spip_code' dir='ltr'>find . -name "*:*" -print -exec rename 's/:/_/g' {} \;</code></p>

<p class="spip">Il est important que le poste original et le poste de destination soient synchronisés sur la même heure, car en cas de différence, cela peut poser des problèmes.</p>

<h2>Redémarrage du serveur avant de lancer les sauvegardes</h2>
<p class="spip">Par mesure de sécurité, je préfère redémarrer automatiquement le serveur avant de lancer les sauvegardes pour au moins une raison :
<br /></p>
<li> Être sur que le disque dure amovible est reconnu comme « /dev/sda » et non pas « /dev/sdb » ou autre chose.
<h2>Sauvegarde de MySQL</h2>
<p class="spip">Pour la sauvegarde d’une base de données, il est conseillé de ne pas sauvegarder les fichiers directement mais d’utiliser les outils spécifiques à la base de données. Il est même conseillé (mais pas obligatoire) d’arrêter la base de données pendant la sauvegarde.</p>

<p class="spip">Voici un exemple de script permettant de sauvegarder dans un fichier chaque table de chaque base de données. Et par mesure de sécurité supplémentaire, j’ai même un fichier contenant chaque base de données complète :</p>

<div style='text-align: left;' class='spip_code' dir='ltr'><code>for LaBase in $(echo 'SHOW DATABASES;' | mysql)<br />
do<br />
    if [ "$LaBase" != "Database" ]; then<br />
        Heure=`date +"%H:%M:%S"`<br />
        echo "$Heure : Sauvegarde de $LaBase"<br />
        mysqldump -Q -c -C --add-drop-table --add-locks --quick $LaBase > /<br />
nt/sdb1/Sauvegardes/mysql/$LaBase.sql<br />
<br />
        for LaTable in $(echo "USE $LaBase; SHOW TABLES;" | mysql)<br />
        do<br />
            if [ "$LaTable" != "Tables_in_$LaBase" ]; then<br />
                #echo "-> Sauvegarde de $LaBase-$LaTable"<br />
                mysqldump -Q -c -C --add-drop-table --add-locks -quick<br />
$LaBase$LaTable > /mnt/sdb1/Sauvegardes/mysql/$LaBase-$LaTable.sql<br />
            fi<br />
        done<br />
    fi<br />
done</code></div>
<p class="spip"><strong class="spip">Remarque </strong> : Il aurait été beaucoup plus simple de sauvegarder toutes les bases de données dans un seul fichier avec le paramètre « &mdash;all-databases », mais comme mes bases de données sont très importantes, j’ai préféré avoir un fichier séparé pour chaque table.</p>

<h2>Sauvegarde d’OpenLDAP</h2>
<p class="spip">La commande suivante permet d’exporter dans un fichier texte le contenu de la base de données LDAP pour être sur de faire une sauvegarde dans de bonnes conditions :</p>

<p class="spip"><code class='spip_code' dir='ltr'># slapcat > /mnt/sdb1/Sauvegardes/openldap/openldap.ldif</code></p>

<h2>Test d’écriture de gros fichiers</h2>
<p class="spip">La taille maximum qu’un fichier peut avoir, dépend de beaucoup de choses (version du noyau Linux, système de fichiers utilisés,..). Le mieux pour être sûr que le système accepte de gros fichiers (ex : 10Go) est de créer un fichier de test avec la commande suivante :</p>

<div style='text-align: left;' class='spip_code' dir='ltr'><code># dd if=/dev/zero of=testfile2 bs=1024k count=10000<br />
10000+0 records in<br />
10000+0 records out<br />
10485760000 bytes (10 GB) copied, 526.987 seconds, 19.9 MB/s</code></div>
<p class="spip"><strong class="spip">Remarque </strong> : Cette commande permet également de connaître la vitesse d’enregistrement.</p>

<h2>Historique des modifications</h2>
<table class="spip">
<thead><tr class='row_first'><th scope='col'><strong class="spip">Version</strong></th><th scope='col'><strong class="spip">Date</strong></th><th scope='col'><strong class="spip">Commentaire</strong></th></tr></thead>
<tbody>
<tr class="row_even"><td>0.2</td><td>01/09/06</td><td>Création par Tony GALMICHE</td></tr>
<tr class="row_odd"><td>0.5</td><td>03/04/07</td><td>Mise à jour suite à mise en place disque de 500Go + Mise en ligne</td></tr>
</tbody>
</table>