Stratégie simple mais efficace de backup local et historisation sous Linux

Vous venez d'installer (ou louer) un nouveau server ou bien un vieux serveur qui tourne depuis un certain temps, et vous vous dites qu'il est temps de faire quelque chose à propos de ses backups. Que ce soit pour garder l'ancienne version de la configuration de votre serveur web ou bien pour garder les photos des soirées qu'il ne faut pas montrer, la gestion des backups est primordiale. De nombreuses solutions sont aujourd'hui possible et en voici une simple et facile à mettre en place.

La théorie

  • Créer un script pour synchroniser le dossier à backuper avec votre dossier de sauvegarde (source avec cible),
  • Créer un script qui s’exécute de façon périodique (par exemple une fois par jour) et qui va créer un "hardlink copy" du dossier de sauvegarde,
  • Créer un script de nettoyage pour ne garder que des copies mensuelles, annuelles...

Script pour le backup

Nous créons un script qui fera une sauvegarde complète du dossier voulu. Un simple cp -r pourrait faire l'affaire, mais afin d'éviter les copies des fichiers inchangés, il est plus simple d'utiliser la commande de synchronisation rsync.

#plain_backup.sh

#! /bin/bash
SOURCE=/path/to/backup
BACKUP_ROOT=/path/to/your/backup_folder/root
rsync -avz $SOURCE/ $BACKUP_ROOT/latest
  • a pour garder les attributs des fichiers synchronisés
  • v pour afficher ce qui est copié
  • z pour compresser (pas nécessaire en local)

Script pour ne garder qu'une copie quotidienne sans consommer tout l'espace disque

Maintenant que le backup est effectif, nous souhaitons ajouter une notion d'historisation. Par exemple, nous souhaitons avoir une photo quotidienne de l'état de notre répertoire (la périodicité peut être ajustée comme on le souhaite, et sera configurable lors de l'automatisation des scripts).

#create_snapshot.sh

#! /bin/bash

BACKUP_ROOT=/path/to/your/backup_folder/root
LATEST=$BACKUP_ROOT/latest
SNAPSHOT_ROOT=$BACKUP_ROOT/snapshots
SNAPSHOT=$SNAPSHOT_ROOT/$(date +'%Y-%m-%d_%H%M%S')

mkdir -p $SNAPSHOT_ROOT
cp -al $LATEST $SNAPSHOT

ce que fait la commande cp:

  • -a pour garder les attributs des fichiers pendant la copie,
  • -l pour créer un lien fixe (hardlink); le contenu du fichier sur le disque sera en réalité le même que celui du fichier source.

A noter que si le fichier a été modifié dans le répertoire "SOURCE", alors la commande rsync aura créée un nouveau fichier dans le répertoire "LATEST" et tous les fichiers sous "BACKUP_ROOT" sont considérés comme lecture seule et ne doivent pas être modifié manuellement ni directement.

Si vous modifiez un fichier dans le répertoire "BACKUP_ROOT", vous modifiez en même temps tous les snapshots contenant ce fichier.

Script de maintenance des backups

Ce petit script va nous permettre de nettoyer (supprimer) les photos (ie. snapshots) des dossiers plus anciens de 30 jours:

#maintain_backups.sh

#! /bin/bash

BACKUP_ROOT=/path/to/your/backup_folder/root

find $BACKUP_ROOT/snapshots -maxdepth 1 -mtime +30 -regex ".*/[0-9\-]*_[0-9]*" -prune -exec rm -rf {} \;
  • -mtime +30 prendra les fichiers et répertoires modifiés depuis plus de 30 jours,
  • -maxdepth 1 pour limiter la recherche uniquement aux sous-dossiers du dossier snapshot (et éviter de supprimer des anciens fichiers de ces dossiers, ce qui serait dommage pour une opération de backup...)
  • -regex "./[0-9\-]*_[0-9]*" pour préciser à la commande find de ne prendre que ce pattern. C'est une sécurité supplémentaire pour éviter que le dossier "BACKUP_ROOT" ne pointe au mauvais endroit comme '/'. Cette partie n'est pas obligatoire si vous savez  ce que vous faites.
  • -prune pour préciser à find de ne pas s’embêter à regarder dans le dossier qui a le nom de matché
  • -exec rm -df {} pour préciser à find de supprimer les dossiers trouvés.

Ajoutez les script en cron

Commençons par créer un méta script "to rule them all":

#backup.sh

#! /bin/bash

./plain_backup.sh
./create_snapshot.sh
./maintain_backups.sh

Ensuite ajoutez un job à la crontab avec la commande crontab -e. Pour les options de la crontab, vous pouvez utiliser un site comme https://crontab.guru qui vous indiquera le résultat du pattern.

* 1 * * * username_to_run_with   /path/to/scripts/backup.sh

Petite note pour la crontab, sur certains systèmes vous pouvez aussi utiliser en root @reboot ou quelques autres raccourcis bien utiles à la place des 5 champs de gestion du temps (plus d'infos dans la man page). Cela peut éviter un script dans init.d ou systemd.