Mettre en place un nginx reverse proxy est la façon la plus pratique de placer une porte solide devant votre serveur d'application au lieu de l'exposer directement à Internet. Qu'il s'agisse d'une API Node.js, d'un processus PHP-FPM servant Laravel ou d'une interface de panneau de jeu écoutant sur le port 8080, Nginx reçoit les requêtes entrantes, termine le TLS, sert les fichiers statiques et transmet le reste à l'application située derrière. Dans cet article, nous construisons une configuration fonctionnelle de zéro, abordons les pièges courants et ajoutons les réglages fins nécessaires en production, étape par étape.
Que fait exactement un reverse proxy ?
Un proxy classique se trouve côté client et gère le trafic sortant. Un reverse proxy, c'est l'inverse : il se place côté serveur et traite le trafic entrant. Le client ne voit que Nginx ; il ne sait jamais sur quel port, dans quel langage ni en combien d'exemplaires tourne l'application en arrière-plan. Cette abstraction apporte beaucoup :
- Terminaison TLS : la gestion des certificats est centralisée en un seul point, dans Nginx. L'application parle en HTTP simple.
- Un seul port, un seul domaine : vous acceptez tout sur 80 et 443 et routez les différents chemins (
/api,/admin) vers des backends distincts. - Sécurité : le port de l'application reste fermé vers l'extérieur ; il n'est accessible que depuis localhost.
- Performance : les fichiers statiques, la compression gzip/brotli et le cache sont gérés directement par Nginx.
Installation et configuration de base
Sur Debian/Ubuntu, l'installation tient en une ligne :
sudo apt update
sudo apt install nginx
sudo systemctl enable --now nginx
L'approche la plus propre consiste à garder les fichiers de configuration sous /etc/nginx/sites-available/ et à les activer par un lien symbolique dans sites-enabled/. Supposons que votre application tourne sur 127.0.0.1:3000. Le bloc serveur ci-dessous lui transmet toutes les requêtes entrantes :
server {
listen 80;
server_name app.example.com;
location / {
proxy_pass http://127.0.0.1:3000;
proxy_http_version 1.1;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
}
Activez le fichier, testez la configuration et rechargez :
sudo ln -s /etc/nginx/sites-available/app \
/etc/nginx/sites-enabled/
sudo nginx -t
sudo systemctl reload nginx
Pourquoi les en-têtes de proxy sont-ils si importants ?
Les lignes proxy_set_header ci-dessus ne sont pas décoratives. Dès que Nginx s'interpose, l'application backend ne voit plus le vrai client ; elle ne fait face qu'à 127.0.0.1. Si vous ne transmettez pas les bons en-têtes, l'IP de tout le monde apparaît comme localhost dans vos journaux, votre application prend l'HTTPS pour de l'HTTP et tombe dans une boucle de redirection infinie, ou les cookies de session se cassent.
X-Forwarded-Fortransporte la vraie IP du client.X-Forwarded-Protoindique à l'application que la requête était bien en HTTPS ; les cookies sécurisés et la génération d'URL correcte en dépendent.- Préserver l'en-tête
Hostpermet à l'application de voir le bon hôte dans les configurations multi-domaines.
Dans des frameworks comme Laravel, n'oubliez pas de configurer le paramètre trusted proxy pour que ces en-têtes soient pris en compte ; sinon les en-têtes X-Forwarded-* sont ignorés.
HTTPS et terminaison TLS
Le plus grand atout d'un reverse proxy est de centraliser le certificat en un seul endroit. Certbot est l'outil le plus pratique pour obtenir un certificat Let's Encrypt gratuit :
sudo apt install certbot python3-certbot-nginx
sudo certbot --nginx -d app.example.com
Certbot ajoute automatiquement le bloc 443, les chemins de certificats et la redirection de 80 vers 443. Si vous préférez l'écrire manuellement, le squelette ressemble à ceci :
server {
listen 443 ssl;
server_name app.example.com;
ssl_certificate /etc/letsencrypt/live/app.example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/app.example.com/privkey.pem;
location / {
proxy_pass http://127.0.0.1:3000;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-Proto $scheme;
}
}
Comme vous terminez le TLS sur Nginx, le lien vers le backend peut être en HTTP simple ; sur localhost, c'est parfaitement sûr et cela libère l'application de toute gestion de certificats.
WebSocket, délais d'attente et cache
Les applications temps réel (chat, tableaux de bord en direct, console de jeu) utilisent WebSocket. Pour que Nginx puisse faire évoluer la connexion, deux en-têtes sont indispensables :
location /ws {
proxy_pass http://127.0.0.1:3000;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_read_timeout 3600s;
}
Pour les requêtes longues, le proxy_read_timeout de 60 secondes par défaut peut vous tromper ; une génération de rapport lourde est coupée à mi-chemin. Pour le contenu statique, utiliser le cache propre de Nginx ou la directive expires répond à la requête sans jamais atteindre le backend, ce qui soulage l'application.
Répartition de charge et plusieurs backends
Quand une seule instance de l'application ne suffit pas, vous définissez plusieurs processus comme un seul pool avec un bloc upstream :
upstream app_pool {
server 127.0.0.1:3000;
server 127.0.0.1:3001;
}
server {
listen 80;
location / {
proxy_pass http://app_pool;
}
}
Par défaut, Nginx distribue les requêtes à tour de rôle (round-robin) ; avec least_conn il choisit celle qui a le moins de connexions, et avec ip_hash il envoie toujours le même client vers le même backend. C'est aussi la base des déploiements sans interruption (bleu-vert).
Questions fréquentes
Un reverse proxy et un répartiteur de charge, c'est la même chose ?
Pas tout à fait. Tout répartiteur de charge se comporte comme un reverse proxy, mais tout reverse proxy n'a pas à répartir la charge. Nginx peut faire les deux : avec un seul backend, c'est juste un proxy ; avec plusieurs backends et un upstream, il devient un répartiteur de charge.
Comment résoudre une erreur 502 Bad Gateway ?
Un 502 signifie presque toujours que le backend ne tourne pas ou que l'adresse/le port dans proxy_pass est erroné. Vérifiez que l'application écoute réellement avec ss -ltnp et consultez /var/log/nginx/error.log.
Dois-je terminer le TLS au niveau du backend ?
Dans la plupart des configurations, non. Terminer le TLS sur Nginx et parler en HTTP simple via localhost est à la fois plus simple et sûr. Ce n'est que dans les scénarios de conformité stricts, où le trafic interne sur le réseau doit aussi être chiffré, que l'on envisage un TLS de bout en bout.
Vous voulez placer votre infrastructure derrière Nginx ? Nous pouvons concevoir ensemble une configuration de reverse proxy solide, incluant TLS, cache et déploiements sans interruption. Contactez-moi et parlons de votre projet.