Migrer un site WordPress sans temps d'arret

Credit : Logo officiel

Migrer un site WordPress sans temps d'arret

Dylan D. — Agent Support Technique Serveur WordPress 2527 mots 13 min de lecture

Migrer un site WordPress sans temps d'arret

Le mois dernier, j'ai migre un site WooCommerce de 12 Go (8 Go de fichiers + 4 Go de base de donnees) avec environ 400 commandes par jour. Le client voulait basculer d'un mutualise sature vers un VPS IONOS Performance, sans aucune coupure visible. Resultat : downtime mesure a zero seconde, aucune commande perdue, zero ticket SAV. La methode est rodee, et je te la donne en detail.

L'idee fondamentale tient en une phrase : on prepare le nouveau serveur en parallele, on synchronise les fichiers et la base plusieurs fois, on bascule le DNS apres avoir teste, et on garde l'ancien actif tant que la propagation DNS n'est pas finie. Pas de magie, juste de la rigueur.

Preparer la migration : la checklist J-7

Une semaine avant la bascule, je fais ces verifications systematiquement :

  1. Inventaire de la stack actuelle : version WordPress, version PHP, version MySQL/MariaDB, plugins payants avec leurs licences, theme custom, certificats SSL, redirections htaccess.
  2. Estimation du volume : du -sh /var/www/wordpress pour les fichiers et du -sh /var/lib/mysql/wordpress_db pour la base.
  3. Plan de rollback : qu'est-ce qu'on fait si la bascule echoue ? Reponse : on remet l'ancien IP dans le DNS, le TTL court permet de revenir en 5 minutes.
  4. Baisser le TTL : a J-2, on passe le TTL des enregistrements A/AAAA a 300 secondes (5 minutes) chez IONOS. Ca evite que les resolveurs gardent l'ancienne IP en cache pendant 24h apres la bascule.
  5. Communication : prevenir l'equipe de modos/redaction qu'ils ne doivent pas publier le jour J pour eviter de perdre du contenu entre deux synchros.

Pieges classiques a auditer avant

Avant la moindre rsync, je verifie ces details qui font perdre des heures si oublies :

Etape 1 : Preparer le nouveau serveur

Sur le nouveau VPS IONOS Debian 12, on installe la stack LEMP a jour :

apt update && apt upgrade -y
apt install nginx mariadb-server php8.3-fpm php8.3-mysql php8.3-xml \
            php8.3-mbstring php8.3-curl php8.3-zip php8.3-gd php8.3-imagick \
            php8.3-intl php8.3-bcmath redis-server -y
mysql_secure_installation

WP-CLI :

curl -O https://raw.githubusercontent.com/wp-cli/builds/gh-pages/phar/wp-cli.phar
chmod +x wp-cli.phar && mv wp-cli.phar /usr/local/bin/wp

Creation de la base et de l'utilisateur dedie :

mysql -e "CREATE DATABASE wordpress_db DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;"
mysql -e "CREATE USER 'wp_user'@'localhost' IDENTIFIED BY 'MotDePasseSolide!2026';"
mysql -e "GRANT ALL ON wordpress_db.* TO 'wp_user'@'localhost'; FLUSH PRIVILEGES;"

Replique le php.ini (memory_limit, upload_max_filesize, post_max_size) en accord avec l'ancien environnement. C'est la qu'on perd des heures de debug si on oublie : un site qui tournait avec memory_limit = 512M et qui se retrouve a 128M plante a la premiere sauvegarde de page.

; /etc/php/8.3/fpm/php.ini
memory_limit = 512M
upload_max_filesize = 64M
post_max_size = 64M
max_execution_time = 300
max_input_vars = 3000

Vhost Nginx initial

Cree /etc/nginx/sites-available/monsite.fr :

server {
    listen 80;
    listen [::]:80;
    server_name monsite.fr www.monsite.fr;
    root /var/www/wordpress;
    index index.php;

    location / {
        try_files $uri $uri/ /index.php?$args;
    }

    location ~ \.php$ {
        include snippets/fastcgi-php.conf;
        fastcgi_pass unix:/run/php/php8.3-fpm.sock;
    }

    location ~ /\.ht { deny all; }
}

Le SSL on le posera apres la bascule DNS via Certbot, parce que Let's Encrypt valide le challenge HTTP via le domaine, donc tant que le DNS n'a pas bascule, on ne peut pas emettre le certificat sur le nouveau serveur. Si tu veux un certificat avant, utilise un challenge DNS-01 ou un wildcard.

Etape 2 : Synchroniser les fichiers avec rsync

Premiere synchro complete depuis l'ancien serveur :

rsync -avz --progress -e "ssh -p 22 -i ~/.ssh/id_ed25519" \
      /var/www/wordpress/ \
      admin@nouveau-serveur.ionos.fr:/var/www/wordpress/

-a preserve permissions, dates, liens symboliques. -v verbeux. -z compresse a la volee, utile sur lien lent. Cette synchro peut prendre 10 minutes a 2 heures selon la taille et le debit.

Les synchros suivantes (qu'on lance une ou deux fois par jour jusqu'a la bascule finale) sont incrementales et donc rapides :

rsync -avz --delete -e "ssh -p 22" \
      /var/www/wordpress/ \
      admin@nouveau-serveur.ionos.fr:/var/www/wordpress/

Le --delete supprime sur la destination les fichiers qui n'existent plus sur la source : indispensable pour avoir un miroir exact, mais redoutable si tu te trompes de chemin. Verifie deux fois avant d'appuyer sur entree.

Permissions correctes apres rsync

Sur le nouveau serveur :

chown -R www-data:www-data /var/www/wordpress
find /var/www/wordpress -type d -exec chmod 755 {} \;
find /var/www/wordpress -type f -exec chmod 644 {} \;
chmod 600 /var/www/wordpress/wp-config.php

Etape 3 : Exporter et importer la base

Sur l'ancien serveur :

cd /var/www/wordpress
wp db export /tmp/migration.sql --add-drop-table --default-character-set=utf8mb4
scp /tmp/migration.sql admin@nouveau-serveur.ionos.fr:/tmp/

Sur le nouveau, edite d'abord /var/www/wordpress/wp-config.php avec les nouveaux identifiants de base, puis :

cd /var/www/wordpress
wp db import /tmp/migration.sql
wp cache flush

Pour les tres grosses bases

A partir de 2 a 3 Go, mysqldump devient lent. mydumper parallelise l'export et est 5 a 10 fois plus rapide :

apt install mydumper -y
mydumper -h localhost -u root -p MOT_DE_PASSE -B wordpress_db -o /tmp/dump --threads=4 --compress
rsync -avz /tmp/dump/ admin@nouveau-serveur:/tmp/dump/
# Sur le nouveau
myloader -h localhost -u root -p MOT_DE_PASSE -B wordpress_db -d /tmp/dump --threads=4

Base avec replication maitre/esclave

Si le site est sous une replication MySQL (cas plus rare en WordPress mais pas inexistant pour les boutiques a fort trafic), on prepare le nouveau serveur en esclave de l'ancien pendant la phase de transition. Sur le nouveau :

CHANGE MASTER TO MASTER_HOST='ancien-serveur.fr',
  MASTER_USER='repl_user',
  MASTER_PASSWORD='secret',
  MASTER_LOG_FILE='mysql-bin.000123',
  MASTER_LOG_POS=4567;
START SLAVE;

Le nouveau encaisse en continu les modifications de l'ancien. Au moment de la bascule, on stoppe l'ecriture cote ancien (mode maintenance), on attend le Seconds_Behind_Master = 0, on promote le nouveau, on bascule le DNS. Downtime sub-seconde mesurable. C'est plus complexe a mettre en place, reserve aux migrations critiques.

Etape 4 : Mettre a jour les URLs si necessaire

Si tu changes de domaine ou que tu passes en HTTPS :

wp search-replace 'http://ancien-domaine.fr' 'https://nouveau-domaine.fr' \
   --all-tables --precise --skip-columns=guid
wp search-replace 'ancien-domaine.fr' 'nouveau-domaine.fr' \
   --all-tables --precise --skip-columns=guid

--precise gere correctement les chaines serializees PHP (objets WordPress et metadonnees). C'est crucial : un sed brutal va casser les serializations et tu te retrouves avec des widgets blancs et des metadonnees corrompues.

Verifications :

wp option get siteurl
wp option get home
wp option pluck wp_options home

Methode alternative : Duplicator Pro

Si tu preferes le graphique ou que tu n'as pas d'acces SSH a l'ancien hebergement (mutualise) :

  1. Installer Duplicator Pro sur l'ancien site.
  2. Creer un package complet (archive + installer.php).
  3. Telecharger les deux fichiers et les uploader sur le nouveau serveur dans /var/www/wordpress.
  4. Modifier le /etc/hosts de ta machine pour pointer le domaine sur la nouvelle IP.
  5. Acceder a https://monsite.fr/installer.php et suivre l'assistant.
  6. Duplicator s'occupe de l'import SQL et du search-replace.

Perso, je prefere rsync + WP-CLI pour les sites au-dessus de 5 Go : plus rapide, plus de controle, et les synchros incrementales pendant la phase de bascule sont imbattables. Duplicator est tres bon pour les sites de quelques centaines de Mo ou quand l'acces SSH cote source est inexistant.

Etape 5 : Tester avant la bascule DNS

Modifie ton /etc/hosts local pour pointer vers le nouveau serveur :

echo "203.0.113.50 monsite.fr www.monsite.fr" | sudo tee -a /etc/hosts

Navigue le site comme un utilisateur :

Cote serveur, regarde les logs en temps reel :

tail -f /var/log/nginx/error.log /var/log/php8.3-fpm.log

Si tout est vert pendant 30 minutes de tests, c'est bon signe.

Tests automatises avec WP-CLI

Pour les sites un peu massifs, je lance une serie de checks scriptes :

wp core verify-checksums --path=/var/www/wordpress
wp plugin verify-checksums --all --path=/var/www/wordpress
wp option list --search='*url*' --path=/var/www/wordpress
wp user list --field=user_email --path=/var/www/wordpress | head
wp post list --post_type=product --posts_per_page=5 --path=/var/www/wordpress

Les deux premiers verifient l'integrite des fichiers core et des plugins (super utile pour reperer un fichier corrompu pendant le rsync). Les autres font des smoke tests sur les donnees pour s'assurer que la base est complete.

Etape 6 : Synchro finale et bascule DNS

Le jour J, prevois une fenetre tranquille (nuit, week-end). Ordre des operations :

wp maintenance-mode activate --path=/var/www/wordpress

rsync -avz --delete -e ssh /var/www/wordpress/ admin@nouveau-serveur:/var/www/wordpress/

wp db export --path=/var/www/wordpress | \
  ssh admin@nouveau-serveur 'cat > /tmp/final.sql && cd /var/www/wordpress && wp db import /tmp/final.sql'

wp maintenance-mode deactivate --path=/var/www/wordpress

Puis chez IONOS DNS Manager :

Le TTL c'est le piege classique. Si tu n'as pas baisse a 300 a J-2, les resolveurs DNS continuent de servir l'ancienne IP pendant des heures apres la bascule. Resultat : 50% de tes visiteurs vont sur l'ancien serveur, 50% sur le nouveau, et tes commandes WooCommerce arrivent dans deux bases differentes. Cauchemar a reconcilier.

Maintenir l'ancien serveur actif

Ne coupe pas l'ancien serveur tout de suite. Garde-le en lecture seule (ou complet) pendant 48 a 72 heures, le temps que la propagation DNS soit complete sur tous les resolveurs de la planete. Surveille les logs des deux serveurs : si l'ancien n'a plus aucune requete pendant 24h, tu peux le couper en toute tranquillite.

Une astuce que j'utilise : sur l'ancien, je modifie le vhost Nginx pour rediriger toutes les requetes vers le nouveau pendant la fenetre de propagation, en s'appuyant sur le Host et redirigeant en 302 (pas 301, sinon les navigateurs cachent la redirection). Comme ca meme les visiteurs qui arrivent sur l'ancien voient le nouveau site.

Verification post-migration

dig +short monsite.fr @8.8.8.8
dig +short monsite.fr @1.1.1.1
dig +short monsite.fr @9.9.9.9

curl -I https://monsite.fr
curl -vI https://monsite.fr 2>&1 | grep -E 'subject:|expire date'

certbot --nginx -d monsite.fr -d www.monsite.fr

Flush des caches :

wp cache flush --path=/var/www/wordpress
wp transient delete --all --path=/var/www/wordpress
systemctl reload php8.3-fpm nginx

Supprime la ligne dans /etc/hosts local. Demande aux clients (et a Google Search Console) de reverifier la propriete du domaine si necessaire.

Comparaison de comportement avant/apres

Un truc que je fais sur les boutiques sensibles : avant de couper l'ancien serveur, je sauvegarde une vingtaine de pages cles avec wget --recursive --level=2 --no-host-directories --directory-prefix=avant, puis pareil sur le nouveau dans apres/. Un simple diff -r avant/ apres/ me dit si du contenu a saute, si des chemins d'images ont change, si des balises meta ont disparu. C'est rustique mais imparable pour detecter les regressions invisibles a l'oeil nu sur 500 pages.

wget --recursive --level=2 --no-host-directories --directory-prefix=avant https://monsite.fr
# bascule DNS
wget --recursive --level=2 --no-host-directories --directory-prefix=apres https://monsite.fr
diff -r avant/ apres/ | head -50

Audit SEO post-bascule

Dans les jours qui suivent, je surveille systematiquement :

Erreurs courantes et leur fix

Pour aller plus loin

La migration n'est qu'une etape. Pour fiabiliser et performer ensuite :

La migration n'est plus un evenement stressant

Une fois que tu as la methode, migrer un WordPress devient une operation banale, repetable, et sans surprise. Le secret c'est de ne pas vouloir tout faire d'un coup le jour J : prepare le nouveau serveur des le debut, fais des synchros regulieres, teste en avance via /etc/hosts, et baisse le TTL a J-2. La bascule devient alors une formalite de cinq minutes, et tes visiteurs n'auront jamais vu ton site indisponible.

EDIT 2026 : pour les sites de plusieurs Go de base, regarde du cote de mydumper/myloader qui sont beaucoup plus rapides que mysqldump pour l'export/import. Et si tu fais souvent des migrations, automatise tout ca dans un playbook Ansible : tu economiseras des heures sur le long terme. Pour les boutiques WooCommerce avec tres fort trafic, la replication MySQL temporaire entre l'ancien et le nouveau serveur reste la methode reine pour atteindre un downtime mesure en millisecondes.

# Articles similaires

Sur les memes sujets et plus loin