Nginx : installation et configuration complète
Nginx sert des millions de sites. Voici comment l'installer, configurer des virtual hosts, mettre en place un reverse proxy et activer HTTPS en moins d'une heure.
La première fois que j'ai configuré Nginx, j'ai passé deux heures à chercher pourquoi mon site ne répondait pas. La réponse : un fichier de config avec une typo dans le chemin, et le service Nginx qui continuait à servir la config précédente sans se plaindre.
Nginx est un serveur web, un reverse proxy et un load balancer. Il peut servir des fichiers statiques à 100 000 requêtes par seconde sur un petit VPS, ou distribuer le trafic entre dix serveurs d'application. Ce guide couvre le cas le plus courant : installer Nginx, configurer un domaine, et le faire pointer vers une application.
Installation
# Ubuntu / Debian
sudo apt update && sudo apt install nginx -y
sudo systemctl enable --now nginx
# CentOS / RHEL / Fedora
sudo dnf install nginx -y
sudo systemctl enable --now nginx
# Vérification
nginx -v
# nginx version: nginx/1.24.0
curl http://localhost
# Doit retourner la page de bienvenue NginxNginx est actif. La première chose à faire : ouvrir les ports HTTP et HTTPS dans le firewall. UFW gère ça en deux commandes :
sudo ufw allow 'Nginx Full' # Ouvre 80 et 443
sudo ufw statusStructure des fichiers de configuration
/etc/nginx/
├── nginx.conf ← config principale
├── sites-available/ ← configs de sites (désactivées par défaut)
│ └── monsite.conf
├── sites-enabled/ ← symlinks vers sites-available/
│ └── monsite.conf → ../sites-available/monsite.conf
├── conf.d/ ← configs supplémentaires (chargées automatiquement)
└── snippets/ ← fragments réutilisables (SSL, etc.)La convention Ubuntu : écrire dans sites-available/, activer avec un symlink dans sites-enabled/. Sur Red Hat, tout va dans conf.d/.
# Tester la config avant de recharger
sudo nginx -t
# nginx: configuration file /etc/nginx/nginx.conf test is successful
# Recharger sans coupure
sudo systemctl reload nginx
# Voir les logs en temps réel
sudo tail -f /var/log/nginx/error.log
sudo tail -f /var/log/nginx/access.logServer blocks : servir un site statique
Un server block est l'équivalent Nginx d'un Virtual Host Apache.
server {
listen 80;
listen [::]:80;
server_name monsite.fr www.monsite.fr;
root /var/www/monsite;
index index.html;
location / {
try_files $uri $uri/ =404;
}
# Logs par site
access_log /var/log/nginx/monsite.access.log;
error_log /var/log/nginx/monsite.error.log;
}# Activer le site
sudo ln -s /etc/nginx/sites-available/monsite.conf /etc/nginx/sites-enabled/
sudo nginx -t && sudo systemctl reload nginxPour créer le dossier racine et y déposer un fichier :
sudo mkdir -p /var/www/monsite
echo "<h1>Ça marche</h1>" | sudo tee /var/www/monsite/index.html
sudo chown -R www-data:www-data /var/www/monsiteReverse proxy : pointer vers une application
Le cas le plus courant : une application Node.js, Python ou Go tourne sur un port local, Nginx reçoit les requêtes HTTPS et les transmet.
server {
listen 80;
server_name app.monsite.fr;
location / {
proxy_pass http://127.0.0.1:3000; # Port de votre app
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection 'upgrade';
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;
proxy_cache_bypass $http_upgrade;
}
}Les headers Upgrade et Connection sont nécessaires pour les WebSockets. X-Forwarded-For transmet l'IP réelle du client à l'application — sans ça, votre app voit uniquement 127.0.0.1 comme IP source.
Le guide complet pour héberger une app Node.js sur VPS couvre PM2 et le déploiement complet autour de ce reverse proxy.
SSL / HTTPS avec Let's Encrypt
Let's Encrypt fournit des certificats SSL gratuits. Certbot automatise l'installation et le renouvellement.
# Installer Certbot
sudo apt install certbot python3-certbot-nginx -y
# Obtenir et installer le certificat
sudo certbot --nginx -d monsite.fr -d www.monsite.fr
# Certbot modifie automatiquement le server block et recharge Nginx
# Test de renouvellement automatique
sudo certbot renew --dry-runAprès Certbot, votre config ressemble à ça :
server {
listen 443 ssl;
server_name monsite.fr www.monsite.fr;
ssl_certificate /etc/letsencrypt/live/monsite.fr/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/monsite.fr/privkey.pem;
include /etc/letsencrypt/options-ssl-nginx.conf;
ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem;
# ... reste de la config
}
server {
listen 80;
server_name monsite.fr www.monsite.fr;
return 301 https://$host$request_uri; # Redirect HTTP → HTTPS
}Le renouvellement automatique est géré par un timer systemd installé par Certbot. Vérification :
systemctl status certbot.timer
# Active: active (waiting) — renouvel 2x par jourCompression Gzip
Activez la compression pour réduire la taille des réponses texte (HTML, CSS, JS, JSON) de 60-80%.
http {
gzip on;
gzip_vary on;
gzip_proxied any;
gzip_comp_level 6;
gzip_min_length 1000;
gzip_types
text/plain
text/css
text/javascript
application/javascript
application/json
application/xml
image/svg+xml;
}# Vérifier la compression
curl -H "Accept-Encoding: gzip" -I https://monsite.fr
# Content-Encoding: gzip ← OKHeaders de sécurité
# Bloquer le chargement dans un iframe (clickjacking)
add_header X-Frame-Options "SAMEORIGIN" always;
# Empêcher le sniffing de MIME type
add_header X-Content-Type-Options "nosniff" always;
# Activer le filtre XSS du navigateur
add_header X-XSS-Protection "1; mode=block" always;
# Forcer HTTPS pendant 1 an
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
# Référer limité
add_header Referrer-Policy "strict-origin-when-cross-origin" always;
# Content Security Policy — à adapter
add_header Content-Security-Policy "default-src 'self'; script-src 'self'; style-src 'self' 'unsafe-inline';" always;include snippets/security-headers.conf;Rate limiting
Nginx peut limiter les requêtes par IP, sans Redis ni middleware.
# Définir une zone de rate limiting
limit_req_zone $binary_remote_addr zone=api:10m rate=10r/s;
limit_req_zone $binary_remote_addr zone=login:10m rate=5r/m;location /api/ {
limit_req zone=api burst=20 nodelay;
limit_req_status 429;
proxy_pass http://127.0.0.1:3000;
}
location /auth/login {
limit_req zone=login burst=3 nodelay;
limit_req_status 429;
proxy_pass http://127.0.0.1:3000;
}burst=20 autorise une rafale de 20 requêtes supplémentaires avant de rejeter. nodelay traite immédiatement les requêtes dans le burst au lieu de les mettre en file.
Cache des fichiers statiques
location ~* \.(js|css|png|jpg|jpeg|gif|ico|svg|woff2)$ {
expires 1y;
add_header Cache-Control "public, immutable";
access_log off;
}immutable indique au navigateur de ne jamais revalidider l'asset tant qu'il n'a pas expiré — idéal pour les fichiers avec hash dans le nom (bundle.abc123.js).
Configuration finale complète
# Redirect HTTP → HTTPS
server {
listen 80;
server_name monsite.fr www.monsite.fr;
return 301 https://$host$request_uri;
}
server {
listen 443 ssl http2;
server_name monsite.fr www.monsite.fr;
# SSL (généré par Certbot)
ssl_certificate /etc/letsencrypt/live/monsite.fr/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/monsite.fr/privkey.pem;
include /etc/letsencrypt/options-ssl-nginx.conf;
# Headers de sécurité
include snippets/security-headers.conf;
# Compression
gzip on;
gzip_types text/plain text/css application/javascript application/json;
# Rate limiting sur l'API
location /api/ {
limit_req zone=api burst=20 nodelay;
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 https;
}
# Assets statiques
location ~* \.(js|css|png|jpg|ico|svg|woff2)$ {
expires 1y;
add_header Cache-Control "public, immutable";
}
# App principale
location / {
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_set_header Host $host;
proxy_set_header X-Forwarded-Proto https;
proxy_cache_bypass $http_upgrade;
}
access_log /var/log/nginx/monsite.access.log;
error_log /var/log/nginx/monsite.error.log;
}Nginx est puissant parce qu'il est composable : chaque directive fait une chose précise et les blocs s'imbriquent logiquement. La commande nginx -t avant chaque rechargement évite 90% des downtime. Configurer SSH correctement sur votre VPS avant d'exposer des services au web est la première étape — une fois Nginx en place, le reste est de l'outillage.
La configuration Nginx a aussi un impact SEO direct : compression Gzip, headers de cache, HTTPS — ces paramètres influencent le LCP et le TTFB qui entrent dans les Core Web Vitals de Google. Guide complet Lighthouse pour mesurer l'impact de ces optimisations.