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_KEY ré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 mysql ou un équivalent).
  • Accès aux sauvegardes : archive fichiers (.tar.gz ou .zip) + dump SQL (.sql ou .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.


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.php en 640 (ou plus strict selon votre modèle).
  • Évitez que l’utilisateur PHP-FPM puisse écrire partout : idéalement, écriture limitée à wp-content/uploads et éventuellement wp-content/cache si nécessaire.

Ressources


FAQ

Dois-je restaurer les fichiers avant la base, ou l’inverse ?

Sur un staging, je fais généralement : core propre → wp-contentwp-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.