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.).
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 donnees | Export SQL | Quotidien 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 |
|---|---|
-a | Mode archive : preserve permissions, dates, liens symboliques, groupes |
-v | Mode verbose : affiche les fichiers transferes |
-z | Compresse les donnees pendant le transfert SSH |
--delete | Supprime les fichiers cibles qui n'existent plus a la source |
--link-dest | Cree des liens physiques vers une sauvegarde precedente (sauvegarde incrementale) |
--exclude | Exclut des fichiers ou dossiers du transfert |
-e "ssh -p 22" | Specifie la commande SSH a utiliser pour le transport |
--dry-run | Simule 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).
--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
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}/"
~/.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
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
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.
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) oupg_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 fichiers | Quotidien 2h | Cron | rsync + GPG |
| Sauvegarde BDD | Quotidien 1h30 | Cron | mysqldump / pg_dump |
| Verification existence | Quotidien 8h | Cron | check-backups.sh |
| Test restauration | Mensuel | SysAdmin | test-restore.sh |
| Revue espace disque | Hebdomadaire | SysAdmin | df -h |
| Mise a jour documentation | Apres chaque changement | Equipe | Runbook / Wiki |
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.