Le besoin / Le problème serveur
Si vous avez déjà vu un HTTP 500 après une mise à jour de plugin, ou un site qui redirige en boucle après une migration, vous savez que “restaurer une sauvegarde” n’est pas un clic magique. Le problème vient presque toujours d’un mélange : fichiers restaurés mais base non restaurée (ou l’inverse), URLs incohérentes, permissions cassées, cache serveur qui sert l’ancien site.
Objectif : remettre en ligne un WordPress 6.9.4 (avril 2026) depuis une sauvegarde sans empirer la situation. À la fin, vous saurez restaurer proprement les fichiers et/ou la base, valider l’intégrité, corriger les URLs, régénérer les permaliens, purger les caches, et diagnostiquer les erreurs serveur avec des commandes exploitables.
Je croise souvent ce scénario sur des sites Elementor/Divi/Avada : le front est “cassé” parce que le cache (plugin + serveur) sert des assets qui ne correspondent plus à la base restaurée. La restauration réussit, mais la perception côté navigateur est “toujours KO”. On va traiter ça explicitement.
Résumé rapide
- Ne restaurez jamais directement en production si vous pouvez éviter : restaurez d’abord en staging, vérifiez, puis basculez.
- Fichiers + base doivent être cohérents (même date de backup). Mélanger deux dates est une source classique de bugs fantômes.
- Restaurez WordPress core via WP-CLI quand c’est possible, puis réinjectez
wp-content/et la base. - Après import SQL : corrigez URLs, videz caches, régénérez permaliens, vérifiez cron et emails.
- Diagnostiquez avec les logs (PHP-FPM, Nginx/Apache) et
wp cli: vous gagnerez des heures. - Sécurisez : permissions strictes, secrets
AUTH_KEYrégénérés si fuite suspectée, blocage temporaire des écritures.
Avant de commencer (prérequis)
Accès requis
- SSH sur le serveur (ou au minimum un shell).
- WP-CLI fonctionnel (idéalement sur staging et prod).
- Accès MySQL/MariaDB (CLI
mysqlou un équivalent). - Accès aux sauvegardes : archive fichiers (
.tar.gzou.zip) + dump SQL (.sqlou.sql.gz).
Sauvegarde obligatoire (même si le site est cassé)
Même si “tout est déjà cassé”, faites une capture de l’état actuel. J’ai déjà vu des restaurations échouer, et la seule façon de revenir en arrière était… la sauvegarde de l’état cassé.
# Adaptez le chemin
cd /var/www/site
# Sauvegarde des fichiers actuels (hors cache si vous voulez alléger)
tar -czf /root/backup-avant-restore-files-$(date +%F-%H%M).tar.gz
--exclude=wp-content/cache
--exclude=wp-content/uploads/cache
.
# Sauvegarde de la base actuelle
# Renseignez DB_NAME/DB_USER/DB_PASSWORD depuis wp-config.php
mysqldump --single-transaction --quick --routines --triggers
-u DB_USER -p'DB_PASSWORD' DB_NAME
> /root/backup-avant-restore-db-$(date +%F-%H%M).sql
Versions serveur recommandées (2026)
- PHP 8.1+ (8.2/8.3 souvent plus confortable selon extensions). WordPress 6.9.4 tourne correctement en 8.1+.
- MySQL 8.0+ ou MariaDB 10.6+ (au minimum compatible avec votre hébergeur).
- Nginx + PHP-FPM ou Apache + PHP-FPM (évitez mod_php sur des stacks modernes).
Sources : WordPress – Requirements, WP-CLI – Command reference, PHP Manual.
Étape 1 : mettre le site en sécurité (mode maintenance + gel des écritures)
Avant de manipuler quoi que ce soit : stoppez les écritures. Sinon vous restaurez une base “ancienne” pendant que WooCommerce (ou un formulaire) continue d’écrire, et vous créez des incohérences.
1) Maintenance immédiate (simple et efficace)
cd /var/www/site
# Active le mode maintenance WordPress (crée .maintenance)
wp maintenance-mode activate --allow-root
2) Coupez temporairement le trafic d’écriture (option serveur)
Si vous avez un reverse proxy ou Nginx, vous pouvez refuser POST pendant la restauration (utile si vous ne faites pas confiance au mode maintenance). Exemple Nginx (à retirer après) :
# À placer dans le server{} le temps de l'intervention
# (voir section "Fichiers de configuration complets" pour un exemple complet)
# if ($request_method = POST) { return 503; }
3) Désactivez le cache applicatif (le temps de l’opération)
Sur des sites avec cache agressif, j’ai souvent vu une restauration “réussie” mais le navigateur reçoit encore des pages servies par le cache (plugin ou Nginx fastcgi_cache). Désactivez temporairement :
- Cache plugin (si possible via WP-CLI si le plugin le permet).
- Cache serveur (fastcgi_cache / varnish) via purge ou désactivation.
Étape 2 : identifier ce qu’il faut restaurer (fichiers, base, ou les deux)
Restaurer “tout” est parfois la meilleure option, mais pas toujours. Voici la logique que j’applique sur incident réel.
Cas A : le site affiche une erreur PHP (fatal error) après mise à jour
- Souvent : plugin/thème incompatible, fichier corrompu, autoloader cassé.
- Solution rapide : restaurer uniquement
wp-content/plugins/et/ou le thème, ou réinstaller le core proprement.
Cas B : le site affiche l’ancien contenu, ou redirections étranges, ou “site vide”
- Souvent : base restaurée d’une autre date, URLs incohérentes, table prefix différente, import partiel.
- Solution : restaurer la base (et vérifier les URLs), ou restaurer base + uploads.
Cas C : hack/suspicion de compromission
- Restaurer “à l’identique” peut réinjecter la backdoor si la sauvegarde est post-compromission.
- Solution : restaurez depuis un point antérieur, puis changez secrets, mots de passe, et auditez.
Vérifiez rapidement ce que contient votre backup
# Inspecter une archive tar.gz sans l'extraire
tar -tzf /chemin/backup-files.tar.gz | head -n 50
# Vérifier un dump SQL (taille, encodage, premières lignes)
zcat /chemin/backup-db.sql.gz | head -n 30
Étape 3 : préparer un staging (restaurer d’abord hors production)
Si vous avez le choix, restaurez sur un staging. Ça évite de “tester en prod”, erreur que je vois encore chez des développeurs expérimentés sous pression.
Option 1 : staging sur le même serveur (vhost séparé)
Créez un répertoire et une base dédiés :
# Répertoire staging
mkdir -p /var/www/site-staging
chown -R www-data:www-data /var/www/site-staging
# Base staging (MySQL/MariaDB)
mysql -u root -p <<'SQL'
CREATE DATABASE site_staging DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
CREATE USER 'site_staging_user'@'localhost' IDENTIFIED BY 'ChangezMoi-Long-Mdp';
GRANT ALL PRIVILEGES ON site_staging.* TO 'site_staging_user'@'localhost';
FLUSH PRIVILEGES;
SQL
Option 2 : staging local via Docker (rapide pour valider un dump)
Utile si vous n’avez pas la main sur le serveur. Je le fais souvent pour vérifier qu’un dump SQL n’est pas corrompu.
mkdir -p ~/wp-restore-test && cd ~/wp-restore-test
cat > docker-compose.yml <<'YML'
services:
db:
image: mariadb:10.11
environment:
MARIADB_DATABASE: wp
MARIADB_USER: wp
MARIADB_PASSWORD: wp
MARIADB_ROOT_PASSWORD: root
command: ["--character-set-server=utf8mb4", "--collation-server=utf8mb4_unicode_ci"]
volumes:
- dbdata:/var/lib/mysql
wp:
image: wordpress:php8.2-apache
ports:
- "8080:80"
environment:
WORDPRESS_DB_HOST: db:3306
WORDPRESS_DB_NAME: wp
WORDPRESS_DB_USER: wp
WORDPRESS_DB_PASSWORD: wp
volumes:
- ./html:/var/www/html
volumes:
dbdata:
YML
docker compose up -d
Étape 4 : restaurer les fichiers WordPress proprement
La restauration “propre” que je préfère : réinstaller le core (WordPress 6.9.4) puis remettre wp-content depuis la sauvegarde. Ça évite de garder des fichiers core modifiés ou corrompus.
1) Remettre un core sain (WP-CLI)
Sur le répertoire cible (staging d’abord) :
cd /var/www/site-staging
# Télécharge WordPress 6.9.4 en français
wp core download --version=6.9.4 --locale=fr_FR --force --allow-root
2) Restaurer wp-content depuis la sauvegarde
Vous voulez récupérer : thèmes, plugins, uploads, mu-plugins. Évitez de restaurer le cache.
cd /var/www/site-staging
# Exemple avec tar.gz contenant l'arborescence complète du site
tar -xzf /chemin/backup-files.tar.gz
--strip-components=0
--wildcards
"wp-content/*"
# Nettoyage des caches courants (souvent safe)
rm -rf wp-content/cache 2>/dev/null || true
rm -rf wp-content/uploads/cache 2>/dev/null || true
rm -f wp-content/advanced-cache.php 2>/dev/null || true
3) Permissions propres (évite 403/500 bizarres)
Les permissions sont un classique : backup fait en root, restauration en www-data, et vous obtenez des “Permission denied” dans les logs PHP-FPM.
# Adaptez l'utilisateur du serveur web (www-data sur Debian/Ubuntu)
chown -R www-data:www-data /var/www/site-staging
# Dossiers 755, fichiers 644 (base saine)
find /var/www/site-staging -type d -exec chmod 755 {} ;
find /var/www/site-staging -type f -exec chmod 644 {} ;
# wp-config.php un peu plus strict
chmod 640 /var/www/site-staging/wp-config.php
4) Divi 5 / Elementor / Avada : points spécifiques
- Elementor : après restauration, il faut souvent régénérer CSS/Assets (voir étape 6).
- Divi 5 : si vous avez un cache statique/critical CSS, purge obligatoire après import base.
- Avada : Fusion cache/compiled assets peuvent afficher un front “cassé” tant que vous n’avez pas vidé les caches.
Étape 5 : restaurer la base de données (MySQL/MariaDB) sans se tirer une balle dans le pied
Une restauration base ratée ressemble à : pages 404, widgets perdus, admin inaccessible, ou site qui boucle sur /wp-admin/install.php. La cause fréquente : mauvais DB_NAME, mauvais préfixe, import interrompu, ou encodage incohérent.
1) Créez/validez le wp-config.php avant import
Sur staging, créez un wp-config.php cohérent (un exemple complet est plus bas). À ce stade, le point critique : DB_NAME / DB_USER / DB_PASSWORD / DB_HOST et $table_prefix.
2) Import SQL (dump non compressé)
# Import direct
mysql -u site_staging_user -p site_staging < /chemin/backup-db.sql
3) Import SQL (dump compressé .sql.gz)
zcat /chemin/backup-db.sql.gz | mysql -u site_staging_user -p site_staging
4) Vérifiez que les tables existent et que le préfixe correspond
mysql -u site_staging_user -p -D site_staging -e "SHOW TABLES;" | head
# Vérifier l'option siteurl/home (préfixe wp_ à adapter)
mysql -u site_staging_user -p -D site_staging -e
"SELECT option_name, option_value FROM wp_options WHERE option_name IN ('siteurl','home');"
5) Si l’URL a changé : search-replace WP-CLI (sûr, sérialisation gérée)
Ne faites pas un UPDATE ... REPLACE() SQL “à la main” sur les champs sérialisés : vous cassez les longueurs, et donc les options. WP-CLI gère la sérialisation.
cd /var/www/site-staging
# Exemple : passage de https://www.example.com vers https://staging.example.net
wp search-replace 'https://www.example.com' 'https://staging.example.net'
--all-tables
--precise
--report-changed-only
--allow-root
# Vérifiez ensuite siteurl/home
wp option get siteurl --allow-root
wp option get home --allow-root
6) Ajustez le domaine pour éviter l’envoi d’emails depuis staging
Sur staging, j’ajoute souvent un garde-fou : désactiver les emails sortants (plugin ou config SMTP “null”). Côté serveur, vous pouvez aussi bloquer la sortie SMTP au firewall, mais c’est hors scope ici.
Étape 6 : corriger URL, permaliens, cache et tâches planifiées après restauration
Après restauration, le site “répond”, mais des symptômes persistent : 404, CSS manquants, builder qui affiche une page blanche, admin lente. Voici ce qui se passe en coulisses : la base a été restaurée, mais WordPress et vos plugins ont des caches/transients, des règles de réécriture, et parfois des chemins absolus à régénérer.
1) Régénérer les permaliens (flush rewrite rules)
cd /var/www/site-staging
# Réécrit .htaccess (Apache) ou les règles internes
wp rewrite flush --hard --allow-root
2) Vider caches WordPress (transients) et opcache si nécessaire
cd /var/www/site-staging
# Nettoyage transients (utile après migration)
wp transient delete --all --allow-root
# Si vous utilisez un object-cache.php (Redis/Memcached), testez sans
# (à faire temporairement si vous suspectez un cache incohérent)
# mv wp-content/object-cache.php wp-content/object-cache.php.disabled
3) Elementor : régénérer CSS/Data (via WP-CLI quand possible)
Elementor a des commandes WP-CLI selon versions et add-ons, mais elles ne sont pas garanties sur tous les setups. Méthode robuste : forcer une régénération via l’admin… sauf que vous ne voulez pas de captures/clics ici. Alternative côté serveur : supprimer les fichiers CSS générés pour forcer la régénération à la prochaine requête.
# Elementor stocke souvent des CSS générés dans uploads/elementor/css/
rm -rf /var/www/site-staging/wp-content/uploads/elementor/css/* 2>/dev/null || true
Note : selon votre config, un cache CDN peut aussi servir les anciens CSS. Purgez-le après bascule prod.
4) Divi 5 / Avada : vider les assets compilés
Sur Divi/Avada, les répertoires exacts varient selon versions et réglages. Je pars d’une règle simple : supprimer les caches/compiled assets dans uploads et wp-content si identifiés, sans toucher aux médias.
# Exemples prudents (à adapter selon votre site)
rm -rf /var/www/site-staging/wp-content/et-cache 2>/dev/null || true
rm -rf /var/www/site-staging/wp-content/uploads/fusion-styles 2>/dev/null || true
5) Cron : vérifier les événements bloqués
Après restauration, j’ai souvent vu des sites avec des tâches cron “en retard” (ex: indexation, envoi, nettoyage). Vérifiez :
cd /var/www/site-staging
wp cron event list --fields=hook,next_run,recurrence --allow-root | head -n 30
Étape 7 : revenir en production (bascule contrôlée)
La bascule la plus fiable : préparez un répertoire “release”, puis échangez un symlink. Ça réduit le downtime et évite les états intermédiaires.
1) Stratégie simple par symlink
Exemple : /var/www/site_current pointe vers /var/www/releases/2026-04-15-1200.
# Arborescence
mkdir -p /var/www/releases/2026-04-15-1200
# Restaurer dans release (mêmes étapes que staging)
# ... (core download + wp-content + import DB si DB dédiée)
# Bascule atomique
ln -sfn /var/www/releases/2026-04-15-1200 /var/www/site_current
# Reload PHP-FPM/Nginx si nécessaire (selon votre stack)
systemctl reload php8.2-fpm 2>/dev/null || true
systemctl reload nginx 2>/dev/null || true
2) Si vous restaurez sur la même base que la prod
Évitez si possible. Sinon :
- Maintenance activée.
- Export DB actuel (déjà fait).
- Import DB backup.
- Search-replace si besoin.
- Flush permaliens + purge caches.
- Désactivation maintenance.
3) Sortir du mode maintenance
cd /var/www/site_current
wp maintenance-mode deactivate --allow-root
Fichiers de configuration complets
Les fichiers ci-dessous sont des bases saines pour WordPress 6.9.4+ et PHP 8.1+. Adaptez les chemins, domaines et sockets.
.htaccess (Apache) – WordPress + headers de base
<IfModule mod_rewrite.c>
RewriteEngine On
# Si WordPress est dans un sous-dossier, adaptez RewriteBase
RewriteBase /
# Éviter l'indexation de répertoires
Options -Indexes
# Règles WordPress
RewriteRule ^index.php$ - [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /index.php [L]
</IfModule>
# Headers de sécurité (à ajuster selon besoins)
<IfModule mod_headers.c>
Header always set X-Content-Type-Options "nosniff"
Header always set X-Frame-Options "SAMEORIGIN"
Header always set Referrer-Policy "strict-origin-when-cross-origin"
Header always set Permissions-Policy "geolocation=(), microphone=(), camera=()"
</IfModule>
# Empêcher l'accès direct à certains fichiers sensibles
<FilesMatch "(^.|wp-config.php|readme.html|license.txt)">
Require all denied
</FilesMatch>
nginx.conf (server block) – WordPress + PHP-FPM + blocage fichiers sensibles
server {
listen 80;
server_name example.com www.example.com;
root /var/www/site_current;
index index.php index.html;
# Logs (indispensables pour diagnostiquer une restauration)
access_log /var/log/nginx/site_access.log;
error_log /var/log/nginx/site_error.log;
# Taille upload (à ajuster)
client_max_body_size 64m;
# Fichiers sensibles
location ~* /(wp-config.php|readme.html|license.txt) {
deny all;
}
# Bloquer l'exécution PHP dans uploads (réduit l'impact d'une compromission)
location ~* ^/wp-content/uploads/.*.php$ {
deny all;
}
# WordPress permaliens
location / {
try_files $uri $uri/ /index.php?$args;
}
# PHP
location ~ .php$ {
include snippets/fastcgi-php.conf;
# Adaptez le socket/port PHP-FPM selon votre version
fastcgi_pass unix:/run/php/php8.2-fpm.sock;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include fastcgi_params;
}
# Cache-control statique (prudence si vous avez un CDN)
location ~* .(css|js|jpg|jpeg|png|gif|svg|webp|ico|woff2?)$ {
expires 7d;
add_header Cache-Control "public, max-age=604800";
try_files $uri =404;
}
}
wp-config.php (base saine + debug contrôlé)
<?php
/**
* wp-config.php pour WordPress 6.9.4+ (PHP 8.1+)
* Adaptez DB_* et les clés.
*/
define( 'DB_NAME', 'site_staging' );
define( 'DB_USER', 'site_staging_user' );
define( 'DB_PASSWORD', 'ChangezMoi-Long-Mdp' );
define( 'DB_HOST', 'localhost' );
define( 'DB_CHARSET', 'utf8mb4' );
define( 'DB_COLLATE', '' );
/**
* Si vous restaurez un dump avec un préfixe différent, adaptez-le ici.
* Exemple courant : 'wp_'.
*/
$table_prefix = 'wp_';
/**
* Clés et sels : régénérez-les si vous suspectez une fuite/compromission.
* https://api.wordpress.org/secret-key/1.1/salt/
*/
define( 'AUTH_KEY', 'changez-moi' );
define( 'SECURE_AUTH_KEY', 'changez-moi' );
define( 'LOGGED_IN_KEY', 'changez-moi' );
define( 'NONCE_KEY', 'changez-moi' );
define( 'AUTH_SALT', 'changez-moi' );
define( 'SECURE_AUTH_SALT', 'changez-moi' );
define( 'LOGGED_IN_SALT', 'changez-moi' );
define( 'NONCE_SALT', 'changez-moi' );
/**
* Debug : sur staging, activez; sur production, logguez sans afficher.
*/
define( 'WP_DEBUG', true );
define( 'WP_DEBUG_LOG', true );
define( 'WP_DEBUG_DISPLAY', false );
@ini_set( 'display_errors', '0' );
/**
* Limites mémoire (à ajuster selon builders).
* Elementor/Divi/Avada peuvent nécessiter plus en édition.
*/
define( 'WP_MEMORY_LIMIT', '256M' );
define( 'WP_MAX_MEMORY_LIMIT', '512M' );
/**
* Désactiver l'éditeur de fichiers dans l'admin (réduit le risque).
*/
define( 'DISALLOW_FILE_EDIT', true );
/**
* Forcer HTTPS derrière proxy (si applicable).
* À activer uniquement si vous terminez TLS en amont.
*/
// if ( isset( $_SERVER['HTTP_X_FORWARDED_PROTO'] ) && $_SERVER['HTTP_X_FORWARDED_PROTO'] === 'https' ) {
// $_SERVER['HTTPS'] = 'on';
// }
if ( ! defined( 'ABSPATH' ) ) {
define( 'ABSPATH', __DIR__ . '/' );
}
require_once ABSPATH . 'wp-settings.php';
php.ini (ou override PHP-FPM) – valeurs typiques restauration/migration
; php.ini (extraits) - adaptez selon votre hébergement
memory_limit = 512M
max_execution_time = 180
max_input_time = 180
post_max_size = 64M
upload_max_filesize = 64M
; Logs d'erreurs (chemin selon distro)
log_errors = On
error_log = /var/log/php/php_errors.log
; Opcache (souvent activé en prod)
opcache.enable=1
opcache.memory_consumption=256
opcache.interned_strings_buffer=16
opcache.max_accelerated_files=20000
opcache.validate_timestamps=1
opcache.revalidate_freq=2
Vérification
Ne validez pas “à l’œil”. Validez par commandes : HTTP, base, WordPress, et logs.
1) Vérifier la réponse HTTP et les headers
# Vérifier que la home répond
curl -I https://www.example.com
# Vérifier une page interne (pour détecter 404 permaliens)
curl -I https://www.example.com/une-page/
2) Vérifier WordPress via WP-CLI
cd /var/www/site_current
# Version core
wp core version --allow-root
# Vérifier l'intégrité des fichiers core
wp core verify-checksums --allow-root
# Vérifier siteurl/home
wp option get siteurl --allow-root
wp option get home --allow-root
# Lister les plugins actifs (repérer un plugin activé qui casse tout)
wp plugin list --status=active --allow-root
3) Vérifier la base (taille, tables, erreurs)
mysql -u DB_USER -p -D DB_NAME -e "SHOW TABLE STATUSG" | head -n 60
# Vérifier l'encodage (utf8mb4 attendu)
mysql -u DB_USER -p -D DB_NAME -e "SHOW VARIABLES LIKE 'character_set_server';"
mysql -u DB_USER -p -D DB_NAME -e "SHOW VARIABLES LIKE 'collation_server';"
4) Vérifier les logs en temps réel
# Nginx
tail -f /var/log/nginx/site_error.log
# PHP-FPM (chemin selon distro)
tail -f /var/log/php8.2-fpm.log 2>/dev/null || true
tail -f /var/log/php/php_errors.log 2>/dev/null || true
Si ça ne marche pas
Quand une restauration échoue, la tentation est de “réessayer en changeant un truc au hasard”. Vous perdrez du temps. Faites un diagnostic par couches : DNS/TLS, serveur web, PHP, WordPress, base, cache.
Tableau de diagnostic rapide
| Symptôme | Cause probable | Vérification | Solution |
|---|---|---|---|
| HTTP 500 immédiat | Fatal PHP, plugin incompatible, fichier manquant | tail -f logs PHP-FPM/Nginx |
Désactiver plugins via renommage, vérifier wp core verify-checksums |
| Redirection en boucle | URL home/siteurl, HTTPS derrière proxy, règles Nginx | wp option get home, curl -I -L |
Corriger options, config proxy HTTPS |
| /wp-admin renvoie 404 | Permaliens/rules, vhost mal configuré | wp rewrite flush, check try_files |
Flush rewrite, corriger Nginx/Apache |
| Page blanche (front) | Erreur JS, assets cache, builder incomplet | Logs + vérifier fichiers CSS générés | Purger caches, supprimer CSS générés Elementor/Divi |
| “Error establishing a database connection” | DB credentials, DB down, socket/host | mysql -u ..., logs MySQL |
Corriger wp-config.php, redémarrer DB |
| Site revient mais contenu “ancien” | Mauvaise sauvegarde (mauvaise date) ou cache CDN | Comparer date dump, purge CDN | Restaurer backup cohérent, purge CDN |
1) Désactiver tous les plugins sans accès admin
Technique simple : renommer le dossier plugins. WordPress n’arrive plus à charger les plugins actifs, donc il les désactive.
cd /var/www/site_current/wp-content
mv plugins plugins.disabled.$(date +%F-%H%M)
Si le site revient, réactivez progressivement (en renommant le dossier puis via WP-CLI) :
cd /var/www/site_current/wp-content
mv plugins.disabled.2026-04-15-1200 plugins
cd /var/www/site_current
wp plugin activate nom-du-plugin --allow-root
2) Revenir à un thème par défaut
Quand un thème (ou un builder) casse le front, forcer un thème core permet d’isoler. Faites-le via WP-CLI :
cd /var/www/site_current
# Exemple : activer Twenty Twenty-Five si installé
wp theme activate twentytwentyfive --allow-root
3) Vérifier l’intégrité des fichiers core
cd /var/www/site_current
wp core verify-checksums --allow-root
4) Vérifier que le dump SQL n’est pas tronqué
Un dump interrompu finit souvent au milieu d’un INSERT. Indice : la dernière ligne est coupée.
tail -n 5 /chemin/backup-db.sql
# Si .gz
zcat /chemin/backup-db.sql.gz | tail -n 5
5) Vérifier les erreurs MySQL
# Statut du service
systemctl status mysql 2>/dev/null || systemctl status mariadb 2>/dev/null || true
# Logs (chemins variables)
tail -n 200 /var/log/mysql/error.log 2>/dev/null || true
tail -n 200 /var/log/mariadb/mariadb.log 2>/dev/null || true
Pièges et erreurs courantes
| Erreur | Cause | Solution |
|---|---|---|
| Restauration partielle (fichiers d’un jour, base d’un autre) | Backups séparés, mauvaise sélection | Restaurer un couple cohérent (même timestamp), sinon accepter une incohérence et corriger manuellement |
| Import SQL “réussi” mais site demande l’installation | Mauvaise base, mauvais préfixe, tables vides | Vérifier $table_prefix, SHOW TABLES, options siteurl/home |
| Copier un snippet trouvé sur un ancien tuto | Code incompatible PHP 8.1+ ou WordPress 6.9.4 | Éviter les hacks SQL sur sérialisation, préférer wp search-replace, vérifier docs officielles |
| Oublier de purger caches (plugin + serveur + CDN) | Pages/JS/CSS servis depuis cache | Supprimer caches locaux, purger fastcgi_cache/varnish/CDN, forcer recompile assets builder |
| Tester en production sans sauvegarde | Pression, urgence | Snapshot fichiers + dump DB avant toute action (même si “cassé”) |
| Permissions cassées après extraction | Archive extraite en root, propriétaire incorrect | chown -R + chmod cohérents, vérifier logs “Permission denied” |
| Oublier de régénérer permaliens | Rewrite rules non mises à jour | wp rewrite flush --hard |
| Confusion action rapide vs réparation durable | On “désactive un plugin” mais on ne corrige pas la cause | Isoler (plugins/thème), corriger, puis réactiver proprement |
Sécurité serveur
Restaurer, c’est aussi une opportunité de refermer des portes. Si la panne est liée à une compromission, la restauration seule ne suffit pas.
1) Bloquer l’exécution PHP dans uploads (Nginx/Apache)
Déjà montré côté Nginx. Côté Apache, ajoutez :
# À placer dans un .htaccess sous wp-content/uploads/ si AllowOverride le permet
<FilesMatch ".php$">
Require all denied
</FilesMatch>
2) Régénérer les clés/sels WordPress si doute
Si vous suspectez un vol de cookies/sessions, régénérez les clés dans wp-config.php. Source officielle : WordPress.org – Secret-Key Service.
3) Vérifier les comptes admin et mots de passe
Commande utile :
cd /var/www/site_current
# Liste des admins (identifiez les inconnus)
wp user list --role=administrator --fields=ID,user_login,user_email,registered --allow-root
4) Désactiver l’édition de fichiers
Déjà dans le wp-config.php : DISALLOW_FILE_EDIT.
5) Réduire la surface d’attaque via permissions
- Pas de
777. wp-config.phpen640(ou plus strict selon votre modèle).- Évitez que l’utilisateur PHP-FPM puisse écrire partout : idéalement, écriture limitée à
wp-content/uploadset éventuellementwp-content/cachesi nécessaire.
Ressources
- Developer Resources – Advanced Administration
- WP-CLI – Command reference
- WordPress – Requirements
- Developer Reference – wp_mail() (utile pour diagnostiquer des emails qui partent depuis staging)
- GitHub – WordPress/wordpress-develop (pour vérifier le core et suivre les changements)
- WordPress Core Trac (tickets si vous suspectez un bug core)
- PHP Manual – OPcache configuration
FAQ
Dois-je restaurer les fichiers avant la base, ou l’inverse ?
Sur un staging, je fais généralement : core propre → wp-content → wp-config.php → import DB → search-replace → flush permaliens. En production, l’ordre dépend de votre méthode de bascule, mais gardez l’idée : fichiers et base doivent correspondre.
Je n’ai qu’une sauvegarde des fichiers, pas de la base. Je peux récupérer le site ?
Vous récupérerez le thème, les plugins et les médias, mais pas le contenu (pages/articles/options) qui est en base. Sans dump SQL, la restauration complète est impossible. À défaut : tentez de retrouver un dump chez l’hébergeur, ou dans un plugin de backup, ou dans des snapshots.
Après restauration, j’ai des 404 partout sauf la home
Classique : règles de réécriture. Exécutez wp rewrite flush --hard et vérifiez la config Nginx (try_files) ou le .htaccess.
Après import SQL, mon site redirige vers l’ancien domaine
Corrigez home et siteurl via WP-CLI, puis faites un wp search-replace sur l’ancien domaine. Évitez les remplacements SQL bruts sur données sérialisées.
Je vois “Error establishing a database connection” alors que j’ai importé le dump
Vérifiez d’abord que PHP peut se connecter : identifiants dans wp-config.php, host (localhost vs socket), et que le service DB tourne. Testez avec mysql -u ... depuis le serveur.
WP-CLI ne marche pas (fatal error) alors que le site est cassé
Renommez wp-content/plugins pour désactiver les plugins, puis relancez WP-CLI. WP-CLI charge WordPress, donc un plugin fatal peut aussi le casser.
Dois-je restaurer le dossier wp-content/cache ?
Non. C’est rarement utile et souvent nuisible (cache incohérent). Je le supprime presque systématiquement après restauration.
Elementor/Divi/Avada : pourquoi la mise en page est cassée après restauration ?
Souvent à cause d’assets compilés (CSS/JS) qui ne correspondent plus à la base restaurée, ou d’un cache serveur/CDN. Supprimez les CSS générés (ex: uploads/elementor/css), purgez caches, puis laissez le builder régénérer.
Comment éviter d’envoyer des emails depuis le staging restauré ?
Le plus sûr : bloquer SMTP en sortie (réseau) ou configurer un plugin SMTP vers un faux serveur. À minima, changez l’email admin et désactivez les automatisations (newsletter, WooCommerce) le temps de valider.
J’ai restauré, mais l’admin est très lente
Regardez les logs PHP-FPM (timeouts), la santé de la base (indexes, tables crashées), et l’object cache (Redis/Memcached) : un object-cache.php incohérent peut ralentir ou casser. Testez temporairement sans object cache.