Pages d'erreur personnalisées Nginx : Améliorer l'expérience utilisateur
Configurez des pages d'erreur personnalisées Nginx utiles pour les réponses 404, 403 et 50x sans masquer les véritables échecs.
Pages d'erreur personnalisées Nginx : Améliorer l'expérience utilisateur
Les pages d'erreur personnalisées Nginx transforment un échec brut en une prochaine étape claire. Elles ne réparent pas le lien cassé, le fichier manquant ou l'application en amont qui a planté. Elles font quelque chose de plus petit mais toujours précieux : elles disent au visiteur ce qui s'est passé dans un langage simple et l'empêchent de se sentir largué de votre site.
Cela compte lors d'erreurs ordinaires. Quelqu'un suit un ancien lien de documentation et obtient une 404. Un chemin de fichier privé renvoie 403. Votre application redémarre pendant le déploiement et Nginx voit brièvement une 502. Sans page personnalisée, les utilisateurs peuvent voir une réponse serveur par défaut qui semble abrupte ou technique. Avec une bonne page statique, ils savent s'ils doivent chercher, revenir en arrière, réessayer ou attendre.
Les meilleures pages d'erreur sont des outils opérationnels ennuyeux. Elles sont statiques, rapides, accessibles et honnêtes. Elles ne cachent pas les pannes à la surveillance, et elles n'exposent pas de détails internes aux utilisateurs.
Commencez par les erreurs que les gens voient réellement
Vous n'avez pas besoin de concevoir une page pour chaque code d'état HTTP. Commencez par les plus courants.
404 Not Found est la première page à personnaliser. Elle apparaît lorsque l'URL demandée ne correspond pas à un fichier, une route ou un emplacement Nginx qui renvoie du contenu. Les anciens liens, les articles renommés, les pages de documentation supprimées et les URL tapées à la main mènent tous ici.
Une page 404 utile dit quelque chose comme : "Nous n'avons pas trouvé cette page." Ensuite, elle offre un chemin de retour vers la page d'accueil, l'index de documentation, la zone produit ou la page de recherche. Ne blâmez pas l'utilisateur. L'URL peut avoir été erronée bien avant qu'il ne clique dessus.
403 Forbidden est différent. Nginx a compris la demande mais ne la servira pas. Les causes incluent les permissions de fichiers, les règles d'accès, l'affichage du répertoire désactivé, les règles d'autorisation/refus IP ou les exigences d'authentification. Une page 403 doit être calme et courte. Si la ressource est privée, dites-le. Si les utilisateurs peuvent avoir besoin d'accès, orientez-les vers la bonne connexion ou le chemin de support.
Pour les sites soutenus par une application, gérez les erreurs 50x avec soin :
500 Internal Server Errorsignifie généralement que l'application a échoué lors du traitement de la demande.502 Bad Gatewaysignifie souvent que Nginx n'a pas reçu de réponse valide du service en amont.503 Service Unavailableest utile pour la maintenance, la surcharge ou un service délibérément indisponible.504 Gateway Timeoutsignifie que Nginx a attendu trop longtemps la réponse en amont.
Exemple de tableau de bord SaaS : votre processus d'application redémarre pendant le déploiement. Pendant quelques secondes, Nginx ne peut pas se connecter à l'amont et les utilisateurs voient une 502. Une page personnalisée peut dire : "Le tableau de bord est temporairement indisponible. Veuillez actualiser dans une minute." Ce n'est pas parfait, mais c'est plus clair qu'une erreur de passerelle par défaut.
Créez des fichiers d'erreur statiques
Gardez les pages d'erreur en dehors de la chaîne de dépendance de l'application. Si la base de données est en panne, la page 500 doit toujours se charger. Si l'application Node, Python, Ruby ou PHP est défaillante, Nginx doit toujours servir le repli statique.
Une disposition de fichiers simple pourrait être :
/var/www/example.com/public/
index.html
assets/
/var/www/example.com/errors/
404.html
403.html
50x.html
Gardez le HTML léger. Évitez les scripts tiers, les images lourdes, les bundles d'application côté client et tout ce qui appelle le backend cassé. Un petit fichier CSS est acceptable si Nginx peut le servir directement.
Un 404.html minimal pourrait être :
<!doctype html>
<html lang="fr">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Page non trouvée</title>
</head>
<body>
<main>
<h1>Page non trouvée</h1>
<p>La page a peut-être été déplacée, ou le lien est peut-être obsolète.</p>
<p><a href="/">Aller à la page d'accueil</a></p>
</main>
</body>
</html>
Cela suffit. Vous pouvez le styliser pour correspondre à votre site, mais le message et les liens comptent plus que la décoration.
Reliez les pages avec error_page
Dans Nginx, la directive error_page associe un ou plusieurs codes d'état à une URI. Un bloc serveur de base ressemble à ceci :
server {
listen 80;
server_name example.com www.example.com;
root /var/www/example.com/public;
error_page 404 /errors/404.html;
error_page 403 /errors/403.html;
error_page 500 502 503 504 /errors/50x.html;
location /errors/ {
internal;
root /var/www/example.com;
}
location / {
try_files $uri $uri/ =404;
}
}
La résolution de chemin est la partie qui piège les gens. Dans cet exemple, les demandes sous /errors/ utilisent root /var/www/example.com;, donc /errors/404.html correspond à /var/www/example.com/errors/404.html.
La directive internal signifie que les clients externes ne peuvent pas demander /errors/404.html directement comme une URL normale. Nginx peut toujours le servir en interne lors du traitement d'une erreur.
Après avoir modifié la configuration, testez et rechargez :
sudo nginx -t
sudo systemctl reload nginx
Ensuite, testez le comportement :
curl -I http://example.com/definitely-missing-page
curl -s http://example.com/definitely-missing-page | head
Le statut doit toujours être 404, même si le corps est votre HTML convivial. Une erreur courante est de renvoyer accidentellement 200 OK pour une page manquante, ce qui fait croire à la surveillance et aux moteurs de recherche que l'URL manquante est une vraie page.
Pages personnalisées derrière un proxy inverse
Si Nginx sert de proxy vers une application en amont, l'application peut renvoyer ses propres réponses d'erreur. Par défaut, les réponses proxy sont généralement transmises au client. Pour que Nginx intercepte les réponses d'erreur en amont et utilise vos règles error_page, activez proxy_intercept_errors dans le contexte pertinent.
location /app/ {
proxy_pass http://app_backend;
proxy_intercept_errors on;
error_page 502 503 504 /errors/50x.html;
}
La documentation de Nginx décrit proxy_intercept_errors comme s'appliquant aux réponses proxy avec des codes d'état supérieurs ou égaux à 300, qui peuvent ensuite être redirigées vers Nginx pour le traitement error_page. En pratique, ne l'activez pas partout sans réfléchir.
Pour les pages navigateur, intercepter 502 ou 503 est souvent utile. Pour les API JSON, cela peut être erroné. Les clients API attendent généralement un corps d'erreur JSON structuré, pas une page HTML. Vous pouvez avoir besoin d'emplacements séparés :
location /api/ {
proxy_pass http://api_backend;
proxy_intercept_errors off;
}
location /dashboard/ {
proxy_pass http://app_backend;
proxy_intercept_errors on;
error_page 502 503 504 /errors/50x.html;
}
Cette séparation maintient les pages destinées aux humains conviviales tout en préservant les erreurs API lisibles par machine.
Préservez le bon code d'état
Nginx vous permet de modifier le code de réponse avec error_page, mais faites-le seulement lorsque vous le voulez vraiment. Cette syntaxe est valide :
error_page 404 =200 /fallback.html;
Pour la plupart des sites Web, ce serait une mauvaise idée. Une page manquante doit rester une 404. Les moteurs de recherche, les vérifications de disponibilité, les analyses et les utilisateurs bénéficient tous de la vérité.
Il existe des cas légitimes pour changer les codes, comme router certaines erreurs vers un emplacement nommé ou renvoyer une page de maintenance avec 503. Mais en règle générale, préservez le statut d'erreur d'origine.
Pour la maintenance, vous pouvez être explicite :
location / {
return 503;
}
error_page 503 /errors/maintenance.html;
location = /errors/maintenance.html {
root /var/www/example.com;
internal;
}
Si vous utilisez un CDN ou un équilibreur de charge devant Nginx, rappelez-vous qu'il peut avoir son propre comportement de page d'erreur. Décidez quelle couche possède quelles erreurs. Sinon, vous pouvez tester Nginx directement et voir une page, tandis que les utilisateurs derrière le CDN en voient une autre.
Écrivez des pages d'erreur pour les humains
Le contenu doit répondre rapidement à trois questions :
- Que s'est-il passé ?
- Est-ce temporaire ?
- Que puis-je faire ensuite ?
Pour une 404, les prochaines étapes utiles sont la recherche, la page d'accueil, l'index de documentation ou contacter le support si la page manquante devrait exister. Pour une 503, les conseils utiles sont de réessayer plus tard ou de consulter une page de statut. Pour une 403, orientez vers les instructions de connexion ou de demande d'accès si approprié.
Évitez les traces de pile, les noms d'hôte en amont, les chemins de système de fichiers, les versions de paquets, les IP internes, les ID de demande sans explication et les détails d'incident. Un ID de demande peut être utile si le support peut l'utiliser, mais étiquetez-le clairement :
<p>Si vous contactez le support, incluez cet ID de demande : <code>$request_id</code></p>
Pour injecter des variables comme $request_id, vous avez besoin d'un modèle de configuration qui le prend en charge. Les fichiers HTML statiques n'expandent pas les variables Nginx par eux-mêmes. De nombreuses équipes gardent les pages d'erreur publiques statiques et se fient aux journaux pour les ID de demande à la place.
L'accessibilité fait partie de l'utilité. Utilisez un h1 clair, un contraste lisible, des liens normaux et du texte brut. Ne faites pas de la seule action de récupération une petite icône ou un bouton piloté par script.
Testez les pages intentionnellement
N'attendez pas que les utilisateurs trouvent vos pages d'erreur. Testez-les après chaque modification.
Pour 404 :
curl -i https://example.com/no-such-page
Pour 403, créez un emplacement de test contrôlé ou utilisez un fichier de test privé. Ne relâchez pas les permissions de production juste pour déclencher une erreur.
Pour 502 ou 503, testez en staging en pointant un emplacement vers un amont indisponible :
location /broken-upstream-test/ {
proxy_pass http://127.0.0.1:59999;
proxy_intercept_errors on;
error_page 502 503 504 /errors/50x.html;
}
Ensuite, demandez-le et confirmez à la fois le code d'état et le corps :
curl -i https://staging.example.com/broken-upstream-test/
Surveillez également les journaux :
sudo tail -f /var/log/nginx/error.log /var/log/nginx/access.log
Une belle page d'erreur ne doit pas effacer le signal opérationnel. Vos alertes doivent toujours se déclencher lorsque les taux de 50x augmentent.
Les pages d'erreur personnalisées Nginx sont une petite tâche de configuration avec un impact utilisateur réel. Commencez par 404, 403 et les erreurs 50x courantes. Servez des fichiers statiques directement depuis Nginx. Préservez des codes d'état précis. Utilisez proxy_intercept_errors uniquement là où les replis HTML ont du sens. Ensuite, testez les pages de la même manière que vous testez tout autre comportement de production.