Contrairement à Apache, nginx ne lit pas de fichier .htaccess à chaque requête : toute la configuration doit être écrite explicitement dans le bloc serveur, une fois pour toutes. C’est un changement d’habitude pour un développeur venu d’un environnement mutualisé habitué au fichier .htaccess généré automatiquement par WordPress. La bonne nouvelle, c’est que cette configuration statique, une fois correcte, est plus rapide à l’exécution et plus simple à auditer.
Ce guide part d’un VPS Debian avec nginx et PHP-FPM déjà installés, et construit un bloc serveur complet pour un site WordPress classique, sans multisite. Chaque section explique pourquoi elle existe, pas seulement ce qu’elle fait.
Le bloc serveur de base
Le fichier se place généralement dans /etc/nginx/sites-available/exemple.fr, avec un lien symbolique vers sites-enabled :
server {
listen 80;
server_name exemple.fr www.exemple.fr;
root /var/www/exemple.fr/public;
index index.php;
access_log /var/log/nginx/exemple.fr-access.log;
error_log /var/log/nginx/exemple.fr-error.log;
}
Ce squelette ne fait encore rien de spécifique à WordPress : il faut y ajouter la gestion des permaliens, l’exécution PHP et la protection des fichiers sensibles.
Gérer les permaliens avec try_files
WordPress s’appuie sur des URL réécrites (les permaliens) qui n’existent pas physiquement sur le disque. La directive try_files reproduit le comportement du .htaccess par défaut :
location / {
try_files $uri $uri/ /index.php?$args;
}
Cette ligne signifie : « essaie de servir le fichier demandé tel quel, sinon essaie un dossier de ce nom, sinon transmets tout à index.php avec les paramètres d’origine ». C’est ce mécanisme qui permet à une URL comme /mon-article/ d’être interprétée correctement par WordPress.
Transmettre les requêtes PHP à PHP-FPM
PHP-FPM tourne en général comme un processus séparé, joignable via un socket Unix ou un port TCP. Le bloc suivant transmet toute requête .php à ce processus :

location ~ \.php$ {
include snippets/fastcgi-php.conf;
fastcgi_pass unix:/run/php/php8.0-fpm.sock;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
}
Le chemin du socket doit correspondre exactement à celui déclaré dans le pool PHP-FPM concerné (fichier dans /etc/php/8.0/fpm/pool.d/). Une erreur fréquente consiste à copier un exemple trouvé en ligne sans vérifier ce chemin, ce qui provoque une erreur 502 Bad Gateway sur chaque page dynamique.
Protéger les fichiers sensibles
Certains fichiers ne doivent jamais être servis directement par le navigateur, même s’ils sont accessibles par leur chemin exact :
wp-config.php, qui contient les identifiants de la base de données.- Les fichiers cachés commençant par un point, comme
.gitou.envs’ils traînent par erreur. - Les fichiers XML et journaux qui ne servent qu’en interne.
location ~ /wp-config.php {
deny all;
}
location ~ /\. {
deny all;
}
Bloquer l’exécution PHP dans les uploads
Le dossier wp-content/uploads ne devrait jamais exécuter de script PHP : c’est un vecteur classique d’intrusion, lorsqu’un fichier malveillant déguisé en image y est déposé puis exécuté directement. Un bloc dédié referme cette porte :
location ~* /wp-content/uploads/.*\.php$ {
deny all;
}
Mettre en cache les fichiers statiques
Les images, feuilles de style et scripts n’ont pas besoin de repasser par PHP à chaque requête. Une directive dédiée fixe une durée de cache navigateur raisonnable :
location ~* \.(jpg|jpeg|png|gif|css|js|woff2)$ {
expires 30d;
access_log off;
}
Une configuration nginx correcte pour WordPress tient toujours sur moins d’une centaine de lignes. Si le fichier grandit sans cesse, c’est souvent le signe d’un contournement mal compris plutôt que d’un vrai besoin.
Notre verdict
Écrire ce bloc serveur soi-même, plutôt que de copier un exemple générique trouvé en ligne, oblige à comprendre chaque directive. C’est un investissement de trente minutes qui évite des heures de diagnostic plus tard, le jour où une page blanche apparaît en production et qu’il faut savoir exactement ce que le serveur fait de chaque requête.