Sauvegardes Linux : rsync, cron et restauration

Administration Serveur 01/04/2026 22:00:00 angularforall.com
Sauvegarde Rsync Linux Cron Restauration Mysql Backup Gpg
Sauvegardes Linux : rsync, cron et restauration

Stratégie de sauvegarde 3-2-1 sur Linux : scripts rsync avec rotation, sauvegarde MySQL/PostgreSQL, chiffrement GPG, cron planifié et procédure de restauration testée.

La regle 3-2-1 appliquee a un VPS

La regle 3-2-1 est le standard de l'industrie pour les sauvegardes fiables. Elle stipule qu'il faut maintenir 3 copies des donnees, sur 2 supports differents, dont 1 copie hors site. Appliquee a un VPS Linux, elle se traduit ainsi :

  • Copie 1 : les donnees en production sur le VPS principal.
  • Copie 2 : une sauvegarde locale sur un second disque ou volume attache au meme serveur.
  • Copie 3 (hors site) : une sauvegarde distante sur un autre serveur, un NAS ou un stockage cloud (S3, Backblaze B2, etc.).
A retenir : une sauvegarde stockee uniquement sur le meme serveur que les donnees sources ne vous protege pas d'une panne disque, d'une compromission ou d'une suppression accidentelle de la machine entiere.

Que sauvegarder en priorite ?

Sur un VPS classique hebergeant une application web, les elements critiques sont les suivants :

Element Chemin typique Frequence recommandee
Fichiers applicatifs/var/www/Quotidien
Bases de donneesExport SQLQuotidien voire toutes les heures
Configuration Nginx / Apache/etc/nginx/Apres chaque modification
Cron et scripts/etc/cron.d/, /home/Hebdomadaire
Certificats SSL/etc/letsencrypt/Apres chaque renouvellement

rsync : options essentielles et sauvegarde incrementale

rsync est l'outil de reference pour synchroniser des fichiers sur Linux. Il ne transfere que les blocs modifies, ce qui le rend tres efficace meme sur de gros volumes. Voici les options les plus importantes a connaitre :

Option Signification
-aMode archive : preserve permissions, dates, liens symboliques, groupes
-vMode verbose : affiche les fichiers transferes
-zCompresse les donnees pendant le transfert SSH
--deleteSupprime les fichiers cibles qui n'existent plus a la source
--link-destCree des liens physiques vers une sauvegarde precedente (sauvegarde incrementale)
--excludeExclut des fichiers ou dossiers du transfert
-e "ssh -p 22"Specifie la commande SSH a utiliser pour le transport
--dry-runSimule le transfert sans rien modifier (utile pour tester)

Sauvegarde simple vers un serveur distant

La commande suivante synchronise tout le dossier /var/www/ vers un serveur de sauvegarde distant. Le slash final apres la source est important : il signifie "le contenu de ce dossier" et non "ce dossier lui-meme".

# Sauvegarde complete de /var/www/ vers un serveur distant
# user@backup : utilisateur SSH sur le serveur de sauvegarde
# /backups/www/ : repertoire de destination sur le serveur distant
rsync -avz --delete \
    /var/www/ \
    user@backup:/backups/www/

Sauvegarde incrementale avec --link-dest

L'option --link-dest est la cle des sauvegardes incrementales efficaces. Elle indique a rsync de creer des liens physiques (hard links) vers les fichiers identiques de la sauvegarde precedente plutot que de les recopier. Resultat : chaque snapshot du jour parait complet mais n'occupe que l'espace des fichiers modifies.

# Principe des sauvegardes incrementales avec hard links
# PREV_BACKUP : chemin de la sauvegarde du jour precedent
# CURRENT_BACKUP : repertoire de la sauvegarde du jour en cours

rsync -avz \
    --link-dest=/backups/www/2026-04-30 \
    /var/www/ \
    user@backup:/backups/www/2026-05-01

# Chaque dossier date semble contenir TOUS les fichiers,
# mais les fichiers inchanges ne prennent pas d'espace supplementaire
# grace aux liens physiques (inodes partages).
Note : pour exclure les fichiers de cache, logs ou uploads temporaires du transfert, ajoutez des options --exclude : --exclude="cache/", --exclude="*.log", --exclude="tmp/".

Script Bash complet avec rotation sur 7 jours

Un bon script de sauvegarde doit : nommer les sauvegardes avec la date du jour, utiliser --link-dest pour les sauvegardes incrementales, supprimer automatiquement les sauvegardes plus vieilles que 7 jours, et journaliser les operations pour faciliter le diagnostic.

#!/bin/bash
# =============================================================
# Script : backup-www.sh
# Usage  : sudo bash /usr/local/bin/backup-www.sh
# Role   : Sauvegarde incrementale de /var/www/ avec rotation 7j
# =============================================================

# --- Configuration ---
SRC="/var/www/"                          # Source a sauvegarder
DEST="/backups/www"                      # Dossier de destination local
REMOTE_USER="backupuser"                 # Utilisateur SSH distant
REMOTE_HOST="backup.example.com"         # Serveur de sauvegarde
REMOTE_DEST="/backups/vps1/www"          # Chemin distant
RETENTION_DAYS=7                         # Nombre de jours a conserver
LOG_FILE="/var/log/backup-www.log"       # Fichier de log
ALERT_EMAIL="admin@example.com"          # Email pour les alertes

# --- Date du jour au format YYYY-MM-DD ---
TODAY=$(date +%F)
YESTERDAY=$(date -d "yesterday" +%F)

# --- Chemins de sauvegarde ---
BACKUP_TODAY="${DEST}/${TODAY}"
BACKUP_YESTERDAY="${DEST}/${YESTERDAY}"

# --- Fonction de log horodate ---
log() {
    echo "[$(date '+%Y-%m-%d %H:%M:%S')] $1" | tee -a "${LOG_FILE}"
}

log "=== Debut sauvegarde : ${TODAY} ==="

# --- Creation du dossier de destination si absent ---
mkdir -p "${DEST}"

# --- Sauvegarde incrementale locale avec hard links ---
if [ -d "${BACKUP_YESTERDAY}" ]; then
    # La sauvegarde d'hier existe : on l'utilise comme reference
    log "Sauvegarde incrementale base sur ${BACKUP_YESTERDAY}"
    rsync -avz \
        --link-dest="${BACKUP_YESTERDAY}" \
        --exclude="cache/" \
        --exclude="*.log" \
        --exclude="tmp/" \
        "${SRC}" "${BACKUP_TODAY}" >> "${LOG_FILE}" 2>&1
else
    # Aucune reference : premiere sauvegarde complete
    log "Premiere sauvegarde complete (pas de reference precedente)"
    rsync -avz \
        --exclude="cache/" \
        --exclude="*.log" \
        --exclude="tmp/" \
        "${SRC}" "${BACKUP_TODAY}" >> "${LOG_FILE}" 2>&1
fi

# --- Verification du resultat de rsync ---
RSYNC_STATUS=$?
if [ "${RSYNC_STATUS}" -ne 0 ]; then
    log "ERREUR : rsync a echoue avec le code ${RSYNC_STATUS}"
    echo "ERREUR backup ${TODAY} sur $(hostname)" | mail -s "[BACKUP FAILED] ${TODAY}" "${ALERT_EMAIL}"
    exit 1
fi

log "rsync termine avec succes"

# --- Synchronisation vers le serveur distant ---
log "Envoi vers ${REMOTE_HOST}..."
rsync -avz \
    --link-dest="${REMOTE_DEST}/${YESTERDAY}" \
    "${BACKUP_TODAY}/" \
    "${REMOTE_USER}@${REMOTE_HOST}:${REMOTE_DEST}/${TODAY}/" >> "${LOG_FILE}" 2>&1

RSYNC_REMOTE_STATUS=$?
if [ "${RSYNC_REMOTE_STATUS}" -ne 0 ]; then
    log "AVERTISSEMENT : echec du transfert distant (code ${RSYNC_REMOTE_STATUS})"
    echo "Backup local OK mais echec transfert distant - ${TODAY}" | \
        mail -s "[BACKUP WARN] transfert distant" "${ALERT_EMAIL}"
else
    log "Transfert distant OK"
fi

# --- Rotation : suppression des sauvegardes de plus de 7 jours ---
log "Rotation : suppression des sauvegardes de plus de ${RETENTION_DAYS} jours"
find "${DEST}" -maxdepth 1 -type d -mtime +${RETENTION_DAYS} | while read OLD_BACKUP; do
    log "Suppression : ${OLD_BACKUP}"
    rm -rf "${OLD_BACKUP}"
done

log "=== Fin sauvegarde : $(date '+%Y-%m-%d %H:%M:%S') ==="

# --- Notification de succes ---
mail -s "[BACKUP OK] $(hostname) - ${TODAY}" "${ALERT_EMAIL}" < "${LOG_FILE}"
exit 0
A retenir : rendez le script executable avec chmod +x /usr/local/bin/backup-www.sh et testez-le manuellement une premiere fois avec --dry-run avant de le planifier dans cron.

Sauvegarder MySQL et PostgreSQL proprement

Les fichiers de donnees bruts d'une base (dossiers /var/lib/mysql/ ou /var/lib/postgresql/) ne doivent jamais etre sauvegardes directement avec rsync pendant que la base est en ligne : le dump risque d'etre incohérent. Il faut utiliser les outils dedies qui garantissent la coherence transactionnelle.

MySQL et MariaDB avec mysqldump

L'option --single-transaction est indispensable pour InnoDB : elle demarre une transaction avant l'export, garantissant un snapshot coherent sans verrouiller les tables. Les options --routines et --triggers exportent aussi les procedures stockees et triggers.

# Export d'une base MySQL/MariaDB avec coherence transactionnelle
# --single-transaction : snapshot coherent pour InnoDB (pas de lock)
# --routines          : inclut les procedures stockees
# --triggers          : inclut les triggers
# gzip                : compresse a la volee pour economiser l'espace
mysqldump \
    --single-transaction \
    --routines \
    --triggers \
    -u root -p dbname \
    | gzip > /backups/db/db_$(date +%F).sql.gz

# Verification : affiche la taille et la date du fichier cree
ls -lh /backups/db/db_$(date +%F).sql.gz
# Script de sauvegarde de TOUTES les bases MySQL d'un coup
# Utile pour les serveurs hebergeant plusieurs applications

MYSQL_USER="root"
MYSQL_PASS="votre_mot_de_passe"     # Idealement, lire depuis ~/.my.cnf
BACKUP_DIR="/backups/mysql"
DATE=$(date +%F)

mkdir -p "${BACKUP_DIR}/${DATE}"

# Recupere la liste de toutes les bases (exclut les bases systeme)
mysql -u "${MYSQL_USER}" -p"${MYSQL_PASS}" -e "SHOW DATABASES;" | \
    grep -Ev "(Database|information_schema|performance_schema|sys|mysql)" | \
    while read DB; do
        echo "Sauvegarde de la base : ${DB}"
        mysqldump \
            --single-transaction \
            --routines \
            --triggers \
            -u "${MYSQL_USER}" -p"${MYSQL_PASS}" \
            "${DB}" | gzip > "${BACKUP_DIR}/${DATE}/${DB}.sql.gz"
    done

echo "Sauvegarde MySQL terminee dans ${BACKUP_DIR}/${DATE}/"
Conseil securite : stockez les credentials MySQL dans ~/.my.cnf plutot que dans les scripts. Creez un utilisateur dedie avec uniquement les privileges SELECT, LOCK TABLES, SHOW VIEW, EVENT pour les sauvegardes.

PostgreSQL avec pg_dump

Pour PostgreSQL, pg_dump garantit toujours un snapshot coherent grace au MVCC (Multi-Version Concurrency Control). Utilisez le flag -Fc pour le format personnalise, plus efficace pour la restauration avec pg_restore.

# Export d'une base PostgreSQL en format SQL compresse
# -U postgres : utilisateur PostgreSQL
# dbname      : nom de la base a sauvegarder
pg_dump -U postgres dbname \
    | gzip > /backups/db/db_$(date +%F).sql.gz

# Ou en format binaire optimise pour pg_restore (recommande)
# -Fc : format custom (supporte la restauration parallele et selective)
pg_dump -U postgres -Fc dbname \
    > /backups/db/db_$(date +%F).dump

# Sauvegarde de TOUTES les bases PostgreSQL (incluant les roles)
pg_dumpall -U postgres \
    | gzip > /backups/db/all_databases_$(date +%F).sql.gz

Rotation des sauvegardes de bases de donnees

# Supprime les fichiers de sauvegarde SQL plus vieux que 14 jours
# -mtime +14 : modifie il y a plus de 14 jours
# \( -name ... \) : cible uniquement les fichiers .gz et .dump
find /backups/db/ \
    -type f \
    \( -name "*.sql.gz" -o -name "*.dump" \) \
    -mtime +14 \
    -delete

echo "Rotation des sauvegardes BDD terminee"

Chiffrer les archives avec GPG

Avant d'envoyer des sauvegardes vers un stockage distant (serveur tiers, cloud), il est indispensable de les chiffrer. GPG (GNU Privacy Guard) permet un chiffrement symetrique (par mot de passe) ou asymetrique (par cle publique/privee). Pour les sauvegardes automatisees, le chiffrement symetrique est le plus simple a mettre en oeuvre.

Chiffrement symetrique AES-256

# Chiffrement d'une archive avec AES-256 (chiffrement symetrique)
# --symmetric      : mode symetrique (cle partagee)
# --cipher-algo    : algorithme de chiffrement (AES256 recommande)
# --batch          : mode non interactif (pour les scripts)
# --passphrase-fd  : lit le mot de passe depuis un descripteur de fichier

# Methode 1 : chiffrement interactif (demande le mot de passe)
gpg --symmetric --cipher-algo AES256 backup.tar.gz
# Produit : backup.tar.gz.gpg

# Methode 2 : chiffrement non interactif via un fichier de passphrase
# (pour les scripts cron - le fichier doit etre en chmod 600)
echo "votre_passphrase_longue_et_aleatoire" > /root/.backup_passphrase
chmod 600 /root/.backup_passphrase

gpg --batch \
    --symmetric \
    --cipher-algo AES256 \
    --passphrase-file /root/.backup_passphrase \
    --output backup.tar.gz.gpg \
    backup.tar.gz
A retenir : ne stockez jamais les cles GPG ou les fichiers de passphrase sur le meme serveur que les backups chiffres. Si le serveur est compromis, les deux sont accessibles simultanement. Conservez la passphrase dans un gestionnaire de mots de passe externe (Bitwarden, 1Password, Vault).

Dechiffrement pour restauration

# Dechiffrement d'une archive GPG
# --output : fichier de sortie dechiffre
# --decrypt : mode dechiffrement

gpg --batch \
    --passphrase-file /root/.backup_passphrase \
    --output backup_restaure.tar.gz \
    --decrypt backup.tar.gz.gpg

# Verification de l'integrite apres dechiffrement
gzip -t backup_restaure.tar.gz && echo "Archive integre" || echo "Archive corrompue"

Integrer GPG dans le script de sauvegarde

# Fragment a ajouter au script backup-www.sh apres la creation de l'archive
# Archive le dossier de sauvegarde du jour en tar.gz, puis chiffre

PASSPHRASE_FILE="/root/.backup_passphrase"  # chmod 600, propriete root
ARCHIVE="${DEST}/${TODAY}.tar.gz"
ENCRYPTED="${DEST}/${TODAY}.tar.gz.gpg"

# Creation de l'archive tar compressee
tar -czf "${ARCHIVE}" -C "${DEST}" "${TODAY}/"

# Chiffrement de l'archive avec GPG
gpg --batch \
    --symmetric \
    --cipher-algo AES256 \
    --passphrase-file "${PASSPHRASE_FILE}" \
    --output "${ENCRYPTED}" \
    "${ARCHIVE}"

# Suppression de l'archive non chiffree apres chiffrement reussi
if [ -f "${ENCRYPTED}" ]; then
    rm -f "${ARCHIVE}"
    echo "Archive chiffree : ${ENCRYPTED}"
else
    echo "ERREUR : echec du chiffrement GPG"
    exit 1
fi

Planifier avec cron et recevoir des alertes par email

Cron est le planificateur de taches standard sur Linux. Il permet d'executer des scripts a des moments precis : chaque jour, chaque semaine, ou a n'importe quelle frequence. La syntaxe d'un crontab se compose de 5 champs de temps suivis de la commande.

Syntaxe crontab

# Format d'une ligne crontab :
# minute  heure  jour_du_mois  mois  jour_de_semaine  commande
#   *       *          *         *         *            /chemin/script.sh
#
# Exemples de valeurs :
# *    : toutes les valeurs possibles
# */5  : toutes les 5 unites
# 2    : exactement la valeur 2
# 1-5  : de 1 a 5 (lundi a vendredi)
# 1,3,5 : lundi, mercredi, vendredi

Crontab complet pour les sauvegardes

# Editer le crontab root : sudo crontab -e
# Ou creer un fichier dans /etc/cron.d/backup

# -------------------------------------------------------
# SAUVEGARDES AUTOMATISEES - VPS PRODUCTION
# -------------------------------------------------------

# Sauvegarde des fichiers web : tous les jours a 2h du matin
# Eviter les heures de pointe (trafic + acces disque)
0 2 * * * root /usr/local/bin/backup-www.sh

# Sauvegarde des bases de donnees : tous les jours a 1h30
# Avant la sauvegarde des fichiers pour avoir un etat coherent
30 1 * * * root /usr/local/bin/backup-databases.sh

# Sauvegarde de la configuration Nginx : tous les dimanches a 3h
# Apres les eventuelles modifications de la semaine
0 3 * * 0 root tar -czf /backups/config/nginx_$(date +\%F).tar.gz /etc/nginx/

# Sauvegarde des certificats Let's Encrypt : le 1er de chaque mois
# Les certificats sont renouvelés automatiquement tous les 90j
0 4 1 * * root tar -czf /backups/config/letsencrypt_$(date +\%F).tar.gz /etc/letsencrypt/

# Verification de la sante des sauvegardes : tous les jours a 8h
# Ce script verifie que les fichiers du jour existent et ne sont pas vides
0 8 * * * root /usr/local/bin/check-backups.sh

Envoyer des alertes par email avec mail

La commande mail (paquet mailutils ou s-nail) permet d'envoyer des notifications depuis les scripts. Associee a un SMTP relay (Postfix ou service externe), elle est le moyen le plus simple d'etre alerte en cas de probleme.

# Installation de mailutils sur Debian/Ubuntu
sudo apt install mailutils -y

# Envoi d'un email de confirmation avec le log en corps de message
# -s : sujet de l'email
# admin@example.com : destinataire
# < /var/log/backup.log : contenu du fichier comme corps du message
mail -s "[BACKUP OK] $(hostname) - $(date +%F)" admin@example.com < /var/log/backup.log

# Envoi d'une alerte en cas d'echec depuis un script
if [ $? -ne 0 ]; then
    echo "La sauvegarde a echoue sur $(hostname) a $(date)" | \
        mail -s "[BACKUP FAILED] Intervention requise" admin@example.com
fi
Alternative moderne : pour des alertes plus fiables, envisagez d'utiliser un webhook Slack, une notification Telegram via bot, ou un service comme PagerDuty ou Healthchecks.io (envoie une alerte si le script ne "check in" pas a l'heure prevue).

Script de verification quotidienne des sauvegardes

#!/bin/bash
# =============================================================
# Script : check-backups.sh
# Role   : Verifie que les sauvegardes du jour existent et
#          ont une taille raisonnable
# =============================================================

BACKUP_DIR="/backups"
DB_DIR="/backups/db"
TODAY=$(date +%F)
ALERT_EMAIL="admin@example.com"
MIN_SIZE_KB=100   # Taille minimale acceptable en KB
ERRORS=0

# Fonction de verification d'un fichier de sauvegarde
check_file() {
    local FILE=$1
    local LABEL=$2

    if [ ! -f "${FILE}" ]; then
        echo "MANQUANT : ${LABEL} (${FILE})" | \
            mail -s "[BACKUP CHECK FAIL] ${LABEL} absent" "${ALERT_EMAIL}"
        ERRORS=$((ERRORS + 1))
    else
        # Verification de la taille minimale
        SIZE=$(du -k "${FILE}" | cut -f1)
        if [ "${SIZE}" -lt "${MIN_SIZE_KB}" ]; then
            echo "TROP PETIT : ${FILE} (${SIZE}KB, min ${MIN_SIZE_KB}KB)" | \
                mail -s "[BACKUP CHECK WARN] ${LABEL} suspect" "${ALERT_EMAIL}"
            ERRORS=$((ERRORS + 1))
        else
            echo "OK : ${LABEL} (${SIZE}KB)"
        fi
    fi
}

# Verifications
check_file "${BACKUP_DIR}/www/${TODAY}" "Sauvegarde www"
check_file "${DB_DIR}/app_db_${TODAY}.sql.gz" "Dump MySQL app_db"

# Rapport final
if [ "${ERRORS}" -eq 0 ]; then
    echo "Toutes les sauvegardes sont presentes et valides."
else
    echo "ATTENTION : ${ERRORS} erreur(s) detectee(s) dans les sauvegardes."
fi

Tester la restauration : la partie oubliee

La plupart des equipes configurent leurs sauvegardes et ne testent jamais la restauration. C'est une erreur critique. Un backup non teste est un backup non fiable. Les tests reguliers revelent les problemes avant qu'une vraie catastrophe ne se produise.

A retenir : un backup non teste n'est pas un backup. Planifiez des tests de restauration mensuels dans votre agenda, exactement comme vous planifiez les deploiements. La restauration doit etre documentee et repetee jusqu'a devenir un reflexe.

Procedure de restauration des fichiers

# =============================================================
# Procedure de restauration depuis une sauvegarde rsync
# =============================================================

# Etape 1 : Identifier la sauvegarde a restaurer
ls -la /backups/www/
# Exemple de sortie :
# drwxr-xr-x 2026-04-28
# drwxr-xr-x 2026-04-29
# drwxr-xr-x 2026-04-30

# Etape 2 : Restauration complete (ecrase les fichiers actuels)
# ATTENTION : couper le serveur web avant la restauration en production
sudo systemctl stop nginx

# Restauration depuis la sauvegarde du 30 avril
rsync -av --delete \
    /backups/www/2026-04-30/ \
    /var/www/

# Etape 3 : Verifier les permissions apres restauration
# rsync -a preserve les permissions mais c'est bon de verifier
ls -la /var/www/

# Etape 4 : Redemarrer le serveur web
sudo systemctl start nginx
sudo systemctl status nginx

Procedure de restauration MySQL

# =============================================================
# Restauration d'une base de donnees MySQL
# =============================================================

# Etape 1 : Dechiffrer l'archive si elle est chiffree avec GPG
gpg --batch \
    --passphrase-file /root/.backup_passphrase \
    --output /tmp/db_restore.sql.gz \
    --decrypt /backups/db/db_2026-04-30.sql.gz.gpg

# Etape 2 : Verifier l'integrite du fichier decompresse
gzip -t /tmp/db_restore.sql.gz && echo "Fichier OK" || echo "Fichier corrompu - STOP"

# Etape 3 : Creer une base de donnees vierge pour la restauration
# (ne jamais restaurer directement en production sans test prealable)
mysql -u root -p -e "CREATE DATABASE dbname_restored;"

# Etape 4 : Importer le dump dans la base de test
zcat /tmp/db_restore.sql.gz | mysql -u root -p dbname_restored

# Etape 5 : Verifier le contenu restaure
mysql -u root -p dbname_restored -e "SHOW TABLES; SELECT COUNT(*) FROM ma_table_principale;"

# Etape 6 : Si le test est concluant, basculer en production
# mysql -u root -p -e "DROP DATABASE dbname; CREATE DATABASE dbname;"
# zcat /tmp/db_restore.sql.gz | mysql -u root -p dbname

# Nettoyage
rm -f /tmp/db_restore.sql.gz

Restauration PostgreSQL

# Restauration depuis un dump pg_dump format SQL
zcat /backups/db/db_2026-04-30.sql.gz | psql -U postgres dbname_restored

# Restauration depuis un dump format custom (pg_restore)
# -d : base de destination
# -j 4 : restauration parallele sur 4 coeurs (plus rapide)
pg_restore -U postgres \
    -d dbname_restored \
    -j 4 \
    /backups/db/db_2026-04-30.dump

Script de test de restauration automatise

#!/bin/bash
# =============================================================
# Script : test-restore.sh
# Role   : Teste la restauration de la derniere sauvegarde BDD
#          dans une base temporaire et envoie un rapport
# =============================================================

BACKUP_DIR="/backups/db"
TEST_DB="restore_test_$(date +%s)"    # Nom unique avec timestamp
ALERT_EMAIL="admin@example.com"
LATEST_DUMP=$(ls -t "${BACKUP_DIR}"/*.sql.gz 2>/dev/null | head -1)

if [ -z "${LATEST_DUMP}" ]; then
    echo "ERREUR : aucun dump trouve dans ${BACKUP_DIR}" | \
        mail -s "[RESTORE TEST FAIL] Aucun dump disponible" "${ALERT_EMAIL}"
    exit 1
fi

echo "Test de restauration depuis : ${LATEST_DUMP}"

# Creation de la base de test
mysql -u root -p"${MYSQL_ROOT_PASS}" -e "CREATE DATABASE ${TEST_DB};"

# Restauration
zcat "${LATEST_DUMP}" | mysql -u root -p"${MYSQL_ROOT_PASS}" "${TEST_DB}"
RESTORE_STATUS=$?

if [ "${RESTORE_STATUS}" -eq 0 ]; then
    # Verification : compte les tables restaurees
    TABLE_COUNT=$(mysql -u root -p"${MYSQL_ROOT_PASS}" \
        -e "SELECT COUNT(*) FROM information_schema.tables WHERE table_schema='${TEST_DB}';" \
        --skip-column-names 2>/dev/null)
    echo "Restauration reussie : ${TABLE_COUNT} tables restaurees depuis ${LATEST_DUMP}" | \
        mail -s "[RESTORE TEST OK] $(hostname) - $(date +%F)" "${ALERT_EMAIL}"
else
    echo "ECHEC de la restauration depuis ${LATEST_DUMP}" | \
        mail -s "[RESTORE TEST FAIL] Intervention requise" "${ALERT_EMAIL}"
fi

# Nettoyage de la base de test
mysql -u root -p"${MYSQL_ROOT_PASS}" -e "DROP DATABASE IF EXISTS ${TEST_DB};"
echo "Base de test ${TEST_DB} supprimee"

Checklist sauvegarde/restauration production

Utilisez cette checklist avant de considerer votre strategie de sauvegarde comme operationnelle en production. Chaque point doit etre verifie et documente.

Configuration initiale

  • La regle 3-2-1 est respectee (3 copies, 2 supports, 1 hors site).
  • Le script de sauvegarde des fichiers est en place et executable.
  • Le script de sauvegarde des bases de donnees utilise --single-transaction (MySQL) ou pg_dump (PostgreSQL).
  • La rotation des sauvegardes est configuree (7 jours minimum).
  • Les sauvegardes distantes sont chiffrees avec GPG.
  • La passphrase GPG est stockee hors du serveur.
  • Les cron jobs sont en place et les horaires ne se chevauchent pas.
  • Les alertes email (ou autre) sont configurees et testees.

Verification quotidienne / hebdomadaire

  • Les fichiers de sauvegarde du jour existent et ont une taille coherente.
  • Les logs de sauvegarde ne contiennent pas d'erreurs.
  • L'espace disque disponible sur le serveur de sauvegarde est suffisant.
  • Les emails d'alerte arrivent correctement dans la boite mail.

Tests mensuels obligatoires

  • Une restauration complete des fichiers a ete testee avec succes.
  • Un dump base de donnees a ete restaure dans une base de test et verifie.
  • Le temps de restauration complet a ete mesure et documente.
  • La procedure de restauration est a jour dans le runbook d'equipe.
Action Frequence Responsable Outil
Sauvegarde fichiersQuotidien 2hCronrsync + GPG
Sauvegarde BDDQuotidien 1h30Cronmysqldump / pg_dump
Verification existenceQuotidien 8hCroncheck-backups.sh
Test restaurationMensuelSysAdmintest-restore.sh
Revue espace disqueHebdomadaireSysAdmindf -h
Mise a jour documentationApres chaque changementEquipeRunbook / Wiki
Bonne pratique : conservez une copie imprimee ou hors ligne de la procedure de restauration. En cas de compromission grave du serveur, vous n'aurez peut-etre pas acces a votre documentation en ligne.

Conclusion

Mettre en place une strategie de sauvegarde solide sur Linux repose sur trois piliers : des outils fiables (rsync, mysqldump, gpg), une planification rigoureuse avec cron, et des tests de restauration reguliers. La regle 3-2-1 offre le cadre minimal pour se proteger des scenarios les plus courants : panne materielle, erreur humaine et compromission.

Le point le plus negliges reste systematiquement le test de restauration. Automatisez-le avec un script mensuel, mesurez le temps de restauration et documentez la procedure dans votre runbook. C'est cette pratique qui transforme une "configuration de sauvegarde" en une veritable strategie de continuite de service.

A retenir : la valeur d'une sauvegarde se mesure uniquement au moment de la restauration. Testez, mesurez, documentez — et recommencez chaque mois. Un systeme de sauvegarde non teste est une fausse securite.

Partager