Sauvegarder son serveur VPS

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 backupuser sans sudo sur la VM
  • Une clé SSH restreinte à la commande rsync uniquement
  • 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é

MesureDétail
Utilisateur MariaDB dédiéDroits SELECT uniquement sur les bases concernées
Mot de passe MariaDBFichier /etc/mysql/backup.cnf chmod 600
Clé SSH dédiéeSans passphrase, usage automatisé uniquement
Restriction rsyncClé limitée à la commande rsync, pas de shell
backupuser sans sudoImpossibilité d’escalade de privilèges
Accès ju révoqué depuis VPSLe compte admin de la VM n’est pas joignable depuis le VPS
UFW sur la VMSSH autorisé uniquement depuis le réseau local et l’IP du VPS
Port non standardPort 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.

Commentaires

Laisser un commentaire

Votre adresse e-mail ne sera pas publiée. Les champs obligatoires sont indiqués avec *