💻 Serveur & shell

.htaccess : les règles essentielles

Redirections 301, HTTPS forcé, blocage de fichiers, compression gzip, cache navigateur et debug du .htaccess Apache.

intermédiaire ⏱ 15 min Mise à jour : 2026-04-23

Le .htaccess est un fichier de configuration Apache que vous placez à la racine de votre site (ou dans un sous-dossier). Il permet de redéfinir le comportement du serveur sans toucher à la configuration globale : redirections, réécritures d'URL, contrôle d'accès, compression, cache navigateur. Sur nos hébergements Plesk avec Apache, c'est l'outil le plus direct pour pas mal de besoins courants.

⚠️
Apache uniquement
Le .htaccess est une fonctionnalité d'Apache. Si votre hébergement tourne sur Nginx pur, le fichier est ignoré. Sur nos Plesk, Apache est servi derrière un Nginx reverse proxy : le .htaccess fonctionne pour tout ce qui concerne PHP, les redirections et la réécriture. Pour les règles statiques (compression, cache), la config Nginx prend parfois le relais automatiquement.

Anatomie d'un .htaccess

Un fichier texte simple, une directive par ligne, des commentaires avec #. Les directives sont regroupées par modules Apache (mod_rewrite, mod_expires, mod_deflate, etc.). On les enveloppe dans un <IfModule> pour éviter une erreur 500 si le module n'est pas chargé.

# Forcer l'UTF-8 par défaut
AddDefaultCharset UTF-8

# Désactiver le listing des dossiers
Options -Indexes

# Page d'erreur personnalisée
ErrorDocument 404 /404.php

Forcer HTTPS

À placer tout en haut de votre .htaccess, avant toute autre règle RewriteRule :

<IfModule mod_rewrite.c>
    RewriteEngine On

    # Forcer HTTPS
    RewriteCond %{HTTPS} !=on
    RewriteRule ^ https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301]
</IfModule>

Le flag R=301 indique une redirection permanente (les moteurs transfèrent le jus SEO). L signifie « dernière règle » et évite que d'autres RewriteRule s'appliquent après.

Redirections 301

Deux approches, les deux fonctionnent :

Avec Redirect (simple)

# URL exacte vers URL exacte
Redirect 301 /ancienne-page.html https://exemple.fr/nouvelle-page

# Dossier entier
Redirect 301 /blog-old/ https://exemple.fr/blog/

Avec RewriteRule (pattern matching)

<IfModule mod_rewrite.c>
    RewriteEngine On

    # www vers sans-www (ou l'inverse)
    RewriteCond %{HTTP_HOST} ^www\.exemple\.fr [NC]
    RewriteRule ^(.*)$ https://exemple.fr/$1 [L,R=301]

    # Toute URL /produit/XXX vers /p/XXX
    RewriteRule ^produit/(.*)$ /p/$1 [L,R=301]
</IfModule>
💡
Tester avec 302 avant de passer en 301
Une 301 est mise en cache agressivement par les navigateurs. Si vous vous êtes trompé, les visiteurs restent bloqués sur la mauvaise redirection pendant des jours. Pendant vos tests, utilisez R=302 (temporaire), validez, puis passez en R=301.

Bloquer l'accès à des fichiers ou dossiers

Un fichier précis

<Files "wp-config.php">
    Require all denied
</Files>

<Files ".env">
    Require all denied
</Files>

Tous les fichiers d'un type

<FilesMatch "\.(sql|log|bak|ini|conf)$">
    Require all denied
</FilesMatch>

Interdire le listing d'un dossier

# À la racine ou dans le dossier concerné
Options -Indexes

Bloquer l'exécution PHP dans uploads/

Une protection classique pour wp-content/uploads/ (placez ce .htaccess dans le dossier uploads) :

<FilesMatch "\.(php|phtml|phps)$">
    Require all denied
</FilesMatch>
Syntaxe Apache 2.4
Sur Apache 2.4 (ce qu'on utilise), la syntaxe officielle est Require all denied / Require all granted. L'ancienne (Deny from all, Order deny,allow) fonctionne encore via mod_access_compat, mais est dépréciée. Préférez la nouvelle.

Protéger un dossier par mot de passe

Créez le fichier de mots de passe avec htpasswd (depuis SSH) :

htpasswd -c /home/user/.htpasswd admin
# Entrez le mot de passe deux fois

Puis dans un .htaccess au niveau du dossier à protéger :

AuthType Basic
AuthName "Zone protégée"
AuthUserFile /home/user/.htpasswd
Require valid-user

Plesk propose aussi l'équivalent graphique : Websites & Domains > Password-Protected Directories.

Compression gzip / deflate

Réduit la taille des réponses HTML, CSS, JS, SVG de 60 à 80 % avant envoi au navigateur :

<IfModule mod_deflate.c>
    AddOutputFilterByType DEFLATE text/html
    AddOutputFilterByType DEFLATE text/css
    AddOutputFilterByType DEFLATE text/plain
    AddOutputFilterByType DEFLATE text/xml
    AddOutputFilterByType DEFLATE application/javascript
    AddOutputFilterByType DEFLATE application/json
    AddOutputFilterByType DEFLATE application/xml
    AddOutputFilterByType DEFLATE image/svg+xml
    AddOutputFilterByType DEFLATE font/ttf
    AddOutputFilterByType DEFLATE font/otf
</IfModule>

Ne compressez pas les formats déjà compressés : JPEG, PNG, WebP, MP4, woff2, ZIP. Le gain est nul et la CPU consommée est perdue.

Cache navigateur (mod_expires)

Dit au navigateur combien de temps il peut réutiliser un fichier sans revenir demander au serveur. Énorme gain de performance sur les visites récurrentes :

<IfModule mod_expires.c>
    ExpiresActive On

    # Par défaut (fallback)
    ExpiresDefault "access plus 1 month"

    # HTML : court, pour propager les mises à jour
    ExpiresByType text/html "access plus 0 seconds"

    # CSS / JS : un an (on les cassera via un query string ou un hash de nom)
    ExpiresByType text/css "access plus 1 year"
    ExpiresByType application/javascript "access plus 1 year"

    # Images : un an
    ExpiresByType image/jpeg "access plus 1 year"
    ExpiresByType image/png "access plus 1 year"
    ExpiresByType image/webp "access plus 1 year"
    ExpiresByType image/svg+xml "access plus 1 year"

    # Fonts : un an
    ExpiresByType font/woff2 "access plus 1 year"
    ExpiresByType font/woff "access plus 1 year"
</IfModule>
💡
Cache long + cache busting
Un cache d'un an est excellent pour la vitesse mais catastrophique si vous modifiez un CSS : les visiteurs ne verront pas la mise à jour. La solution : servir les assets avec un nom versionné (style.css?v=3 ou style-a1b2c3.css). Changez le numéro, le navigateur recharge.

Protection hotlinking

Empêche d'autres sites d'afficher vos images en consommant votre bande passante :

<IfModule mod_rewrite.c>
    RewriteEngine On

    # Autoriser si pas de referer (accès direct) ou referer interne
    RewriteCond %{HTTP_REFERER} !^$
    RewriteCond %{HTTP_REFERER} !^https?://(www\.)?exemple\.fr [NC]

    # Autoriser Google Images, Bing, etc. (optionnel)
    RewriteCond %{HTTP_REFERER} !^https?://(www\.)?(google|bing|duckduckgo)\. [NC]

    # Bloquer tout le reste sur les images
    RewriteRule \.(jpe?g|png|gif|webp|svg)$ - [F,NC,L]
</IfModule>

Le flag F renvoie un 403 Forbidden. Remplacez exemple.fr par votre domaine.

Debug : tester avec curl

Pour vérifier qu'une redirection ou un header fonctionne sans passer par le navigateur (qui cache tout) :

# Voir les headers de réponse (suivre ou pas la redirection)
curl -I https://exemple.fr/ancienne-page

# Suivre toute la chaîne de redirections
curl -IL https://exemple.fr

# Forcer un User-Agent (certaines règles filtrent par UA)
curl -I -A "Mozilla/5.0" https://exemple.fr

# Vérifier que gzip est bien activé
curl -I -H "Accept-Encoding: gzip" https://exemple.fr | grep -i content-encoding

Pièges à connaître

Boucles de redirection

Classique : vous forcez HTTPS, et un autre outil (plugin WordPress, config Plesk) force déjà HTTPS. Résultat : le navigateur boucle et affiche ERR_TOO_MANY_REDIRECTS. Dans ce cas, retirez une des deux règles.

⚠️
Attention au reverse proxy
Sur nos Plesk, Nginx sert de reverse proxy devant Apache. La variable %{HTTPS} peut renvoyer off côté Apache même si l'utilisateur est en HTTPS (Nginx a déjà terminé le TLS). Préférez tester via le header X-Forwarded-Proto :
RewriteCond %{HTTP:X-Forwarded-Proto} !=https
RewriteRule ^ https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301]

Ordre des règles

Les règles sont évaluées dans l'ordre du fichier. Une règle [L] qui matche coupe tout ce qui suit. Mettez vos règles les plus générales en bas, les plus spécifiques en haut.

Erreur 500 après modification

Presque toujours une faute de frappe ou un module Apache non chargé. Pour diagnostiquer :

  • Commentez (avec #) la dernière règle ajoutée. Si ça repart, vous tenez le coupable.
  • Consultez les logs Apache depuis Plesk : Websites & Domains > Logs puis filtre Error Log.
  • Vérifiez que chaque bloc <IfModule>, <Files>, <FilesMatch> est bien fermé.
🔥
Toujours garder une copie
Avant toute modification, copiez votre .htaccess en .htaccess.bak. Une règle mal écrite peut rendre le site inaccessible. Avec la sauvegarde, vous restaurez en deux secondes via SFTP.

Module manquant ?

Sur nos infrastructures, les modules Apache standards sont chargés : mod_rewrite, mod_expires, mod_deflate, mod_headers, mod_mime. Si vous avez besoin d'un module plus exotique (mod_pagespeed, mod_security avec règles custom, etc.), ouvrez un ticket Datacampus pour qu'on valide l'installation côté serveur.

Pour aller plus loin

Besoin d'aide ?

Cette documentation ne couvre pas votre cas ? Notre support humain est là.