Un reverse proxy reçoit le trafic public sur les ports 80 et 443 et le transmet à des applications qui n'écoutent qu'en local. Il apporte le HTTPS, plusieurs sites sur une seule IP et un point unique pour les journaux et les limites. Ce guide le met en place sur un VPS Linux Infrawire pour des applications Node.js, Python ou Docker.
📋 Prérequis
- Un VPS Linux (Ubuntu 24.04 / Debian 12 ou AlmaLinux 9 / Rocky 9) avec accès SSH root. L'IP et le mot de passe root sont dans votre espace client.
- Un domaine
example.comdont les enregistrements A/AAAA pointent versVPS_IP. - Une application qui écoute sur un port local, par exemple
127.0.0.1:3000.
📦 Installer Nginx
Bash# Debian / Ubuntu sudo apt update && sudo apt install -y nginx # AlmaLinux / Rocky sudo dnf install -y nginx sudo systemctl enable --now nginx
Sur AlmaLinux/Rocky, SELinux empêche par défaut Nginx de se connecter à des backends. Autorisez-le une fois :
Bashsudo setsebool -P httpd_can_network_connect 1
🚀 Une première application derrière le proxy
Votre application doit écouter sur 127.0.0.1 et non sur 0.0.0.0, afin de n'être joignable que via Nginx. Quel que soit le langage, le schéma est identique : node server.js sur le port 3000, gunicorn -b 127.0.0.1:8000 app:app pour Python, ou un conteneur publié avec docker run -d -p 127.0.0.1:3000:80 IMAGE.
Créez /etc/nginx/sites-available/example.com (sur AlmaLinux/Rocky, utilisez /etc/nginx/conf.d/example.com.conf) :
Nginx1server { 2 listen 80; 3 listen [::]:80; 4 server_name example.com; 5 6 location / { 7 proxy_pass http://127.0.0.1:3000; 8 proxy_http_version 1.1; 9 proxy_set_header Host $host; 10 proxy_set_header X-Real-IP $remote_addr; 11 proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; 12 proxy_set_header X-Forwarded-Proto $scheme; 13 } 14}
Activez-le sous Debian/Ubuntu, puis validez et rechargez :
Bashsudo ln -s /etc/nginx/sites-available/example.com /etc/nginx/sites-enabled/ sudo nginx -t && sudo systemctl reload nginx
Les en-têtes X-Forwarded-* permettent à l'application de connaître l'IP réelle du client et de savoir si le visiteur est en HTTPS. Sans eux, votre application ne voit que 127.0.0.1 et peut générer des liens en http://. Beaucoup de frameworks doivent aussi être configurés pour faire confiance au proxy (par exemple app.set('trust proxy', 1) dans Express).
🔌 Prise en charge des WebSocket
Les WebSocket exigent les en-têtes d'upgrade HTTP. Ajoutez un map au niveau du contexte http (par exemple dans /etc/nginx/conf.d/websocket.conf) :
Nginxmap $http_upgrade $connection_upgrade { default upgrade; '' close; }
Puis, dans le bloc location :
Nginxproxy_set_header Upgrade $http_upgrade; proxy_set_header Connection $connection_upgrade;
⏱️ Timeouts et taille du corps
Les valeurs par défaut sont 60 secondes et 1 Mo. Ajustez-les pour les endpoints lents ou les envois de fichiers :
Nginxproxy_connect_timeout 5s; proxy_read_timeout 120s; proxy_send_timeout 120s; client_max_body_size 50m;
Pour un WebSocket de longue durée, augmentez proxy_read_timeout (par exemple 3600s) ou faites envoyer des pings par l'application.
🔒 HTTPS avec Certbot
Ouvrez d'abord le pare-feu pour les ports 80 et 443, puis :
Bash# Debian / Ubuntu sudo apt install -y certbot python3-certbot-nginx sudo certbot --nginx -d example.com
Sur AlmaLinux/Rocky, installez Certbot avec sudo dnf install -y epel-release puis sudo dnf install -y certbot python3-certbot-nginx. Certbot ajoute le certificat à votre bloc server, propose la redirection HTTP vers HTTPS et installe le renouvellement automatique. Vérifiez-le avec :
Bashsudo certbot renew --dry-run
🗂️ Plusieurs applications sur un VPS
Créez un bloc server par domaine, chacun avec son server_name et son propre port local :
Nginx1server { 2 listen 80; 3 server_name app1.example.com; 4 location / { proxy_pass http://127.0.0.1:3000; } 5} 6 7server { 8 listen 80; 9 server_name app2.example.com; 10 location / { proxy_pass http://127.0.0.1:8000; } 11}
Répétez les en-têtes de proxy dans chaque bloc, puis lancez Certbot avec -d app1.example.com -d app2.example.com. Vous pouvez aussi séparer par chemin (location /api/ { proxy_pass http://127.0.0.1:8000/; }) ; la barre oblique finale retire alors le préfixe.
✅ Tester
Bashcurl -I https://example.com ss -ltnp | grep -E ':(80|443|3000)' sudo tail -f /var/log/nginx/error.log
Le port du backend doit être lié à 127.0.0.1 uniquement, tandis que Nginx écoute sur 80 et 443.
🛠️ Dépannage
502 Bad Gateway. L'application est arrêtée ou sur un autre port. Vérifiez avec ss -ltnp, puis démarrez-la. Sur AlmaLinux/Rocky, un Permission denied dans le journal d'erreurs signifie que le booléen SELinux ci-dessus manque.
504 Gateway Timeout. Le backend met plus de temps que proxy_read_timeout. Augmentez-le ou optimisez l'endpoint.
WebSocket qui se déconnecte ou échoue en 400/426. Les en-têtes Upgrade et Connection manquent, ou proxy_http_version 1.1; est absent.
Mauvaise IP client dans les logs. X-Forwarded-For est envoyé mais votre application ne fait pas confiance au proxy. Activez le réglage de confiance de votre framework.
🎉 Vos applications sont maintenant servies derrière Nginx, en HTTPS, avec des en-têtes propres et de la place pour autant de sites que votre VPS peut en supporter.