# Migrer un multisite WordPress vers un nouveau serveur sans casser le mappage

> Un réseau multisite avec des domaines mappés doit changer de serveur sans perdre un seul domaine client. La procédure diffère nettement d'une migration de site simple.

- Auteur : Clément Hadrot
- Publié le : 2024-05-23
- Mis à jour le : 2024-05-23
- Catégorie : Hébergement &amp; serveurs
- URL : https://wpmoderne.dev.wordpress-developpement.fr/hebergement/migrer-multisite-wordpress-nouveau-serveur-mappage/

## L’essentiel

- sunrise.php doit être en place avant même que WordPress ne démarre
- Chaque table wp_X_options garde ses propres siteurl et home
- Le fichier blogs.dir ou la table wp_blogs référence les chemins à vérifier un par un

Le réseau gère 34 sites clients distincts sous une seule installation WordPress multisite, chacun avec son propre nom de domaine mappé plutôt qu'un sous-domaine de la plateforme. Migrer ce genre d'infrastructure vers un nouveau serveur n'a rien à voir avec la migration d'un site WordPress simple, traitée par ailleurs sur ce blog : ici, une erreur sur un seul domaine mappé peut faire disparaître un site client entier du jour au lendemain, sans que les 33 autres ne soient affectés, ce qui rend le problème plus difficile à repérer.

La complexité vient de la façon dont WordPress multisite gère les domaines : chaque sous-site a sa propre entrée `siteurl` et `home` dans sa table d'options dédiée (`wp_2_options`, `wp_3_options`, etc.), et le mappage de domaine personnalisé passe historiquement par un fichier `sunrise.php` chargé avant même l'initialisation normale de WordPress.

## Le rôle central de sunrise.php

Sur un réseau multisite avec domain mapping, le fichier `wp-content/sunrise.php` intercepte la requête entrante dès le tout début du chargement, avant que WordPress ne détermine quel site correspond au domaine demandé. Il interroge la table de mappage (souvent `wp_domain_mapping` selon le plugin utilisé, ou une logique équivalente si le mappage est géré nativement) pour faire correspondre le nom de domaine reçu au bon `blog_id`.

```
// Extrait simplifié de la logique attendue dans sunrise.php
$domain = strtolower($_SERVER['HTTP_HOST']);
$mapped = $wpdb->get_row($wpdb->prepare(
    "SELECT blog_id FROM {$wpdb->base_prefix}domain_mapping WHERE domain = %s",
    $domain
));
if ($mapped) {
    $current_blog->blog_id = $mapped->blog_id;
}
```

Sur la nouvelle machine, si `sunrise.php` n'est pas copié à l'identique et que la constante `SUNRISE` n'est pas définie dans `wp-config.php` avant le chargement du cœur, l'ensemble du mappage de domaine cesse de fonctionner silencieusement : chaque domaine mappé retombe sur le comportement multisite par défaut, souvent une redirection vers le domaine principal du réseau ou une erreur de site introuvable.

## La checklist de migration, domaine par domaine

```
# Vérifier la présence et le contenu de sunrise.php sur la nouvelle machine
diff /ancien-serveur/wp-content/sunrise.php /nouveau-serveur/wp-content/sunrise.php

# Confirmer que la constante SUNRISE est bien définie
grep "define( 'SUNRISE'" /nouveau-serveur/wp-config.php

# Lister l'ensemble des domaines mappés à vérifier un par un après bascule
mysql -e "SELECT domain, blog_id FROM wp_domain_mapping ORDER BY blog_id;"
```

1. Exporter la base complète avec l'ensemble des tables `wp_X_options` de chaque sous-site, pas seulement les tables principales `wp_blogs` et `wp_site`.
2. Copier `sunrise.php` et vérifier la constante `SUNRISE` dans `wp-config.php` avant tout test.
3. Reproduire la configuration serveur web (nginx ou Apache) capable d'accepter les 34 noms de domaine distincts, avec un certificat TLS couvrant chacun d'eux.
4. Basculer le DNS domaine par domaine plutôt qu'en une seule opération globale, pour isoler tout problème sur un seul client à la fois.
5. Vérifier individuellement chaque domaine mappé après bascule, pas seulement un échantillon.

> L'essentiel à retenir : sunrise.php doit être en place avant même que WordPress ne démarre ; Chaque table wp_X_options garde ses propres siteurl et home ; Le fichier blogs.dir ou la table wp_blogs référence les chemins à vérifier un par un

## Le piège des URL absolues stockées en base

Contrairement à un site simple où un remplacement global de `siteurl` suffit souvent, un multisite exige de traiter chaque table `wp_X_options` séparément, et de vérifier les contenus qui embarquent des URL absolues (images dans le contenu des articles, réglages de thème, données sérialisées de certains plugins). Un remplacement brut par recherche-remplacement en base, sans respecter la sérialisation PHP, corrompt silencieusement ces données.

| Élément à vérifier | Piège spécifique au multisite |
| --- | --- |
| Table wp_blogs | Le champ `domain` doit rester cohérent avec le mappage réel |
| wp_X_options par sous-site | siteurl et home distincts pour chaque blog_id |
| Données sérialisées de plugins | Un remplacement d'URL brut casse la sérialisation PHP |

## Certificats TLS pour 34 domaines distincts

Le nouveau serveur doit être capable de délivrer un certificat valide pour chaque domaine mappé, pas uniquement pour le domaine principal du réseau. Une configuration Let's Encrypt via un client compatible avec l'ajout dynamique de domaines (ou un script de génération par lot au moment de la migration) évite de découvrir des erreurs de certificat client par client dans les jours suivant la bascule.

> Sur un multisite mappé, chaque domaine oublié dans la checklist est un client qui découvre lui-même la panne avant l'agence : la vérification exhaustive n'est pas un luxe, c'est la seule façon d'éviter cet appel gênant.

## En résumé

Migrer un réseau WordPress multisite avec domain mapping vers un nouveau serveur exige une rigueur que ne demande pas une migration de site simple : reproduire fidèlement `sunrise.php` et sa constante d'activation, traiter chaque table d'options de sous-site individuellement, et vérifier domaine par domaine plutôt que de se fier à un échantillon. Sur ce réseau de 34 domaines, c'est cette vérification exhaustive, plus que la migration elle-même, qui a représenté l'essentiel du temps passé.
