Aller au contenu principal
Tutoriels

htaccess WordPress : sécurité et performance

Mains sur un clavier mécanique rétroéclairé face à un large écran affichant du code en mode sombre, coloration syntaxique bleu électrique et magenta, une ligne surlignée, tasse et plante floues en arrière-plan

Un htaccess WordPress bien réglé ferme des vecteurs d'attaque entiers, force le HTTPS et pilote le cache navigateur — côté serveur, sans toucher au code du CMS. Le fichier .htaccess est le point de configuration le plus direct d'un site servi par Apache ou LiteSpeed. Encore faut-il savoir quel serveur le lit : Apache et LiteSpeed interprètent le .htaccess à chaque requête, Nginx ne le lit pas du tout et ignore silencieusement ces directives. Le fichier se trouve à la racine de l'installation, à côté de wp-config.php. Règle absolue avant toute modification : en faire une copie. Une seule directive invalide renvoie une erreur 500 sur l'ensemble du site, et le seul retour en arrière fiable est la restauration de la version précédente.

L'essentiel en un coup d'œil

Question Réponse courte
Quel serveur lit le .htaccess ? Apache et LiteSpeed oui, à chaque requête ; Nginx non — il l'ignore totalement
Où se trouve le fichier ? À la racine du site, à côté de wp-config.php
Avant toute modification ? Sauvegarder le fichier — une directive invalide = erreur 500 sur tout le site
Où placer ses propres règles ? Hors des marqueurs # BEGIN WordPress / # END WordPress, réécrits automatiquement
Déjà géré côté Tomco ? Compression, cache navigateur et bloc LSCache — inutile de les dupliquer

Anatomie du htaccess WordPress par défaut

À l'installation, WordPress génère un bloc minimal délimité par deux marqueurs, # BEGIN WordPress et # END WordPress. Il ne contient que la réécriture des permaliens : toute requête qui ne correspond pas à un fichier ou un dossier existant est routée vers index.php.

# BEGIN WordPress
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteRule .* - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization}]
RewriteBase /
RewriteRule ^index\.php$ - [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /index.php [L]
</IfModule>
# END WordPress

Règle structurante : ne jamais écrire entre ces deux marqueurs. WordPress réécrit l'intégralité du bloc dès qu'un permalien est enregistré dans Réglages → Permaliens, ou lors de certaines mises à jour. Toute ligne ajoutée à l'intérieur disparaît sans avertissement. Les règles personnalisées — sécurité, redirections, cache — se placent au-dessus de # BEGIN WordPress ou en dessous de # END WordPress.

Le serveur lit le fichier de haut en bas, à chaque requête, et applique les directives dans l'ordre rencontré. C'est ce qui rend la position des blocs déterminante, en particulier pour les redirections. Sur l'infrastructure de notre hébergement web, LiteSpeed interprète nativement le .htaccess grâce à sa compatibilité Apache : les règles ci-dessous s'appliquent sans adaptation, là où un environnement Nginx pur exigerait de tout convertir en configuration serveur, suivie d'un rechargement du service.

Éditeur de code vu de biais sur écran de verre : arborescence de fichiers à gauche, numéros de ligne de 1 à 22, lignes de configuration floutées, un bloc surligné par une bande de sélection bleue et un curseur magenta
Le .htaccess s'édite à la racine du site, à côté de wp-config.php, et toujours après en avoir copié la version en cours : une seule directive invalide renvoie une erreur 500 sur l'ensemble du site.

Règles de sécurité essentielles du htaccess

Ces règles forment le socle de durcissement que le support Tomco fournit à ses clients, partagé ici dans sa version générique. Chacune ferme un accès précis. Elles complètent — sans les remplacer — les mesures applicatives détaillées dans le guide sécuriser WordPress en 2026, dont le .htaccess est l'application concrète côté serveur.

Protéger wp-config.php. Ce fichier contient les identifiants de base de données et les clés de salage. Interdire son accès HTTP bloque toute lecture directe :

# Interdire l'accès direct à wp-config.php
<Files wp-config.php>
    Require all denied
</Files>

Require all denied est la syntaxe Apache 2.4 et LiteSpeed (l'ancienne forme Order deny,allow / Deny from all relevait d'Apache 2.2). Le scan de wp-config.php est un vecteur constant : l'infrastructure Tomco en bloque des dizaines de milliers de tentatives par mois.

Bloquer xmlrpc.php. L'interface XML-RPC sert d'amplificateur de force brute (méthode system.multicall, qui teste des centaines d'identifiants en une requête) et de levier de déni de service par pingback. Si aucune application mobile, ni Jetpack, ni pingback n'en dépend, la couper entièrement :

# Bloquer XML-RPC si aucun usage légitime
<Files xmlrpc.php>
    Require all denied
</Files>

Interdire l'exécution PHP dans /uploads. Le payload final de nombreuses compromissions est un webshell déposé dans wp-content/uploads. Ce dossier ne doit jamais exécuter de PHP. La règle se place dans un .htaccess distinct, créé dans wp-content/uploads/ :

# wp-content/uploads/.htaccess — bloquer l'exécution de scripts
<FilesMatch "\.(?i:php|phtml|php3|php4|php5|php7|phps)$">
    Require all denied
</FilesMatch>

*Masquer les fichiers `.ht` et couper le listing de répertoires.** Ces deux protections figurent déjà dans la plupart des configurations serveur — c'est le cas chez Tomco — mais les inscrire explicitement ne nuit pas sur un hébergement générique :

# Bloquer l'accès aux fichiers .htaccess / .htpasswd
<FilesMatch "^\.ht">
    Require all denied
</FilesMatch>

# Désactiver l'affichage du contenu des répertoires
Options -Indexes

Diagramme de flux horizontal : un flux de lumière bleue entre par la gauche et traverse trois panneaux de verre successifs — porte de redirection, bouclier de sécurité, bloc de cache — tandis qu'une branche déviée s'éteint en magenta ; le flux ressort vers une sphère filaire de réponse à droite
Le trajet d'une requête : redirections, puis filtres de sécurité, puis cache, avant le routage vers WordPress. Une requête refusée n'atteint jamais PHP.

Le schéma résume l'ordre dans lequel une requête traverse le fichier : redirections d'abord, blocages de sécurité ensuite, règles de cache, puis routage final vers WordPress. Une requête refusée par un Require all denied n'atteint jamais PHP — c'est tout l'intérêt d'un filtrage au niveau serveur, en amont du moteur applicatif.

Limiter les accès aux fichiers sensibles

Au-delà du socle, trois restrictions réduisent encore la surface exposée. Elles supposent un contexte précis : ne les appliquer qu'en connaissance de cause.

Restreindre wp-login.php à une IP fixe. Si l'administration se fait toujours depuis la même adresse (bureau, VPN), verrouiller le formulaire de connexion au niveau serveur écarte la quasi-totalité du brute force avant PHP :

# N'autoriser wp-login.php que depuis une IP de confiance
<Files wp-login.php>
    Require ip 203.0.113.42
</Files>

Remplacer 203.0.113.42 par l'adresse réelle. Éviter de protéger tout le dossier /wp-admin par IP : admin-ajax.php y réside et plusieurs plugins l'appellent depuis le front-end public — une restriction trop large casserait des fonctionnalités visiteurs.

Bloquer des user-agents hostiles. Les scanners automatisés s'annoncent fréquemment par un user-agent caractéristique. Les filtrer réduit le bruit dans les logs :

# Bloquer quelques user-agents d'outils de scan
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteCond %{HTTP_USER_AGENT} (nikto|sqlmap|masscan|libwww-perl) [NC]
RewriteRule .* - [F,L]
</IfModule>

Cette liste reste indicative : un user-agent se falsifie en une ligne. Sur l'infrastructure Tomco, le pare-feu applicatif (ModSecurity) absorbe déjà l'essentiel de ce trafic en amont — la règle relève ici du complément, pas de la première ligne de défense.

Protéger wp-includes. Aucun script de wp-includes n'a vocation à être appelé directement. Le motif officiel de durcissement bloque ces accès, à placer hors des marqueurs WordPress :

# Bloquer l'accès direct aux scripts de wp-includes
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteBase /
RewriteRule ^wp-admin/includes/ - [F,L]
RewriteRule !^wp-includes/ - [S=3]
RewriteRule ^wp-includes/[^/]+\.php$ - [F,L]
RewriteRule ^wp-includes/js/tinymce/langs/.+\.php - [F,L]
RewriteRule ^wp-includes/theme-compat/ - [F,L]
</IfModule>

Ne pas appliquer ce bloc sur une installation multisite, où il casse des chemins légitimes — la documentation de durcissement WordPress le précise.

Performance : cache navigateur et compression

Deux mécanismes accélèrent le rendu sans plugin : le cache navigateur (mod_expires) indique au navigateur combien de temps conserver chaque type de fichier ; la compression (mod_deflate) réduit le poids transféré du HTML, du CSS et du JavaScript.

Point essentiel pour les clients Tomco : ces deux mécanismes sont déjà actifs par défaut côté serveur. La compression (équivalent LiteSpeed de mod_deflate, Brotli inclus) et les en-têtes de cache navigateur sont appliqués sans configuration. Ajouter les blocs ci-dessous y serait redondant — au mieux sans effet, au pire en conflit avec les en-têtes serveur. Ils restent utiles sur un hébergement Apache générique qui ne les active pas.

# Cache navigateur — REDONDANT chez Tomco (déjà actif côté serveur)
<IfModule mod_expires.c>
ExpiresActive On
ExpiresByType image/webp              "access plus 1 year"
ExpiresByType image/png               "access plus 1 year"
ExpiresByType image/jpeg              "access plus 1 year"
ExpiresByType image/svg+xml           "access plus 1 year"
ExpiresByType text/css                "access plus 1 month"
ExpiresByType application/javascript  "access plus 1 month"
ExpiresByType font/woff2              "access plus 1 year"
ExpiresDefault                        "access plus 2 days"
</IfModule>
# Compression — REDONDANT chez Tomco (compression + Brotli déjà actifs)
<IfModule mod_deflate.c>
AddOutputFilterByType DEFLATE text/html text/plain text/css text/xml
AddOutputFilterByType DEFLATE application/javascript application/json
AddOutputFilterByType DEFLATE application/rss+xml image/svg+xml
</IfModule>

Ne jamais compresser les images matricielles (JPEG, PNG, WebP) ni les polices woff2 : déjà compressées, le gain est nul et le CPU gaspillé. Pour mesurer ce qui est réellement servi, inspecter les en-têtes de réponse (Content-Encoding, Cache-Control) dans l'onglet réseau du navigateur. La référence complète des directives figure dans la documentation Apache de mod_expires.

Redirections propres : HTTPS et www

Les redirections décident de l'URL canonique du site. Deux règles couvrent l'essentiel : forcer HTTPS et choisir une seule forme de domaine (avec ou sans www). Elles se placent au-dessus de # BEGIN WordPress, pour s'exécuter avant le routage vers index.php.

# À placer AVANT le bloc # BEGIN WordPress
<IfModule mod_rewrite.c>
RewriteEngine On

# 1. Forcer HTTPS
RewriteCond %{HTTPS} off
RewriteRule ^ https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301]

# 2. Forcer le domaine sans www
RewriteCond %{HTTP_HOST} ^www\.(.+)$ [NC]
RewriteRule ^ https://%1%{REQUEST_URI} [L,R=301]
</IfModule>

Commentaire ligne à ligne : RewriteCond %{HTTPS} off teste si la connexion n'est pas chiffrée ; la règle suivante renvoie un code 301 (redirection permanente) vers la même URL en https://. Le second bloc capture le www. en tête d'hôte — %1 reprend le groupe entre parenthèses de la condition — et redirige vers la version nue. Imposer www au lieu de l'inverse se fait en miroir.

Deux précautions. D'abord, un code 301 est mémorisé durablement par les navigateurs : tester avec un 302 (temporaire) tant que la cible n'est pas certaine, puis repasser en 301. Ensuite, sur l'infrastructure Tomco, le forçage HTTPS peut être activé au niveau du panneau — la règle 1 devient alors redondante. Vérifier avant de cumuler, sous peine de double redirection (deux sauts au lieu d'un).

Pour rediriger une ancienne page précise, mod_alias suffit, plus lisible qu'une RewriteRule :

# Redirection 301 d'une URL retirée vers son remplacement
Redirect 301 /ancienne-page /nouvelle-page

Jonction de redirection sur panneau de verre : un flux bleu entre par la gauche et se scinde en deux — une route bleue fléchée monte vers un cadenas verrouillé, une route magenta descend vers une croix de rejet
Une seule forme d'URL canonique : le trafic HTTP et www est redirigé en 301 vers la version HTTPS sans www. Chez Tomco, le forçage HTTPS peut déjà être actif au niveau du panneau.

Cohabitation avec LiteSpeed Cache

Le plugin LiteSpeed Cache (LSCache) gère lui-même un bloc dans le .htaccess, délimité par # BEGIN LSCACHE et # END LSCACHE (parfois accompagné de # BEGIN NON_LSCACHE). Il est inséré et régénéré automatiquement à chaque modification des réglages du plugin.

Ne jamais éditer ce bloc à la main. Toute modification est écrasée à la prochaine sauvegarde des réglages LSCache, exactement comme le bloc WordPress. Sur Enhance Panel (Tomco), il est régénéré à chaque activation du plugin — la procédure complète figure dans le tutoriel configurer LiteSpeed Cache sur WordPress.

La cohabitation est simple si l'on respecte un principe : ne pas dupliquer ce que LSCache et le serveur font déjà. Le cache de pages, la conversion WebP à la volée et une partie des en-têtes de cache sont pris en charge par LSCache ; la compression et le cache navigateur le sont par le serveur. Le .htaccess manuel se cantonne alors à ce qui relève vraiment de l'administrateur : les règles de sécurité et les redirections vues plus haut. La documentation LiteSpeed décrit le contenu exact du bloc généré.

Ordre recommandé du fichier, de haut en bas : redirections (HTTPS, www), règles de sécurité (Files, FilesMatch, user-agents), bloc # BEGIN LSCACHE (géré par le plugin), puis bloc # BEGIN WordPress (géré par le cœur). Les deux derniers ne se touchent pas ; les deux premiers sont à vous. Cette répartition vaut pour toute l'architecture LiteSpeed de Tomco, où le .htaccess est lu nativement, sans surcouche ni conversion.

Hébergez votre site sur une infrastructure française sécurisée.

Démarrer avec Tomco

Questions fréquentes

Faut-il modifier le .htaccess entre # BEGIN WordPress et # END WordPress ?

Non. Le bloc délimité par # BEGIN WordPress et # END WordPress est réécrit intégralement par le cœur de WordPress dès qu'un permalien est enregistré, ou lors de certaines mises à jour. Toute ligne ajoutée entre les marqueurs disparaît sans avertissement. Les règles personnalisées — sécurité, redirections, cache — doivent se placer au-dessus de # BEGIN WordPress ou en dessous de # END WordPress, jamais à l'intérieur. Le même principe s'applique au bloc # BEGIN LSCACHE généré par LiteSpeed Cache : il appartient au plugin, pas à l'administrateur.

Le .htaccess fonctionne-t-il sous Nginx ?

Non. Nginx ne lit pas les fichiers .htaccess : il les ignore totalement, silencieusement, sans erreur. Sur un serveur Nginx, les règles de réécriture, de sécurité et de cache doivent être transcrites dans la configuration du serveur (blocs server et location) puis rechargées par l'administrateur. Seuls Apache et les serveurs compatibles Apache lisent le .htaccess à chaque requête. C'est le cas de LiteSpeed : sur l'infrastructure Tomco, LiteSpeed interprète nativement le .htaccess, ce qui rend les règles d'un htaccess WordPress directement applicables, contrairement à un environnement Nginx pur. LiteSpeed Enterprise y sert le fichier nativement, avec un TTFB médian mesuré entre 20 et 50 ms.

Dois-je ajouter des règles de cache et de compression si l'hébergeur les active déjà ?

Pas si l'hébergeur les applique côté serveur. Chez Tomco, la compression (équivalent LiteSpeed de mod_deflate, Brotli inclus) et le cache navigateur sont actifs par défaut : ajouter des blocs mod_expires ou mod_deflate dans le .htaccess y est redondant, au mieux sans effet, au pire en conflit avec les en-têtes serveur. Pour vérifier ce qui est réellement servi, ouvrir l'onglet réseau du navigateur et inspecter les en-têtes Content-Encoding (compression) et Cache-Control (durée de cache) d'une réponse. Ces blocs ne deviennent utiles que sur un hébergement Apache générique qui ne les active pas.

Où placer les redirections HTTPS par rapport au bloc WordPress ?

Au-dessus de la ligne # BEGIN WordPress. Le serveur lit le .htaccess de haut en bas ; placer les redirections HTTPS et www avant le bloc WordPress garantit qu'elles s'exécutent avant le routage vers index.php. Les inscrire à l'intérieur des marqueurs # BEGIN WordPress / # END WordPress les exposerait à l'écrasement automatique. Attention au cumul : si le forçage HTTPS est déjà activé au niveau du panneau d'hébergement, possible chez Tomco, une règle 301 supplémentaire crée une double redirection inutile — vérifier avant d'ajouter.

Comment réparer une erreur 500 après modification du .htaccess ?

Une erreur 500 après édition signale presque toujours une directive invalide ou un module absent dans le .htaccess. La réparation tient en une étape : restaurer la copie de sauvegarde réalisée avant modification. C'est la raison pour laquelle sauvegarder le fichier est la première règle. Sans sauvegarde, renommer le fichier en .htaccess.bak rétablit le site — WordPress fonctionne sans, hors permaliens personnalisés — puis régénérer un bloc propre depuis Réglages, Permaliens, Enregistrer. Réintroduire ensuite les règles une par une isole la directive fautive.