Nginx : reverse proxy
Un reverse proxy reçoit les requêtes des visiteurs et les transmet à une application qui écoute sur un port local. Il gère aussi HTTPS, la compression et la sécurité. Les exemples utilisent une application fictive sur 127.0.0.1:3000.
Proxy simple
Section intitulée « Proxy simple »server { listen 80; server_name app.exemple.com;
location / { proxy_pass http://127.0.0.1:3000; 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; }}| En-tête | Rôle |
|---|---|
Host |
Nom d’hôte demandé par le visiteur (sans lui, l’application voit 127.0.0.1:3000) |
X-Real-IP |
Adresse du visiteur |
X-Forwarded-For |
Liste des adresses traversées |
X-Forwarded-Proto |
http ou https (pour que l’application génère les bons liens) |
Pour réutiliser ces lignes, les placer dans un fragment :
sudo tee /etc/nginx/snippets/proxy-headers.conf <<'CONF'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;CONFlocation / { proxy_pass http://127.0.0.1:3000; include snippets/proxy-headers.conf;}La barre oblique finale de proxy_pass
Section intitulée « La barre oblique finale de proxy_pass »| Écriture | Requête /api/utilisateurs transmise comme |
|---|---|
location /api/ { proxy_pass http://127.0.0.1:4000; } |
/api/utilisateurs (le chemin est conservé) |
location /api/ { proxy_pass http://127.0.0.1:4000/; } |
/utilisateurs (le préfixe /api/ est retiré) |
location /api/ { proxy_pass http://127.0.0.1:4000/; # retire /api/ include snippets/proxy-headers.conf;}Avec une adresse seule (sans chemin), le chemin d’origine est conservé ; avec un chemin, même /, la partie du location est remplacée.
WebSockets
Section intitulée « WebSockets »map $http_upgrade $connection_upgrade { default upgrade; '' close;}
server { # … 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 $connection_upgrade; include snippets/proxy-headers.conf; proxy_read_timeout 3600s; # connexions longues }}Le bloc map se place dans le contexte http (par exemple dans un fichier de /etc/nginx/conf.d/).
Événements serveur (SSE) et réponses en flux
Section intitulée « Événements serveur (SSE) et réponses en flux »location /evenements { proxy_pass http://127.0.0.1:3000; proxy_http_version 1.1; proxy_set_header Connection ''; proxy_buffering off; # transmet immédiatement les données proxy_read_timeout 1h;}Délais et taille
Section intitulée « Délais et taille »location / { proxy_pass http://127.0.0.1:3000; proxy_connect_timeout 5s; # établissement de la connexion à l'application proxy_send_timeout 60s; proxy_read_timeout 60s; # attente de la réponse client_max_body_size 20m; # taille maximale des envois (défaut : 1m)}Répartition de charge : upstream
Section intitulée « Répartition de charge : upstream »upstream application { least_conn; # vers le serveur le moins chargé (défaut : tourniquet) server 127.0.0.1:3000 max_fails=3 fail_timeout=30s; server 127.0.0.1:3001 max_fails=3 fail_timeout=30s; server 127.0.0.1:3002 backup; # utilisé seulement si les autres sont en échec keepalive 16; # connexions réutilisées vers l'application}
server { location / { proxy_pass http://application; proxy_http_version 1.1; proxy_set_header Connection ''; # nécessaire pour keepalive include snippets/proxy-headers.conf; }}| Méthode | Comportement |
|---|---|
| (défaut) | Tourniquet (round-robin) |
least_conn |
Serveur ayant le moins de connexions actives |
ip_hash |
Un visiteur reste sur le même serveur (sessions) |
max_fails et fail_timeout retirent temporairement un serveur qui échoue (contrôle de santé passif).
Cache du proxy (facultatif)
Section intitulée « Cache du proxy (facultatif) »# Contexte httpproxy_cache_path /var/cache/nginx/app levels=1:2 keys_zone=app:10m max_size=1g inactive=60m;
server { location /api/public/ { proxy_pass http://127.0.0.1:3000; proxy_cache app; proxy_cache_valid 200 5m; add_header X-Cache-Status $upstream_cache_status always; }}Adresse réelle du visiteur derrière un autre proxy
Section intitulée « Adresse réelle du visiteur derrière un autre proxy »Si Nginx est lui-même derrière un répartiteur de charge ou un CDN :
set_real_ip_from 10.0.0.0/8; # adresses des proxys de confiancereal_ip_header X-Forwarded-For;real_ip_recursive on;curl -I http://app.exemple.com/curl -H "Host: app.exemple.com" http://127.0.0.1/curl -i -H "Upgrade: websocket" -H "Connection: Upgrade" http://127.0.0.1/ws/sudo tail -f /var/log/nginx/error.logDépannage
Section intitulée « Dépannage »| Symptôme | Piste |
|---|---|
502 Bad Gateway |
L’application est arrêtée, mal écoute, ou mauvais port : curl http://127.0.0.1:3000 ; sudo ss -tlnp |
504 Gateway Timeout |
L’application est trop lente : augmenter proxy_read_timeout, ou corriger l’application |
413 Request Entity Too Large |
Augmenter client_max_body_size |
Liens générés en http:// au lieu de https:// |
Transmettre X-Forwarded-Proto et configurer l’application pour le lire |
| WebSocket qui se coupe | Upgrade/Connection, proxy_http_version 1.1, et proxy_read_timeout assez long |
| Chemin transmis incorrect | Barre oblique finale de proxy_pass (voir plus haut) |
connect() failed (13: Permission denied) |
SELinux/AppArmor ou application en écoute sur un autre utilisateur ; vérifier le port et l’adresse |
Pour aller plus loin
Section intitulée « Pour aller plus loin »- Documentation :
ngx_http_proxy_moduleetupstream - Suite : HTTPS et certificats