Le projet démarre simple : un serveur, un WordPress, un dossier wp-content/uploads sur le disque local. Puis le trafic grossit, un deuxième serveur applicatif rejoint la ferme derrière un répartiteur de charge, et là le problème saute aux yeux : un média envoyé depuis l’administration sur le serveur A n’existe pas sur le disque du serveur B. Selon la requête qui atterrit sur quel nœud, une image de produit s’affiche ou renvoie une erreur 404.
La solution durable n’est pas de synchroniser les disques entre eux avec rsync en tâche planifiée, ce qui introduit toujours un délai et des risques de conflit d’écriture. La bonne architecture consiste à sortir les médias du système de fichiers local pour les déporter vers un espace de stockage objet compatible S3, partagé par tous les serveurs applicatifs.
Pourquoi le disque local ne suit plus
WordPress a été conçu à l’origine pour un seul serveur avec un seul système de fichiers : la fonction wp_upload_dir() retourne un chemin local, et l’ensemble du cœur (médiathèque, miniatures générées par wp_generate_attachment_metadata(), thèmes, certains caches) suppose que ce chemin est identique et cohérent à chaque requête. Sur une ferme de plusieurs serveurs sans stockage partagé, cette hypothèse se brise dès le premier upload.
Choisir et préparer le bucket
Le principe repose sur un bucket de stockage objet, compatible avec l’API S3 d’Amazon (ce qui inclut des alternatives comme Scaleway Object Storage, OVHcloud Object Storage ou MinIO auto-hébergé), configuré en accès public en lecture pour les fichiers médias, mais en écriture restreinte à des identifiants applicatifs dédiés.

{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "PublicReadMedia",
"Effect": "Allow",
"Principal": "*",
"Action": "s3:GetObject",
"Resource": "arn:aws:s3:::monsite-media/*"
}
]
}
Cette politique de bucket autorise la lecture publique des objets sans exposer la possibilité d’écrire ou de lister le contenu du bucket, ce qui reste réservé aux identifiants applicatifs utilisés par WordPress.
Brancher WordPress sur le stockage objet
Plutôt que de réécrire soi-même les fonctions de gestion des médias, un plugin de type offload (WP Offload Media, ou une solution équivalente) intercepte les uploads pour les envoyer vers le bucket et réécrire les URL générées dans le contenu et la base de données. Les fichiers restent copiés localement au moment de l’upload puis synchronisés, ou sont directement envoyés vers le stockage objet selon le mode choisi.
- Les identifiants d’accès (clé, secret, région, nom du bucket) sont renseignés une seule fois, généralement via des constantes dans
wp-config.phppour éviter qu’ils transitent par l’interface d’administration. - Le plugin réécrit les URL des médias existants lors d’une migration initiale, ce qui peut prendre du temps sur une médiathèque volumineuse.
- Les miniatures générées par WordPress (plusieurs tailles par image) sont également poussées vers le bucket, pas seulement le fichier original.
Le cas des plugins qui écrivent hors de la médiathèque
Certains plugins (générateurs de PDF de facture, exports CSV, caches de génération d’images à la volée) écrivent des fichiers en dehors du flux standard de la médiathèque, directement dans wp-content/uploads ou ailleurs, sans passer par les hooks que le plugin d’offload sait intercepter. Ces cas demandent une vérification manuelle : soit le plugin propose sa propre intégration S3, soit ces fichiers restent volontairement locaux et non partagés, ce qui est acceptable tant qu’ils ne sont pas censés être visibles depuis n’importe quel serveur de la ferme.
| Type de fichier | Faut-il le partager ? |
|---|---|
| Médiathèque WordPress | Oui, via le stockage objet |
| Cache de page (fichiers statiques générés) | Non, reste local par serveur |
| Exports PDF/CSV générés à la demande | Selon le cas, à vérifier plugin par plugin |
Le stockage objet ne remplace pas une réflexion sur ce qui doit réellement être partagé : partager par réflexe tout ce qui s’écrit sur disque revient souvent à déplacer le problème sans le résoudre.
Un sujet volontairement distinct du CDN d’images
Ce partage de médiathèque ne doit pas être confondu avec la mise en place d’un CDN d’images pour la performance, traitée par ailleurs sur ce site : le stockage objet répond à un problème de cohérence entre serveurs applicatifs, tandis qu’un CDN répond à un problème de latence de livraison au visiteur final. Les deux se combinent bien : le bucket S3 comme source de vérité, un CDN devant lui pour la mise en cache géographique, mais ce sont deux briques distinctes à ne pas mélanger dans la même décision d’architecture.
En résumé
Dès qu’un WordPress dépasse un seul serveur applicatif, la médiathèque locale devient le premier point de rupture silencieux de l’architecture. Un stockage objet compatible S3, branché via un plugin d’offload et des identifiants dédiés, règle ce problème de façon durable, à condition de vérifier au cas par cas les plugins qui écrivent des fichiers en dehors du flux standard des médias.