Nginx : Configuration, reverse proxy et middleware pour APIs

🏷️ Administration Serveur 📅 12/04/2026 11:00:00 👤 Mezgani Said
Nginx Reverse Proxy Load Balancing Web Server Deployment
Nginx : Configuration, reverse proxy et middleware pour APIs

Maîtriser Nginx comme reverse proxy, load balancer et serveur web. Configuration production pour sécuriser vos APIs et applications.

Introduction à Nginx et ses use cases

Nginx est un serveur web haute performance et léger, écrit en C. Contrairement à Apache, Nginx utilise une architecture asynchrone et non-bloquante, ce qui le rend idéal pour gérer des milliers de connexions simultanées.

À retenir : Nginx = performance, légèreté, asynchrone. Parfait pour reverse proxy, load balancing et APIs modernes.

Use cases principaux :

  • Reverse proxy : afficher vos APIs Node.js, Go, Python derrière Nginx
  • Load balancing : distribuer le trafic entre plusieurs serveurs applicatifs
  • Serveur web statique : servir HTML/CSS/JS ultra-rapide
  • SSL/TLS termination : gérer HTTPS centralement
  • Compression : gzip les réponses pour réduire la bande passante
  • Caching : mettre en cache les réponses pour réduire la charge backend

Installation et configuration de base

Installation (Ubuntu/Debian) :

sudo apt update
sudo apt install nginx

# Démarrer le service
sudo systemctl start nginx
sudo systemctl enable nginx  # Auto start on boot

# Vérifier le statut
sudo systemctl status nginx

Configuration de base :

Le fichier principal est : /etc/nginx/nginx.conf

worker_processes auto;          # Nombre de workers = nombre de CPU
worker_connections 1024;        # Connexions max par worker
keepalive_timeout 65;           # Délai avant fermeture connexion inactif

http {
    include /etc/nginx/mime.types;
    default_type application/octet-stream;

    # Format des logs
    log_format main '$remote_addr - $remote_user [$time_local] '
                    '"$request" $status $body_bytes_sent '
                    '"$http_referer" "$http_user_agent"';

    access_log /var/log/nginx/access.log main;
    error_log /var/log/nginx/error.log warn;

    # Include tous les configs de sites
    include /etc/nginx/conf.d/*.conf;
}
Emplacements importants :
  • /etc/nginx/ : fichiers config
  • /var/www/html : fichiers statiques par défaut
  • /var/log/nginx/ : access/error logs

Recharger la config sans redémarrer :

sudo nginx -t                  # Tester la syntaxe
sudo systemctl reload nginx     # Appliquer les changements

Virtual hosts et Server blocks

Les server blocks dans Nginx (équivalent aux vhosts Apache) permettent d'héberger plusieurs sites sur un même serveur.

Structure recommandée :

/etc/nginx/
├── nginx.conf (config principale)
├── conf.d/
│   ├── app1.conf
│   ├── app2.conf
│   └── ...
└── sites-available/
    ├── app1
    └── app2

Exemple simple - app1.conf :

server {
    listen 80;
    server_name app1.example.com;

    root /var/www/app1;
    index index.html;

    location / {
        try_files $uri $uri/ /index.html;
    }

    # Logs spécifiques au site
    access_log /var/log/nginx/app1_access.log;
    error_log /var/log/nginx/app1_error.log;
}

Exemple avec plusieurs domaines :

server {
    listen 80;
    server_name app.example.com www.app.example.com;
    # Servir sur plusieurs domaines

    location / {
        proxy_pass http://localhost:3000;
    }
}
À retenir : Un server block = un site/domaine. Chaque block écoute sur un port et matching un nom de domaine.

Reverse proxy et load balancing

Reverse proxy simple (1 backend) :

server {
    listen 80;
    server_name api.example.com;

    location / {
        # Rediriger les requêtes vers le backend
        proxy_pass http://localhost:3000;

        # Headers importants pour le backend
        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;

        # Timeouts
        proxy_connect_timeout 60s;
        proxy_send_timeout 60s;
        proxy_read_timeout 60s;
    }
}

Load balancing avec plusieurs backends :

upstream app_backend {
    server 192.168.1.10:3000 weight=5;  # 50% du trafic
    server 192.168.1.11:3000 weight=3;  # 30% du trafic
    server 192.168.1.12:3000 weight=2;  # 20% du trafic
}

server {
    listen 80;
    server_name api.example.com;

    location / {
        proxy_pass http://app_backend;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
    }
}

Stratégies de load balancing :

  • round_robin (défaut) : distribue équitablement
  • least_conn : envoie au serveur avec moins de connexions
  • ip_hash : même IP = même serveur (session persistance)
  • random : aléatoire
upstream app_backend {
    least_conn;  # Utiliser cette stratégie

    server 192.168.1.10:3000;
    server 192.168.1.11:3000;
}
Health checks : Nginx teste automatiquement si les backends répondent. Si un échoue, il le retire du load balancing.

Gestion des certificats SSL/TLS

Installer Let's Encrypt avec Certbot :

sudo apt install certbot python3-certbot-nginx

# Générer un certificat
sudo certbot certonly --nginx -d api.example.com -d www.api.example.com

# Le certificat se trouve à :
# /etc/letsencrypt/live/api.example.com/

Configuration HTTPS :

server {
    listen 443 ssl http2;
    server_name api.example.com;

    # Certificat SSL
    ssl_certificate /etc/letsencrypt/live/api.example.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/api.example.com/privkey.pem;

    # Configuration SSL sécurisée
    ssl_protocols TLSv1.2 TLSv1.3;
    ssl_ciphers HIGH:!aNULL:!MD5;
    ssl_prefer_server_ciphers on;
    ssl_session_cache shared:SSL:10m;
    ssl_session_timeout 10m;

    # HSTS : force HTTPS pendant 1 an
    add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;

    location / {
        proxy_pass http://localhost:3000;
    }
}

# Redirection HTTP vers HTTPS
server {
    listen 80;
    server_name api.example.com;
    return 301 https://$server_name$request_uri;
}

Renouveler automatiquement les certificats :

sudo certbot renew --dry-run  # Test
sudo certbot renew            # Renouveler
À retenir : Let's Encrypt gratuit, valide 90 jours, certbot renouvelle automatiquement.

Headers de sécurité avec Nginx

Headers essentiels pour les APIs :

server {
    listen 443 ssl http2;
    server_name api.example.com;

    # Security Headers
    add_header X-Frame-Options "SAMEORIGIN" always;
    add_header X-Content-Type-Options "nosniff" always;
    add_header X-XSS-Protection "1; mode=block" always;
    add_header Referrer-Policy "strict-origin-when-cross-origin" always;
    add_header Permissions-Policy "geolocation=(), microphone=()" always;

    # Content Security Policy (stricte pour les APIs)
    add_header Content-Security-Policy "default-src 'none'; frame-ancestors 'none'" always;

    location / {
        proxy_pass http://app_backend;
        # Headers pour le backend
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
    }
}

Blocage des requêtes dangereuses :

server {
    listen 80;
    server_name api.example.com;

    # Bloquer les robots malveillants
    if ($http_user_agent ~* (bot|crawler|spider|scraper)) {
        return 403;
    }

    # Bloquer les requêtes sans User-Agent
    if ($http_user_agent = "") {
        return 403;
    }

    location / {
        proxy_pass http://app_backend;
    }
}

Cache et compression

Compression Gzip :

http {
    # Activer la compression
    gzip on;
    gzip_vary on;
    gzip_min_length 1000;
    gzip_types text/plain text/css application/json application/javascript text/xml application/xml;
    gzip_comp_level 6;
    gzip_disable "msie6";
}

Cache pour fichiers statiques :

server {
    listen 80;
    server_name cdn.example.com;

    root /var/www/cdn;

    # Cache les fichiers statiques 30 jours
    location ~* \.(jpg|jpeg|png|gif|ico|css|js|svg|woff|woff2|ttf|eot)$ {
        expires 30d;
        add_header Cache-Control "public, immutable";
    }

    # Ne pas cacher l'HTML
    location ~* \.html$ {
        expires -1;
        add_header Cache-Control "no-cache, no-store, must-revalidate";
    }
}

Cache proxy (microservices) :

http {
    # Zone de cache partagée
    proxy_cache_path /var/cache/nginx levels=1:2 keys_zone=api_cache:10m max_size=1g inactive=60m;
}

server {
    location /api/ {
        proxy_pass http://app_backend;

        # Mettre en cache les GET pendant 10 min
        proxy_cache api_cache;
        proxy_cache_methods GET HEAD;
        proxy_cache_valid 200 302 10m;
        proxy_cache_valid 404 1m;

        # Afficher d'où vient la réponse
        add_header X-Cache-Status $upstream_cache_status;
    }
}
Headers de cache :
  • Cache-Control: public, max-age=3600 : cacheable 1h
  • Cache-Control: no-cache, must-revalidate : valider à chaque fois
  • Expires: Wed, 21 Apr 2026 12:00:00 GMT : date d'expiration

Monitoring et logs

Format des logs personnalisé :

http {
    log_format api_log '$remote_addr - $remote_user [$time_local] '
                       '"$request" $status $body_bytes_sent '
                       '$request_time '
                       '"$http_referer" "$http_user_agent" '
                       'upstream: $upstream_addr '
                       'cache: $upstream_cache_status';

    access_log /var/log/nginx/api_access.log api_log;
}

Analyser les logs en temps réel :

# Requêtes les plus lentes
tail -f /var/log/nginx/access.log | sort -k10 -nr | head

# Codes HTTP les plus fréquents
awk '{print $9}' /var/log/nginx/access.log | sort | uniq -c | sort -nr

# IPs avec le plus de requêtes
awk '{print $1}' /var/log/nginx/access.log | sort | uniq -c | sort -nr | head

# Erreurs (5xx)
grep " 5[0-9][0-9] " /var/log/nginx/access.log | tail -20

Stats Nginx en direct :

server {
    listen 8080;
    server_name localhost;

    location /nginx_status {
        stub_status on;
        access_log off;
        allow 127.0.0.1;
        deny all;
    }
}

# Accéder aux stats
curl http://localhost:8080/nginx_status
À retenir : Les logs de Nginx sont votre meilleur ami pour débugger et optimiser. Gardez les anciens logs compressés : gzip /var/log/nginx/*.log

Bonnes pratiques production

1. Limite le nombre de workers et connexions :

worker_processes auto;           # = nombre CPU
worker_rlimit_nofile 65535;      # Fichiers ouverts max
events {
    worker_connections 4096;     # 2000-4000 en prod
}

2. Désactiver les infos de version :

http {
    server_tokens off;  # Cache le numéro de version Nginx
}

3. Timeouts appropriés :

http {
    client_body_timeout 10s;
    client_header_timeout 10s;
    keepalive_timeout 5s 5s;
    send_timeout 10s;
}

4. Limiter la taille des uploads :

http {
    client_max_body_size 10m;  # Max 10 MB par requête
}

5. Monitoring actif et alertes :

# Vérifier que Nginx tourne
ps aux | grep nginx

# Utilité CPU/Mémoire
top -p $(pgrep -d',' nginx)

# Nombre de connexions actives
netstat -tupan | grep ESTABLISHED | wc -l

6. Configuration par environnement :

/etc/nginx/
├── nginx.conf
├── conf.d/
│   ├── common.conf       # Commun (dev + prod)
│   ├── dev.conf          # Dev (permissif)
│   └── prod.conf         # Prod (strict)
└── snippets/
    ├── security.conf
    ├── cache.conf
    └── ssl.conf

7. Tester avant de redéployer :

sudo nginx -t              # Valider la config
sudo nginx -s reload        # Recharger proprement
sudo tail -f /var/log/nginx/error.log  # Vérifier pas d'erreur
À retenir : Nginx est simple à configurer mais puissant. La clé = tests fréquents, logs clairs, monitoring actif.