Credit : Logo officiel
WordPress : changer de domaine proprement avec WP-CLI
WordPress : changer de domaine proprement avec WP-CLI
Mercredi apres-midi, un client e-commerce nous appelle parce que sa migration de domaine a tourne au cauchemar. Il avait son site WordPress 6.4 sur boutique-truc.fr et voulait passer sur boutique-truc.com apres acquisition. Son developpeur a fait un simple UPDATE wp_options SET option_value = REPLACE(...) en SQL pur. Resultat : le site ouvre, mais les widgets ont disparu, le slider d'accueil est casse, le theme a perdu sa config, et les liens internes pointent vers boutique-truc.frcom. Trois heures plus tard, restauration depuis backup et migration refaite avec wp search-replace. Cinq minutes propre.
Changer de nom de domaine sur WordPress, ou passer de HTTP a HTTPS, c'est une etape critique mais qu'on rate facilement. Mal fait, ca casse le site silencieusement (les options sont cassees mais le site charge quand meme). Bien fait avec WP-CLI, c'est propre et rapide. Je te montre la methode complete que j'utilise sur les migrations IONOS.
Pourquoi pas un simple SQL REPLACE ?
C'est l'erreur numero 1 que je vois. Quelqu'un de pas familier avec WordPress se dit "je vais juste faire un REPLACE en SQL" :
-- NE FAITES PAS CA
UPDATE wp_options SET option_value = REPLACE(option_value, 'ancien-domaine.fr', 'nouveau-domaine.fr');
UPDATE wp_postmeta SET meta_value = REPLACE(meta_value, 'ancien-domaine.fr', 'nouveau-domaine.fr');
Le probleme c'est que WordPress stocke beaucoup de donnees serialisees (PHP serialize) dans la base : options des plugins, widgets, Customizer, configurations de theme, settings WooCommerce, et tout un tas d'autres trucs. Un REPLACE SQL casse la serialisation parce qu'il modifie la valeur sans recalculer la longueur.
Exemple concret. La donnee serialisee :
s:24:"http://ancien-domaine.fr"
Le s:24 indique que la chaine fait 24 caracteres. Si tu remplaces par un domaine plus long :
s:24:"http://nouveau-domaine.fr" # FAUX !
La longueur ne correspond plus a la chaine, PHP ne peut plus deserialiser. Resultat :
- Widgets qui disparaissent du site
- Options de theme reinitialisees aux defauts
- Plugins qui perdent leur config
- Menus qui se cassent
- Customizations Elementor/Divi qui sautent
La version correcte aurait du etre s:25 apres le replace, mais SQL ne peut pas calculer ca.
La bonne methode avec WP-CLI
wp search-replace 'https://ancien-domaine.fr' 'https://nouveau-domaine.fr' --skip-columns=guid
WP-CLI gere automatiquement la serialisation. Il deserialise les donnees, fait le remplacement, recalcule les longueurs, et re-serialise correctement. Le bon outil pour le bon job.
Pourquoi --skip-columns=guid
Le champ guid dans wp_posts c'est un identifiant unique permanent assigne a chaque article, page, et media a sa creation. Selon la documentation officielle WordPress, il ne doit jamais etre modifie apres publication.
Si tu changes les GUID :
- Les lecteurs RSS (Feedly, etc.) voient tous les anciens articles comme des nouveaux. Tes abonnes recoivent une notification pour chaque article que tu as deja publie. Spam massif assure.
- Certains plugins qui utilisent le GUID comme reference perdent leurs liaisons.
- Les sitemaps changent, Google reindexe tout, possible chute SEO temporaire.
On voit regulierement des clients qui font le search-replace sans --skip-columns=guid et qui se demandent pourquoi leur flux RSS reenvoit tout. Le guid est techniquement une URL mais sert d'identifiant -- WordPress ne l'utilise jamais pour generer des liens reels.
Procedure complete pas a pas
1. Backup obligatoire
Avant tout, backup complet :
wp db export /home/htdocs/backups/avant-migration-$(date +%Y%m%d-%H%M).sql
Et backup des fichiers pour le worst case :
tar -czf /home/htdocs/backups/files-$(date +%Y%m%d).tar.gz /home/htdocs/web/
2. Dry-run obligatoire
WP-CLI a une option dry-run qui simule sans rien modifier. Toujours la lancer avant le vrai run :
wp search-replace 'https://ancien-domaine.fr' 'https://nouveau-domaine.fr' --skip-columns=guid --dry-run
La sortie te dit combien de remplacements seraient faits dans chaque table :
Table Column Replacements
wp_options option_value 42
wp_postmeta meta_value 156
wp_posts post_content 89
wp_comments comment_content 12
...
Verifie que les chiffres ont du sens. Si t'as 0 remplacement partout, c'est que tu cherches le mauvais domaine. Si tu en as 50 000, soit ton site est tres lie au domaine, soit y'a un truc anormal.
3. Executer le replace
wp search-replace 'https://ancien-domaine.fr' 'https://nouveau-domaine.fr' --skip-columns=guid
WP-CLI affiche le meme tableau que le dry-run mais avec les vrais remplacements effectues.
4. Verifier les options principales
wp option get siteurl
wp option get home
Les deux doivent retourner le nouveau domaine. Si pas le cas (ca arrive avec certaines configs custom) :
wp option update siteurl 'https://nouveau-domaine.fr'
wp option update home 'https://nouveau-domaine.fr'
5. Vider tous les caches
wp cache flush
wp rewrite flush
Si tu as un plugin de cache (W3 Total Cache, WP Super Cache, WP Rocket, LiteSpeed) :
wp w3-total-cache flush all
wp super-cache flush
wp rocket clean --confirm
wp litespeed-purge all
Selon ton plugin, la commande varie. Au pire, va dans le BO et purge le cache manuellement.
Migration HTTP vers HTTPS
Sur les serveurs IONOS, quand un client active le SSL Let's Encrypt sur son domaine, faut basculer toutes les URLs en HTTPS. La methode est identique :
wp search-replace 'http://monsite.fr' 'https://monsite.fr' --skip-columns=guid
Pense aussi aux variantes avec/sans www :
wp search-replace 'http://www.monsite.fr' 'https://www.monsite.fr' --skip-columns=guid
wp search-replace 'http://monsite.fr' 'https://monsite.fr' --skip-columns=guid
L'ordre compte ! Fais d'abord le www. puis le sans-www. Sinon le second remplace les http://monsite.fr (qui font partie de http://www.monsite.fr apres ton premier replace).
Pour eviter les contenus mixtes (HTTPS qui charge du HTTP), force aussi dans le contenu :
wp search-replace 'src="http://' 'src="//' --skip-columns=guid
wp search-replace 'href="http://' 'href="//' --skip-columns=guid
Le // (protocol-relative URL) s'adapte au protocole de la page. Mais c'est decourage en 2026, prefere des URLs https:// explicites.
Migration multisite
Si t'as un WordPress multisite, le wp search-replace marche differemment :
wp search-replace 'https://ancien.fr' 'https://nouveau.fr' --skip-columns=guid --network --url=https://ancien.fr
L'option --network itere sur tous les sites du reseau. L'--url precise sur quel site se baser pour le contexte initial.
Faut aussi mettre a jour wp_blogs :
wp db query "UPDATE wp_blogs SET domain = 'nouveau.fr' WHERE domain = 'ancien.fr'"
Et wp_site :
wp db query "UPDATE wp_site SET domain = 'nouveau.fr' WHERE domain = 'ancien.fr'"
Verification post-migration
Une fois la migration faite, audit complet pour s'assurer qu'il ne reste pas de traces de l'ancien domaine :
wp db search 'ancien-domaine.fr' --stats
L'option --stats te dit combien d'occurrences restent dans chaque table. Idealement zero.
Pour identifier ou il reste des occurrences :
wp db search 'ancien-domaine.fr' --table=wp_options
wp db search 'ancien-domaine.fr' --table=wp_postmeta
Il reste souvent des URLs codees en dur dans les fichiers du theme (header.php, footer.php) ou dans du CSS custom. Le search-replace touche que la base de donnees. Pour les fichiers :
grep -r 'ancien-domaine.fr' /home/htdocs/web/wp-content/themes/
grep -r 'ancien-domaine.fr' /home/htdocs/web/wp-content/uploads/ --include="*.css" --include="*.js"
Migration depuis un autre hebergeur
Quand tu migres un site WordPress depuis un autre hebergeur vers IONOS, tu fais souvent un changement de domaine en plus du changement d'hebergement. La sequence complete :
# 1. Sur l'ancien hebergeur, exporter
wp db export old-site.sql
tar -czf old-files.tar.gz wp-content/
# 2. Transferer vers IONOS
scp old-site.sql old-files.tar.gz user@nouveau-serveur:/home/htdocs/
# 3. Sur IONOS, importer la base et les fichiers
cd /home/htdocs/web/
tar -xzf ../old-files.tar.gz
wp db import ../old-site.sql
# 4. Mettre a jour les URLs
wp search-replace 'https://ancien-domaine.fr' 'https://nouveau-domaine.fr' --skip-columns=guid
# 5. Mettre a jour les options critiques
wp option update siteurl 'https://nouveau-domaine.fr'
wp option update home 'https://nouveau-domaine.fr'
# 6. Vider tous les caches
wp cache flush
wp rewrite flush
Si tu dois garder l'ancien domaine en place le temps de la propagation DNS, edite ton /etc/hosts local pour pointer le nouveau domaine vers la nouvelle IP avant le changement DNS public.
Mettre a jour les redirections 301
Apres une migration de domaine, configure des redirections 301 de l'ancien vers le nouveau pour preserver le SEO. Dans le .htaccess Apache :
RewriteEngine On
RewriteCond %{HTTP_HOST} ^(www\.)?ancien-domaine\.fr [NC]
RewriteRule ^(.*)$ https://nouveau-domaine.fr/$1 [R=301,L]
En Nginx :
server {
listen 80;
listen 443 ssl;
server_name ancien-domaine.fr www.ancien-domaine.fr;
return 301 https://nouveau-domaine.fr$request_uri;
}
Les 301 doivent rester en place plusieurs mois (idealement un an) pour que Google transfere completement le "juice" SEO.
Tester avant de basculer le DNS
Avant de pointer le DNS public sur le nouveau serveur, teste localement en modifiant ton /etc/hosts :
sudo nano /etc/hosts
Ajoute :
195.181.123.45 nouveau-domaine.fr
195.181.123.45 www.nouveau-domaine.fr
L'IP est celle de ton serveur IONOS. Maintenant ton navigateur resout nouveau-domaine.fr vers ce serveur, alors que tout le reste du monde voit encore l'ancien. Tu peux tester completement avant de switcher le DNS public.
Une fois le test OK, change le DNS chez ton registrar. Le TTL est generalement de 3600 secondes (1 heure), donc compte 1-4h pour la propagation complete dans le monde.
N'oublie pas de retirer la ligne du /etc/hosts apres pour que tu vois le DNS reel comme tes visiteurs.
Erreurs courantes et leur fix
"Could not connect to database"
WP-CLI lit wp-config.php pour les credentials. Si le wp-config est casse ou que le user MySQL n'a pas les bons droits, ca plante. Verifie :
wp db check
"Cannot redeclare wp_*" pendant le replace
Un plugin pete pendant l'execution. Desactive temporairement :
wp plugin deactivate --all
wp search-replace ...
wp plugin activate --all
Site casse apres le replace
Restaure le backup :
wp db import /home/htdocs/backups/avant-migration-XXX.sql
Puis investigue. Souvent c'est qu'un plugin stocke des donnees serialisees d'une facon non-standard.
Le replace tourne pendant des heures
Sur des grosses bases (5+ Go), ca peut etre tres long. Ajoute --all-tables si tu as des tables custom non-prefixees :
wp search-replace ... --all-tables
Ou cible juste les tables pertinentes :
wp search-replace ... wp_options wp_postmeta wp_posts
Liens images casses apres migration
Les uploads referencent souvent l'ancien URL. Force le replace dans postmeta :
wp search-replace 'wp-content/uploads' 'wp-content/uploads' --regex --regex-flags=u
Et regenere les thumbnails :
wp media regenerate --yes
Pour aller plus loin
- Migrer un site WordPress sans temps d'arrêt
- Commandes WP-CLI essentielles
- Migrer un petit site WordPress avec BackWPup
- Configurer HTTPS partout : guide SSL/TLS
- Activer le mode debug WordPress
Migration reussie, donnees preservees
WP-CLI 2.10 a ameliore la gestion des serialisations imbriquees, donc si tu avais des soucis avec les anciennes versions, retentes maintenant. Le wp search-replace est l'outil canonique pour toute manipulation d'URL en base WordPress. Apprends a l'utiliser, fais toujours un dry-run d'abord, et garde tes backups.
La migration de domaine c'est pas juste "changer le nom". C'est preserver les options, garder les widgets, conserver les configurations de plugins, maintenir le SEO via 301, et bien sur eviter les contenus mixtes en HTTPS. Avec la methode WP-CLI, tu fais ca proprement en 5 minutes au lieu d'y passer une journee a tout reparer apres une migration cassee. Ton client te remerciera, et toi tu pourras passer aux migrations suivantes en confiance.