Avoir un serveur en production sans stratégie de sauvegarde, c’est comme rouler sans ceinture. Ça fonctionne… jusqu’au jour où ça ne fonctionne plus. Cet article détaille la mise en place d’une solution de sauvegarde automatisée, sécurisée et multicouche pour un VPS Ubuntu hébergeant des sites WordPress.
Contexte et architecture cible
L’objectif est de sauvegarder automatiquement les données critiques d’un VPS OVH vers une VM Ubuntu hébergée sur une Freebox Delta à domicile. Les données à protéger sont de deux types :
- Les bases de données MariaDB — le contenu WordPress (articles, pages, médias, configuration)
- Les fichiers serveur — dossiers
/var/www/et configuration nginx/PHP/Let’s Encrypt
VPS OVH (Ubuntu 24.04)
│
│ rsync over SSH (port 9000)
│ clé Ed25519 restreinte à rsync uniquement
▼
Freebox Delta — VM Ubuntu 24.04 (backup-vps)
├─ ~/sauvegardes/mysql/ ← dumps BDD (rétention 30j)
└─ ~/sauvegardes/files/ ← fichiers www + config (rétention 30j)
+ Snapshot OVH automatique quotidien (filet de sécurité)
Principe de sécurité: moindre privilège
Avant d’écrire le moindre script, il faut réfléchir au modèle de menace. La question clé : que se passe-t-il si le VPS est compromis ?
Sans précautions, un attaquant ayant pris le contrôle du VPS pourrait rebondir vers la VM de sauvegarde via la clé SSH de backup — c’est ce qu’on appelle la latéralisation. Pour éviter ça, on applique le principe du moindre privilège à chaque niveau :
- Un utilisateur MariaDB dédié avec droits de lecture uniquement
- Un utilisateur système
backupusersans sudo sur la VM - Une clé SSH restreinte à la commande
rsyncuniquement - Le mot de passe MariaDB stocké dans un fichier protégé, pas dans le script
Préparation de la VM de sauvegarde
La VM Ubuntu 24.04 tourne sur la Freebox Delta avec une IP fixe assignée via bail DHCP statique. Le port forwarding de la Freebox redirige le port 9000 externe vers le port 22 de la VM.
Création de l’utilisateur restreint:
Sur la VM :
sudo adduser --shell /bin/bash --no-create-home backupuser
sudo mkdir -p /home/backupuser/sauvegardes/mysql
sudo mkdir -p /home/backupuser/sauvegardes/files
sudo chown -R backupuser:backupuser /home/backupuser
sudo chmod 700 /home/backupuser
Génération de la clé SSH dédiée sur le VPS
Sur le VPS OVH, on génère une paire de clés sans passphrase (indispensable pour l’automatisation via cron) :
ssh-keygen -t ed25519 -C "vps-ovh-backup" -f ~/.ssh/id_ed25519_backup
La passphrase est laissée vide volontairement : un script cron ne peut pas saisir de passphrase interactivement.
Restriction de la clé SSH à rsync uniquement
C’est la mesure de sécurité la plus importante. On ajoute la clé publique du VPS dans le fichier authorized_keys de backupuser, préfixée d’une directive qui limite cette clé à une seule commande autorisée :
sudo nano /home/backupuser/.ssh/authorized_keys
command="rsync --server -vlogDtprze.iLsfxCIvu . ~/sauvegardes/",no-port-forwarding,no-X11-forwarding,no-agent-forwarding,no-pty ssh-ed25519 AAAAC3... vps-ovh-backup
Même si un attaquant dispose de cette clé, il ne peut rien faire d’autre que rsync — pas de shell interactif, pas d’escalade de privilèges.
UFW sur la VM
sudo ufw allow from 192.168.1.0/24 to any port 22
sudo ufw allow from <IP_VPS_OVH> to any port 22
sudo ufw enable
Préparation côté MariaDB
Création d’un utilisateur dédié aux sauvegardes
Plutôt que d’utiliser root, on crée un utilisateur avec les droits stricts nécessaires à mysqldump :
sudo mysql -u root -p
CREATE USER 'backup_user'@'localhost' IDENTIFIED BY 'MotDePasse_Fort!';
GRANT SELECT, LOCK TABLES, SHOW VIEW, EVENT, TRIGGER ON monsite_wp.* TO 'backup_user'@'localhost';
FLUSH PRIVILEGES;
EXIT;
Stockage sécurisé du mot de passe
Le mot de passe ne doit jamais apparaître en clair dans un script. On le stocke dans un fichier de configuration MariaDB protégé :
sudo nano /etc/mysql/backup.cnf
[mysqldump]
user=backup_user
password=MotDePasse_Fort!
sudo chmod 600 /etc/mysql/backup.cnf
sudo chown root:root /etc/mysql/backup.cnf
Les scripts de sauvegarde
Script 1 — Sauvegarde des bases de données
sudo nano /usr/local/bin/backup-db.sh
#!/bin/bash
DATE=$(date +%Y%m%d_%H%M%S)
BACKUP_DIR="/var/backups/mysql"
RETENTION=7
mkdir -p $BACKUP_DIR
# Dump des bases WordPress
mysqldump --defaults-extra-file=/etc/mysql/backup.cnf monsite_wp \
| gzip > $BACKUP_DIR/monsite_wp_$DATE.sql.gz
# Envoi vers la VM Freebox
rsync -avz --ignore-existing \
-e "ssh -i /home/ubuntu/.ssh/id_ed25519_backup -p 9000" \
$BACKUP_DIR/ \
backupuser@lagni.freeboxos.fr:~/sauvegardes/mysql/
# Nettoyage local
find $BACKUP_DIR -name "*.sql.gz" -mtime +$RETENTION -delete
echo "[$DATE] Backup BDD OK" >> /var/log/backup-db.log
Script 2 — Sauvegarde des fichiers
sudo nano /usr/local/bin/backup-files.sh
#!/bin/bash
DATE=$(date +%Y%m%d_%H%M%S)
BACKUP_DIR="/var/backups/files"
RETENTION=7
mkdir -p $BACKUP_DIR
# Sauvegarde des sites web
tar czf $BACKUP_DIR/www_$DATE.tar.gz /var/www/
# Sauvegarde de la configuration serveur
tar czf $BACKUP_DIR/etc_$DATE.tar.gz /etc/nginx/ /etc/letsencrypt/ /etc/php/
# Envoi vers la VM Freebox
rsync -avz --ignore-existing \
-e "ssh -i /home/ubuntu/.ssh/id_ed25519_backup -p 9000" \
$BACKUP_DIR/ \
backupuser@lagni.freeboxos.fr:~/sauvegardes/files/
# Nettoyage local
find $BACKUP_DIR -name "*.tar.gz" -mtime +$RETENTION -delete
echo "[$DATE] Backup fichiers OK" >> /var/log/backup-files.log
sudo chmod +x /usr/local/bin/backup-db.sh
sudo chmod +x /usr/local/bin/backup-files.sh
Planification via cron
sudo crontab -e
0 2 * * * /usr/local/bin/backup-db.sh
0 3 * * * /usr/local/bin/backup-files.sh
Les sauvegardes s’exécutent automatiquement chaque nuit — les bases de données à 2h00, les fichiers à 3h00.
Rétention sur la VM Freebox
Sur la VM, on planifie également le nettoyage des anciennes sauvegardes :
crontab -e
0 4 * * * find ~/sauvegardes/mysql/ -name "*.sql.gz" -mtime +30 -delete
0 4 * * * find ~/sauvegardes/files/ -name "*.tar.gz" -mtime +30 -delete
30 jours de rétention sur la VM — ajustable selon l’espace disponible.
Récapitulatif sécurité
| Mesure | Détail |
|---|---|
| Utilisateur MariaDB dédié | Droits SELECT uniquement sur les bases concernées |
| Mot de passe MariaDB | Fichier /etc/mysql/backup.cnf chmod 600 |
| Clé SSH dédiée | Sans passphrase, usage automatisé uniquement |
| Restriction rsync | Clé limitée à la commande rsync, pas de shell |
| backupuser sans sudo | Impossibilité d’escalade de privilèges |
| Accès ju révoqué depuis VPS | Le compte admin de la VM n’est pas joignable depuis le VPS |
| UFW sur la VM | SSH autorisé uniquement depuis le réseau local et l’IP du VPS |
| Port non standard | Port 9000 au lieu de 22 pour réduire l’exposition |
Ce que cette solution ne couvre pas encore
La règle d’or en matière de sauvegarde est la règle 3-2-1 :
- 3 copies des données
- sur 2 supports différents
- dont 1 copie hors site
Notre solution actuelle couvre deux emplacements — le VPS OVH et la VM Freebox à domicile. Le snapshot OVH reste dans le même datacenter que le VPS, et la VM Freebox est physiquement chez soi — vulnérable en cas d’incendie, dégât des eaux ou vol.
Il manque donc une copie véritablement externalisée — dans un datacenter tiers, indépendant d’OVH et géographiquement distant du domicile. Des solutions comme Cloudflare R2 (gratuit jusqu’à 10 Go/mois) ou Backblaze B2 (quelques centimes par Go) permettent de combler ce manque facilement via rclone.
C’est l’objet d’un prochain article.
Laisser un commentaire