1

Récupération d'articles d'archives

This commit is contained in:
2026-03-29 03:00:47 +02:00
parent 060119c91c
commit ecc25fe7cf
592 changed files with 17498 additions and 8153 deletions

View File

@@ -0,0 +1,421 @@
---
comments_url: https://com.richard-dern.fr/post/526
date: '2012-02-19 00:14:00'
dossier:
- Créer son propre Cloud
links:
- lang: fr
name: Page d'origine sur Archive.org
url: https://web.archive.org/web/20120221004524/http://ingnu.fr/2012/02/19/sauvegarder-et-restaurer-son-serveur/
tags:
- Backup
- rsync
- Sauvegarde
title: Sauvegarder et restaurer son serveur
weather:
humidity: 96
illuminance: 0.0
precipitations: true
pressure: 1012.4
source:
- open-meteo
temperature: 3.6
wind_direction: 226
wind_speed: 16.5
weight: 14
---
Maintenant que nous disposons d'un serveur pratiquement complet pour [avoir son propre cloud](https://web.archive.org/web/20120221004524/http://ingnu.fr/category/creer-son-propre-cloud/), que nous avons [renforcé sa sécurité](https://web.archive.org/web/20120221004524/http://ingnu.fr/2012/02/13/renforcer-la-securite-de-son-serveur/) et que nous avons vu comment [opérer un monitoring basique](https://web.archive.org/web/20120221004524/http://ingnu.fr/2012/02/13/trucs-et-astuces-pour-son-serveur-prive/), nous allons voir comment sauvegarder et restaurer son serveur.
Nous allons faire appel au fameux [rsync](https://web.archive.org/web/20120221004524/http://rsync.samba.org/), pour ne pas encombrer notre serveur de solutions aussi lourdes à installer qu'à configurer, d'autant que je vous propose un script qui va simplifier tout ça, et même plus encore...
Vous pouvez placer ce script n'importe où : sur le serveur qui héberge vos services, sur votre propre machine, sur un serveur séparé, un NAS qui supporte rsync et l'authentification par clé, etc.
Il suffit de configurer un peu le script pour que la sauvegarde se fasse presque toute seule.
Elle est pas belle la vie Libre ?
## Choisir son dispositif de stockage
Communément, on sauvegarde sur une partition séparée, de préférence sur un disque séparé, peut être dans une machine séparée, ultimement dans un local séparé.
Il n'y a véritablement que deux prérogatives à l'utilisation du script que je vous propose : la machine doit pouvoir utiliser rsync, et l'authentification par clé.
Toute distribution GNU/Linux en est capable, vous ne devriez donc pas avoir trop de mal à disposer d'une plateforme adéquate.
Évidemment, une autre prérogative s'impose d'elle-même : l'espace disque disponible.
À titre d'exemple, sachez que j'utilise ce script pour sauvegarder deux serveurs et les documents d'une dizaine de personnes.
Le premier, celui qui héberge ingnu.fr, héberge aussi tout un tas d'autres sites, un serveur mail d'une dizaine d'utilisateurs, les bases de données, etc.
Au total, un snapshot des deux machines occupe à l'heure actuelle 7.6Go.
Mon script vous permet de disposer de deux types de sauvegardes : un instantané (appelé *snapshot*) et un instantané de chaque heure de chaque jour.
Le premier instantané est en réalité vieux au maximum d'une minute, tandis que les autres instantanés vous permettent de remonter dans le temps par tranche d'une heure, sur un nombre de jours que vous pouvez déterminer.
Au final, sur cinq jours (qui est le réglage par défaut), l'espace disque total occupé par les sauvegardes n'est que doublé : il est actuellement de 13Go.
Seuls les fichiers modifiés occupent la différence entre l'espace total et l'espace initial.
Vous n'avez donc pas besoin d'un disque de plusieurs téraoctets, à moins que vous ne vouliez sauvegarder aussi des fichiers comme des vidéos ou des distributions GNU/Linux en quantité industrielle...
## Créer la clé d'authentification
La communication entre le serveur et la machine qui exécute la sauvegarde (qui peut aussi être la même machine donc) se fait via rsync, donc ssh.
La connexion est par conséquent chiffrée, et les transferts sont intelligents : la bande passante est minimisée.
Pour pouvoir tout sauvegarder d'un coup, on va donc sauvegarder en tant que root.
Si vous sauvegardez depuis une machine distante, créez une clé avec la commande suivante :
```bash
ssh-keygen -t rsa -f ~/.ssh/id_rsa_backup
```
Que vous enverrez au serveur via la commande :
```bash
ssh-copy-id -i ~/.ssh/id_rsa_backup.pub root@exemple.fr
```
Vous devrez saisir le mot de passe root de la machine distante.
Testez enfin l'accès :
```bash
ssh root@exemple.fr
```
Vous devriez être connecté sans avoir eu besoin de saisir votre mot de passe.
## Créer le script de sauvegarde
Créez un répertoire dédié au script et à sa configuration :
```bash
mkdir -p /scripts/backup
cd /scripts/backup
mkdir conf.d include.d exclude.d
```
Pour respecter le [Standard de Hiérarchie des Systèmes de Fichiers](https://web.archive.org/web/20120221004524/http://www.pathname.com/fhs/), nous devrions placer le script dans */usr/bin*, et la configuration dans */etc/backup*.
Rien ne vous empêche de procéder de la sorte, à condition de modifier les chemins d'accès dans le script que nous allons voir tout de suite :
```bash
nano backup
```
```text
#!/bin/bash
###############################################################################
# Variables #
###############################################################################
my_pid=$$
my_dir=$(dirname $0)
pid_file="/var/run/backup.pid"
conf_dir="$my_dir/conf.d"
include_dir="$my_dir/include.d"
exclude_dir="$my_dir/exclude.d"
log_dir="/var/log/backup"
log_file="$log_dir/backup"
rsync_args="--archive --recursive --delete --delete-excluded"
backup_root="/mnt/backup"
rsync=$(which rsync)
current_date=$(date "+%Y-%m-%d")
current_minute=$(date +%M)
current_hour=$(date +%H)
yesterday_date=$(date --date "yesterday" "+%Y-%m-%d")
max_age=5
oldest_backup=$(date --date "$max_age days ago" "+%Y-%m-%d/%H")
oldest_log=$(date --date "$max_age days ago" "+%Y-%m-%d")
###############################################################################
# Fonctions #
###############################################################################
function check_pid() {
if [ -f "$pid_file" ]
then
old_pid=$(cat "$pid_file")
old_pid_exists=$(ps -p $old_pid | grep -v TTY | awk -F " " '{print $1}')
if [ "$old_pid_exists" != "" ]
then
exit
fi
fi
}
function log() {
if [ "$2" == "true" -o "$2" == "TRUE" -o "$2" == "yes" -o "$2" == "YES" -o "$2" == "1" ]
then
log_date=$(date "+%d/%m/%Y %H:%M:%S")
echo "[$log_date] $1" >> "$log_file"
else
echo "$1" >> "$log_file"
fi
}
function check_dir() {
if [ ! -d "$1" ]
then
mkdir -p "$1"
fi
}
###############################################################################
# Lancement de la procédure #
###############################################################################
##### Vérification des journaux ###############################################
check_dir "$log_dir"
if [ ! -f "$log_file" ]
then
touch "$log_file"
fi
##### Déplacement des anciens journaux ########################################
if [ "$current_hour" == "00" -a "$current_minute" == "00" ]
then
mv "$log_file" "$log_file-$yesterday_date"
fi
##### Démarrage de la procédure ###############################################
check_pid
echo $my_pid > "$pid_file"
start_date=$(date "+%d/%m/%Y %H:%M:%S")
log " "
log "###############################################################################"
log "# Début de la procédure : $start_date #"
log "###############################################################################"
log " "
list=$(ls "$conf_dir")
for host in $list; do
conf_file="$conf_dir/$host"
source "$conf_file"
host_rsync_args="$rsync_args"
host_snapshot="$backup_root/$host/snapshot"
if [ "$ENABLED" != "yes" -a "$ENABLED" != "YES" -a "$ENABLED" != "true" -a "$ENABLED" != "TRUE" -a "$ENABLED" != "1" ]
then
log "**** L'hôte $host est désactivé ****"
log " "
continue
fi
log "**** Traitement de l'hôte $host ****"
log " "
source="$SOURCE"
target="$host_snapshot"
check_dir "$target"
log "Source : $SOURCE" true
log "Destination : $target" true
if [ -f "$include_dir/$host" ]
then
log "Un fichier d'inclusion existe : $include_dir/$host" true
host_rsync_args="$host_rsync_args --files-from=$include_dir/$host"
fi
if [ -f "$exclude_dir/$host" ]
then
log "Un fichier d'exclusion existe : $exclude_dir/$host" true
host_rsync_args="$host_rsync_args --exclude-from=$exclude_dir/$host"
fi
log "Commande : $rsync $host_rsync_args $source $target" true
log "Démarrage de la création ou mise à jour de l'instantané..." true
$rsync $host_rsync_args $source $target
log "Création ou mise à jour de l'instantané terminée" true
##### Sauvegarde périodique ###############################################
if [ "$current_minute" == "00" ]
then
log " "
log "Sauvegarde périodique" true
source="$host_snapshot/"
target="$backup_root/$host/$current_date/$current_hour/"
check_dir "$target"
log "Source : $source" true
log "Destination : $target" true
log "Commande : $rsync $host_rsync_args --links-dest=$source $SOURCE $target" true
log "Démarrage de la sauvegarde périodique..." true
$rsync $host_rsync_args --link-dest="$source" "$SOURCE" "$target"
log "Sauvegarde périodique terminée" true
fi
##### Suppression des anciennes sauvegardes ###############################
log " "
log "Recherche d'une ancienne sauvegarde ($backup_root/$host/$oldest_backup)..." true
if [ -d "$backup_root/$host/$oldest_backup" ]
then
log "Une ancienne sauvegarde existe : $backup_root/$host/$oldest_backup" true
log "Suppression de la sauvegarde la plus ancienne..." true
rm -rf "$backup_root/$host/$oldest_backup"
log "Suppression terminée" true
else
log "Il n'existe pas d'ancienne sauvegarde" true
fi
log " "
done
end_date=$(date "+%d/%m/%Y %H:%M:%S")
log "###############################################################################"
log "# Fin de la procédure : $end_date #"
log "###############################################################################"
log " "
rm -f "$pid_file"
```
Important : Veuillez noter que ce script me convient bien : rien ne vous empêche de faire des ajustements pour qu'il vous corresponde à VOUS !
Notice : Modifiez impérativement la variable *backup_root* !
Quelques explications.
Si vous voulez respecter les FHS, modifiez les variables *conf_dir*, *include_dir* et *exclude_dir*.
Vous pouvez également modifier la variable *max_age*, dont la valeur (un entier) représente le nombre de jours à conserver.
Ensuite, quelques fonctions classiques : recherche d'un pid existant (pour ne pas lancer deux sauvegardes simultanées), journalisation, et recherche et création de répertoire.
La procédure commence alors par la vérification de l'existence des journaux et leur archivage.
Puis, le script récupère la liste des fichiers contenus dans *conf.d*, lit chacun d'entre eux pour obtenir deux directives de configuration (*$ENABLED* true/false et *$SOURCE* représentant la source à sauvegarder), recherche s'il existe un fichier d'inclusion (il vaut mieux sinon vous sauvegardez toute la partition, se trouve dans le répertoire *include.d*) et un fichier d'exclusion (facultatif, se trouve dans *exclude.d*).
Chaque minute (via une tâche cron), le script se lance, et créé ou met à jour l'instantané (le contenu du répertoire *$backup_root/$host/snapshot*).
Chaque heure, ce snapshot est créé dans un répertoire distinct, en faisant appel aux hard links : le fichier n'est pas copié, mais un hard link est créé.
Autrement dit, le fichier est accessible depuis deux adresses différentes.
Même si la source (dans le *snapshot*) est supprimée, le fichier existe toujours grâce au hard link.
Dans notre cas, cela nous permet d'économiser de l'espace disque.
La conséquence de cette façon de procéder est de disposer à tout instant d'une image complète du système de fichiers sauvegardé.
Et le but, c'est de le restaurer en une ligne de commande (une simple copie suffira).
Enfin, on supprime les instantanés les plus anciens.
Attribuez le droit d'exécution au script :
```bash
chmod +x backup
```
## Configuration
Vous disposez donc d'un répertoire *conf.d, include.d* et *exclude.d*.
Le premier contiendra un fichier par machine à sauvegarder.
Vous pouvez nommer ce fichier comme bon vous semble.
Une seule règle à respecter : ce nom devra être le même que celui du fichier d'inclusions et du fichier d'exclusions.
Créons la configuration de notre cloud :
```bash
nano conf.d/my_cloud
```
```text
ENABLED=true
SOURCE=/
```
Si le serveur est une machine différente, on utilisera la notation suivante :
```text
SOURCE="root@exemple.fr:/"
```
Avec cette configuration, on va sauvegarder l'ensemble de la machine concernée (ou plus exactement, l'intégralité de la partition */*).
Ce n'est probablement pas ce que vous voulez, alors nous devons créer un fichier d'inclusions :
```bash
nano include.d/my_cloud
```
À peu de chose près, vous devriez mettre ceci :
```text
/etc/amavis
/etc/apache2
/etc/bind
/etc/clamav
/etc/dovecot
/etc/php5
/etc/postfix
/etc/prosody
/etc/rc.local
/etc/spamassassin
/etc/ssl
/opt
/scripts
/var/vmail
/var/www
/var/lib/mysql
```
Avec ce contenu, vous devriez sauvegarder l'intégralité du serveur que nous avons configuré jusqu'à maintenant.
Pour éviter de sauvegarder des choses inutiles, créons un fichier d'exclusions :
```bash
nano exclude.d/my_cloud
```
```text
log
```
## Lancement
On édite la crontab de l'utilisateur qui procède à la sauvegarde :
```bash
crontab -e
```
```text
* * * * * /scripts/backup/backup
```
Et on vérifie le contenu du journal :
```bash
tail -f /var/log/backup/backup
```
## Restauration
Pour restaurer votre serveur, il suffit de copier vers lui tout ou partie de la dernière sauvegarde valide, via *scp*, tout simplement.
Inutile de tergiverser : grâce à ce système de sauvegarde, il suffit d'une simple copie sécurisée pour restaurer le dernier état valide du serveur; contrairement à d'autres solutions de sauvegarde, pas besoin d'installer un agent sur la machine distante, une simple connexion ssh suffit !
## Conclusion
Nous voici arrivés à la fin de la série d'articles sur la création de son cloud personnel.
Plus qu'un article à publier d'ici quelques minutes, alors à tout de suite !