Si vous avez déjà découvert un site WordPress “cassé” après une mise à jour, et que votre dernier backup date d’il y a trois semaines, vous connaissez le vrai problème : ce n’est pas WordPress, c’est votre routine de sauvegarde. WordPress 6.9.4 tourne très bien sur PHP 8.1+, mais aucun CMS ne vous protège d’une suppression accidentelle, d’un disque plein, d’un piratage, ou d’un mauvais import.

Le besoin / le problème serveur

Une sauvegarde WordPress exploitable doit couvrir deux choses :

  • La base de données (articles, pages, réglages, utilisateurs, commandes WooCommerce, etc.).
  • Les fichiers (wp-content en priorité : thèmes, plugins, uploads, cache éventuel, mu-plugins).

Le problème vient de deux pièges que je vois tout le temps sur des blogs :

  • Le backup “manuel” (zip téléchargé + export SQL à la main) n’est jamais fait au bon moment.
  • Le backup “automatique” est stocké dans le dossier public (ex: /public_html/backups), donc accessible si quelqu’un devine l’URL, ou supprimé si le serveur tombe.

À la fin, vous saurez mettre en place un script automatique via SSH + cron qui :

  • exporte la base via WP-CLI (plus fiable que phpMyAdmin pour l’automatisation),
  • archive les fichiers critiques,
  • compresse, journalise, chiffre (option),
  • fait une rotation (garde N backups),
  • et se teste sur un staging avant de toucher la prod.

Divi 5 / Elementor / Avada : aucun impact direct. Le script sauvegarde les mêmes dossiers, mais retenez que ces builders stockent parfois des assets dans uploads et des données en base : vous devez donc sauvegarder les deux.

Résumé rapide

  • Vous sauvegardez wp-content + un dump SQL généré par WP-CLI.
  • Vous stockez les backups hors du webroot (ex: /home/USER/backups), avec permissions strictes.
  • Vous utilisez un script Bash unique, avec logs et rotation.
  • Vous planifiez via cron (pas via WP-Cron), pour éviter les backups déclenchés au hasard par des visites.
  • Vous testez la restauration sur un staging (toujours), puis seulement ensuite sur production.
  • Vous ajoutez une option d’envoi distant (SSH/SFTP) si vous voulez survivre à la perte du serveur.

Avant de commencer (prérequis)

Accès nécessaires :

  • SSH sur le serveur (indispensable) pour exécuter les commandes et installer cron.
  • WP-CLI installé (souvent déjà présent sur VPS/managed). Sinon, vous pouvez l’installer.
  • Accès au répertoire WordPress (chemin du type /var/www/site ou /home/user/public_html).
  • Optionnel : accès MySQL (si vous voulez vérifier l’import manuellement).

Sauvegarde obligatoire avant toute opération serveur : oui, c’est paradoxal, mais vous allez toucher à des permissions, à cron, et potentiellement à des scripts. Faites au minimum une copie de wp-config.php et un export DB via votre méthode actuelle.

Versions recommandées (avril 2026) :

  • WordPress : 6.9.4
  • PHP : 8.1+ (8.2/8.3 généralement mieux si votre hébergeur suit)
  • MySQL : 8+ ou MariaDB 10.6+
  • Serveur : Nginx ou Apache (les deux conviennent)

Rappel sécurité : ne stockez jamais un dump SQL non chiffré dans un dossier web accessible. Un dump contient des emails, parfois des adresses, et des hash de mots de passe. En cas de fuite, c’est un incident sérieux.

Sources officielles utiles :

Étape 1 : définir une stratégie de sauvegarde réaliste (fichiers + base)

Avant d’écrire du code, décidez quoi vous sauvegardez et combien de temps vous gardez les archives. Une stratégie simple, adaptée aux blogueurs :

  • Quotidien : base + wp-content (ou au minimum wp-content/uploads si votre disque est petit).
  • Rétention : 7 jours (quotidien), + 4 semaines (hebdo), + 3 mois (mensuel) si vous pouvez.

Dans ce guide, on implémente une rotation “simple” : garder les 14 derniers backups quotidiens. C’est facile à maintenir, et vous pouvez l’étendre ensuite.

Pourquoi je privilégie wp-content au “site complet” ? Parce que :

  • Le cœur WordPress (wp-admin, wp-includes) se retélécharge.
  • Les builders (Divi/Elementor/Avada) et votre contenu média vivent dans wp-content.
  • Les archives sont plus petites, donc plus rapides, donc plus souvent faites.

Étape 2 : préparer un répertoire de backups hors web + permissions

Objectif : créer un dossier hors du webroot. Exemple typique :

  • WordPress est dans /var/www/mon-site
  • Backups dans /var/backups/mon-site (ou /home/user/backups/mon-site en mutualisé)

La commande ci-dessous crée le dossier, fixe un propriétaire, et verrouille les permissions. Adaptez le nom d’utilisateur (www-data sous Debian/Ubuntu, parfois nginx ou votre user en mutualisé).

# Créez un dossier de backup hors du webroot
sudo mkdir -p /var/backups/mon-site

# Donnez l'accès à l'utilisateur qui exécute PHP/cron (adaptez)
sudo chown -R www-data:www-data /var/backups/mon-site

# Permissions strictes : seul le propriétaire lit/écrit/exécute
sudo chmod 700 /var/backups/mon-site

Résultat attendu : un dossier non accessible depuis le web, et non listable via HTTP. Si vous êtes en mutualisé sans sudo, faites :

mkdir -p ~/backups/mon-site
chmod 700 ~/backups/mon-site

À ce stade, vérifiez l’espace disque. Les backups échouent souvent “silencieusement” parce que le disque est plein.

# Espace disque
df -h

# Taille du wp-content (pour estimer)
du -sh /var/www/mon-site/wp-content

Étape 3 : écrire un script de backup automatique (Bash) avec rotation

On va créer un script Bash unique, exécutable, qui :

  • se place dans le dossier WordPress,
  • fait un export DB via WP-CLI,
  • archive wp-content + le dump SQL,
  • supprime les backups au-delà d’un certain nombre,
  • écrit un log.

Pourquoi Bash (et pas PHP) ? Pour un backup serveur, Bash est plus direct : accès aux outils système (tar, gzip, find), gestion des erreurs, exécution via cron. Et vous évitez de charger WordPress en HTTP (risque timeout).

Créez le fichier /usr/local/bin/wp-backup-mon-site.sh (ou ~/bin/... en mutualisé). La commande ci-dessous ouvre un éditeur (nano). Vous pouvez utiliser vim si vous préférez.

sudo nano /usr/local/bin/wp-backup-mon-site.sh

Collez ce script complet (adaptez les chemins). Les commentaires sont en français et expliquent les choix.

#!/usr/bin/env bash
set -euo pipefail

# ==============================
# Script de backup WordPress (WP 6.9.4+)
# - Dump SQL via WP-CLI
# - Archive wp-content + dump
# - Rotation (garde N backups)
# - Log d'exécution
# ==============================

# Chemin vers l'installation WordPress (dossier contenant wp-config.php)
WP_PATH="/var/www/mon-site"

# Dossier de destination des backups (hors webroot)
BACKUP_DIR="/var/backups/mon-site"

# Nombre de backups à conserver
KEEP_LAST=14

# Binaire WP-CLI (souvent "wp" si dans le PATH)
WP_BIN="/usr/local/bin/wp"

# Date pour nommer les fichiers
NOW="$(date +%F_%H-%M-%S)"

# Fichiers générés
DB_DUMP="${BACKUP_DIR}/db_${NOW}.sql"
ARCHIVE="${BACKUP_DIR}/backup_${NOW}.tar.gz"
LOG_FILE="${BACKUP_DIR}/backup.log"

# Fonction de log
log() {
  echo "[$(date +%F %T)] $*" | tee -a "${LOG_FILE}"
}

# Vérifications de base
if [[ ! -d "${WP_PATH}" ]]; then
  echo "WP_PATH introuvable: ${WP_PATH}" >&2
  exit 1
fi

if [[ ! -f "${WP_PATH}/wp-config.php" ]]; then
  echo "wp-config.php introuvable dans: ${WP_PATH}" >&2
  exit 1
fi

if [[ ! -d "${BACKUP_DIR}" ]]; then
  echo "BACKUP_DIR introuvable: ${BACKUP_DIR}" >&2
  exit 1
fi

if [[ ! -x "${WP_BIN}" ]]; then
  echo "WP-CLI introuvable/exécutable: ${WP_BIN}" >&2
  exit 1
fi

log "Début backup: WP_PATH=${WP_PATH} BACKUP_DIR=${BACKUP_DIR}"

# Se placer dans le dossier WordPress
cd "${WP_PATH}"

# 1) Export base de données (WP-CLI)
# --single-transaction limite les verrous (InnoDB)
# --quick réduit la mémoire côté client
log "Export base (WP-CLI) vers ${DB_DUMP}"
"${WP_BIN}" db export "${DB_DUMP}" --add-drop-table --single-transaction --quick

# 2) Archive des fichiers
# On sauvegarde wp-content + le dump SQL
# --warning=no-file-changed évite des warnings si des fichiers changent pendant l'archivage
log "Archivage wp-content + dump SQL vers ${ARCHIVE}"
tar --warning=no-file-changed -czf "${ARCHIVE}" 
  -C "${WP_PATH}" wp-content 
  -C "${BACKUP_DIR}" "$(basename "${DB_DUMP}")"

# 3) Optionnel : checksum pour vérifier l'intégrité
log "Génération checksum SHA-256"
sha256sum "${ARCHIVE}" >> "${BACKUP_DIR}/checksums.sha256"

# 4) Nettoyage : supprimer le dump SQL brut après intégration dans l'archive
log "Suppression du dump SQL brut ${DB_DUMP}"
rm -f "${DB_DUMP}"

# 5) Rotation : garder les N derniers backups
log "Rotation: conservation des ${KEEP_LAST} derniers backups"
ls -1t "${BACKUP_DIR}"/backup_*.tar.gz 2>/dev/null | tail -n +"$((KEEP_LAST+1))" | xargs -r rm -f

log "Backup terminé: ${ARCHIVE}"

Rendez-le exécutable :

sudo chmod 750 /usr/local/bin/wp-backup-mon-site.sh
sudo chown root:root /usr/local/bin/wp-backup-mon-site.sh

Note pratique : si votre cron tourne sous www-data (ou votre user), vous pouvez mettre l’utilisateur propriétaire à cet endroit. Sur un petit VPS, je préfère souvent exécuter le backup via root (cron root) mais écrire dans un dossier verrouillé. Sur mutualisé, vous n’aurez pas root : exécutez tout sous votre user.

Étape 4 : exporter la base proprement (WP-CLI) et vérifier l’intégrité

WP-CLI est votre meilleur allié pour les backups WordPress, parce qu’il lit la config (wp-config.php) et s’exécute en local, sans limite HTTP. Les commandes principales :

  • wp db export : export SQL
  • wp db import : import SQL
  • wp db check : vérification

Avant de mettre cron, testez manuellement le script (et lisez le log). Exécutez la commande, puis vérifiez que l’archive a été créée.

# Exécution manuelle
sudo /usr/local/bin/wp-backup-mon-site.sh

# Vérifier la présence des fichiers
sudo ls -lh /var/backups/mon-site | tail -n 20

# Lire le log
sudo tail -n 50 /var/backups/mon-site/backup.log

Vérifiez l’intégrité de l’archive :

# Tester l'archive (ne restaure rien, vérifie juste la structure gzip/tar)
gzip -t /var/backups/mon-site/backup_YYYY-MM-DD_HH-MM-SS.tar.gz

# Lister le contenu
tar -tzf /var/backups/mon-site/backup_YYYY-MM-DD_HH-MM-SS.tar.gz | head

Si vous voyez wp-content/ et un fichier db_....sql, c’est bon signe.

Étape 5 : planifier l’exécution (cron) et journaliser

Ne confondez pas :

  • WP-Cron : déclenché par les visites, pas fiable pour un backup serveur.
  • cron système : déclenché à heure fixe, fiable.

On va planifier un backup chaque nuit à 03:15. Avant de montrer la ligne cron, voici ce qu’elle fait :

  • exécute le script,
  • redirige la sortie standard et erreur vers un fichier (en plus du log interne),
  • évite d’envoyer des emails de cron si tout va bien.

Éditez la crontab (ici pour root ; adaptez si vous utilisez un autre utilisateur) :

sudo crontab -e

Ajoutez :

# Backup WordPress quotidien à 03:15
15 3 * * * /usr/local/bin/wp-backup-mon-site.sh >> /var/backups/mon-site/cron.log 2>&1

Sur mutualisé (sans sudo), utilisez :

crontab -e
15 3 * * * /home/VOTRE_USER/bin/wp-backup-mon-site.sh >> /home/VOTRE_USER/backups/mon-site/cron.log 2>&1

Astuce terrain : j’ai souvent vu des backups cron “ne rien faire” simplement parce que cron n’a pas le même PATH que votre shell. C’est pour ça que le script référence /usr/local/bin/wp explicitement. Si votre WP-CLI est ailleurs, trouvez-le :

which wp
wp --info

Étape 6 : restaurer (staging puis production) sans se piéger

Un backup non testé, c’est une hypothèse. Testez une restauration sur un staging (copie du site) avant le jour où vous en aurez besoin.

6.1 Préparer un staging rapidement

Le plus simple : un second vhost (ex: staging.monsite.tld) pointant vers un dossier séparé et une base séparée. Côté code/commandes, vous avez deux options :

  • Créer une nouvelle installation WordPress 6.9.4, puis restaurer dessus.
  • Cloner les fichiers et créer une nouvelle DB, puis importer.

Je reste sur le scénario “nouvelle installation + restauration”, plus propre.

6.2 Extraire l’archive

Créez un dossier cible (staging) et extrayez uniquement ce dont vous avez besoin. Ici, on restaure wp-content et on récupère le dump SQL.

# Exemple : dossier staging
STAGING_PATH="/var/www/mon-site-staging"
ARCHIVE="/var/backups/mon-site/backup_YYYY-MM-DD_HH-MM-SS.tar.gz"

# Extraire
sudo tar -xzf "${ARCHIVE}" -C "${STAGING_PATH}"

# Vérifier que wp-content est bien en place
sudo ls -la "${STAGING_PATH}/wp-content" | head

Attention : selon comment votre staging est structuré, vous pourriez extraire wp-content au mauvais niveau (erreur classique). Vérifiez toujours l’arborescence après extraction.

6.3 Importer la base

Repérez le fichier SQL extrait (dans l’exemple, il est dans l’archive à la racine du dossier d’extraction). Puis importez avec WP-CLI.

# Se placer dans le staging (dossier contenant wp-config.php du staging)
cd /var/www/mon-site-staging

# Vérifier que WP-CLI "voit" bien WordPress
wp core version

# Import DB (adaptez le nom du fichier)
wp db import /var/www/mon-site-staging/db_YYYY-MM-DD_HH-MM-SS.sql

# Vérifier la base
wp db check

Après import, vous devrez souvent faire un search-replace d’URL si le staging a un domaine différent. WP-CLI le fait bien, mais faites-le avec prudence (sauvegarde avant). Commande typique :

# Remplacer l'URL prod par l'URL staging (adaptez)
wp search-replace 'https://monsite.tld' 'https://staging.monsite.tld' --all-tables --precise --skip-columns=guid

Le paramètre --skip-columns=guid évite de casser les GUID des posts RSS. C’est une bonne pratique que j’applique systématiquement.

Fichiers de configuration complets

Cette section regroupe des fichiers “prêts à coller” adaptés au backup : protection, limites PHP, et un exemple Nginx pour bloquer toute exposition accidentelle si vous stockez quand même des archives dans un dossier servi (ce que je déconseille).

.htaccess (Apache) : bloquer un dossier de backups si vous n’avez pas le choix

Idéalement, vous n’en aurez pas besoin (backups hors webroot). Si votre hébergement vous force à stocker dans un sous-dossier du site, mettez un .htaccess dans ce dossier backups :

# Fichier: /chemin/site/backups/.htaccess
# Objectif: interdire tout accès HTTP aux archives et aux .sql
Require all denied

<FilesMatch ".(sql|gz|zip|tar|tgz)$">
  Require all denied
</FilesMatch>

nginx.conf : bloquer l’accès à /backups/ si exposé

Pour Nginx, ajoutez un bloc dans le server {} du site :

# Exemple à placer dans le server {} de votre vhost
location ^~ /backups/ {
  deny all;
  return 403;
}

wp-config.php : forcer la désactivation de l’éditeur de fichiers

Ce n’est pas “backup”, mais ça limite les dégâts en cas d’accès admin compromis. Ajoutez dans wp-config.php :

/** Désactive l'éditeur de fichiers dans l'admin (réduit le risque en cas de compromission) */
define('DISALLOW_FILE_EDIT', true);

Référence : wp-config.php (WordPress.org)

php.ini (ou override) : éviter un timeout pendant des opérations lourdes

Votre script tourne en CLI, donc il dépend surtout des limites CLI, mais sur certains hébergements, WP-CLI peut hériter de certaines limites. Exemple de réglages raisonnables :

; Exemple php.ini (adaptez selon votre hébergeur)
memory_limit = 512M
max_execution_time = 300
post_max_size = 64M
upload_max_filesize = 64M

Si vous ne savez pas où mettre ça, ne forcez pas : sur beaucoup de serveurs, c’est géré globalement. Testez d’abord.


Vérification

Vous voulez des contrôles simples, reproductibles, sans interface graphique.

1) Vérifier que cron s’exécute

Attendez l’heure prévue, puis :

# Voir les logs
sudo tail -n 100 /var/backups/mon-site/cron.log
sudo tail -n 100 /var/backups/mon-site/backup.log

Vous devez voir “Début backup” puis “Backup terminé”.

2) Vérifier la rotation

Après plusieurs exécutions :

ls -1 /var/backups/mon-site/backup_*.tar.gz | wc -l

Vous devez obtenir au maximum le nombre défini dans KEEP_LAST.

3) Vérifier l’intégrité via checksum

cd /var/backups/mon-site
# Vérifie que les checksums correspondent (si vous ne conservez que les derniers, adaptez)
sha256sum -c checksums.sha256 2>/dev/null | tail -n 20

4) Vérifier que WP-CLI fonctionne en non-interactif

C’est un test que je fais quand un cron échoue : cron a un environnement minimal.

sudo -u www-data /usr/local/bin/wp --info
sudo -u www-data /usr/local/bin/wp --path=/var/www/mon-site core version

Si ça ne marche pas

Quand un backup automatique échoue, c’est rarement “WordPress”. C’est presque toujours : chemin, droits, binaire manquant, ou manque d’espace disque.

Diagnostic par étapes

1) Le script ne s’exécute pas

  • Vérifiez le bit exécutable : ls -l /usr/local/bin/wp-backup-mon-site.sh
  • Vérifiez la première ligne (shebang) : head -n 1 ...
  • Testez en direct : bash -x /usr/local/bin/wp-backup-mon-site.sh (mode debug)

2) WP-CLI échoue en cron mais marche en SSH

  • Cause fréquente : WP_BIN incorrect ou PATH différent.
  • Solution : utilisez le chemin absolu de wp (déjà fait dans le script) et passez --path=... si nécessaire.
# Exemple si WP-CLI "ne trouve pas" WordPress
/usr/local/bin/wp --path=/var/www/mon-site db export /var/backups/mon-site/test.sql

3) “Permission denied”

  • Vérifiez propriétaire + permissions du dossier backup : namei -l /var/backups/mon-site
  • Vérifiez l’utilisateur qui exécute cron : sudo crontab -l (si root) ou crontab -l

4) Disque plein

df -h
du -sh /var/backups/mon-site
du -sh /var/www/mon-site/wp-content/uploads

Tableau de diagnostic (symptômes réalistes)

Symptôme Cause probable Vérification Solution
Le fichier cron.log reste vide Cron non configuré pour le bon utilisateur crontab -l (user) et sudo crontab -l (root) Ajouter la tâche dans la bonne crontab
WP-CLI introuvable/exécutable WP_BIN incorrect ou WP-CLI non installé which wp, wp --info Installer WP-CLI ou corriger le chemin absolu
Error: This does not seem to be a WordPress installation WP_PATH faux ou mauvais dossier courant en cron ls -la $WP_PATH/wp-config.php Fixer WP_PATH et/ou utiliser --path=
tar: Cannot open: Permission denied Droits insuffisants sur BACKUP_DIR ls -ld BACKUP_DIR chown/chmod adaptés, ou exécuter cron avec le bon user
Backups très lents uploads énorme, CPU limité, I/O lente du -sh uploads, top Exclure du cache, passer en incrémental (rsync), augmenter fenêtre de backup
Archive créée mais impossible à restaurer Backup jamais testé, dump absent, archive corrompue tar -tzf, gzip -t Ajouter checksum + test de restauration sur staging

Pièges et erreurs courantes

Erreur Cause Solution
Copier le script dans functions.php Confusion “code WordPress” vs “code serveur” Un backup serveur se fait en SSH/cron, pas dans le thème (risque sécurité + timeouts)
Oublier un point-virgule… en Bash Copier-coller partiel, guillemets cassés Lancer bash -n script.sh et shellcheck si disponible
Tester directement en production sans backup existant Routine “je verrai après” Faire au moins un backup manuel avant de déployer cron
Backups stockés dans /public_html/backups Plus simple “sur le moment” Stocker hors webroot; sinon bloquer via Nginx/Apache + noms non devinables
WP-CLI marche en SSH mais pas en cron Environnement cron minimal (PATH) Utiliser chemin absolu vers wp et définir WP_PATH
Permaliens “bizarres” après restauration Règles de réécriture non régénérées Lancer wp rewrite flush --hard après restauration (sur staging d’abord)
Conflit avec cache (pages incohérentes après restore) Cache plugin + cache serveur + CDN Vider caches (plugin, Nginx fastcgi, CDN) après restauration
Tutoriel ancien basé sur mysqldump avec identifiants en clair Copie de vieux snippets Préférer wp db export (WordPress 6.9.4) et restreindre les fichiers de config

Sécurité serveur

Un système de backup peut devenir une fuite de données si vous le traitez comme un simple zip.

1) Permissions et emplacement

  • Backups hors webroot (priorité n°1).
  • Dossier en 700, fichiers en 600 si possible.
  • Évitez de laisser traîner des .sql non compressés.

2) Chiffrement (option pratique)

Si vous devez transférer/stocker ailleurs (NAS, autre serveur), chiffrez l’archive. Exemple avec OpenSSL (mot de passe) :

# Chiffre une archive (AES-256)
openssl enc -aes-256-cbc -salt -pbkdf2 
  -in /var/backups/mon-site/backup_YYYY.tar.gz 
  -out /var/backups/mon-site/backup_YYYY.tar.gz.enc

Risque : si vous perdez le mot de passe, vous perdez le backup. Stockez-le dans un gestionnaire de mots de passe.

3) Envoi distant (survivre à la perte du serveur)

Le “vrai” plan de secours inclut une copie hors serveur. Le plus simple en code : rsync via SSH vers un autre serveur.

# Exemple: pousser les archives vers un serveur distant
# À faire après la création de l'archive, idéalement avec une clé SSH dédiée
rsync -av --delete /var/backups/mon-site/ backupuser@backup-host:/data/backups/mon-site/

4) Ne jamais exposer les logs

Vos logs peuvent contenir des chemins, des noms de fichiers, des infos utiles à un attaquant. Stockez-les au même endroit que les backups, hors webroot.

Ressources

FAQ

Est-ce que je peux faire ce backup “par code” dans un plugin WordPress ?

Techniquement oui, mais je vous le déconseille pour un débutant : exécuter des archives et exports DB via une requête HTTP expose à des timeouts et à des risques sécurité (quelqu’un déclenche le backup). Un cron système + script SSH est plus fiable.

Pourquoi ne pas sauvegarder tout WordPress (core inclus) ?

Vous pouvez, mais ça grossit beaucoup les archives pour peu de valeur. Le core se réinstalle. wp-content + DB couvre l’essentiel.

WP-CLI est-il compatible avec WordPress 6.9.4 ?

Oui, WP-CLI suit WordPress. Installez une version récente. Vérifiez avec wp --info et testez wp core version.

Je n’ai pas accès à SSH, je fais comment ?

Sans SSH, vous ne pourrez pas faire un vrai backup automatisé côté serveur par script/cron. Votre alternative réaliste : un plugin de backup fiable, ou demander à l’hébergeur d’activer SSH/cron.

Combien de backups dois-je garder ?

Pour un blog : 14 quotidiens est un bon départ. Si vous publiez beaucoup (ou WooCommerce), augmentez et ajoutez une copie distante.

Comment exclure des dossiers de cache dans wp-content ?

Vous pouvez exclure des chemins dans tar, mais c’est plus avancé. Le cache peut être régénéré, donc l’exclure réduit la taille. Exemple (à adapter) : utilisez --exclude='wp-content/cache' dans la commande tar.

Mon site est énorme, tar/gzip est trop lent. Alternative ?

Oui : une sauvegarde incrémentale par rsync (snapshot), et un dump DB séparé. C’est souvent ce que je finis par mettre sur des sites média avec des uploads massifs.

Après restauration, Elementor/Divi/Avada affiche des mises en page cassées

Causes typiques : URL non remplacée (search-replace), cache non vidé, ou assets générés à régénérer. Faites wp search-replace, videz les caches, puis régénérez les fichiers CSS via le builder si nécessaire.

Puis-je stocker les backups sur le même serveur mais dans un autre dossier ?

Oui, mais ça ne protège pas d’une perte totale du serveur. Le minimum est “hors webroot”. L’idéal est “hors serveur”.

Comment être sûr que mon backup contient bien la base ?

Listez l’archive : tar -tzf backup_...tar.gz et vérifiez la présence du db_....sql. Ensuite, testez une restauration sur staging : c’est le seul test qui compte vraiment.