Project Oxygen & Ideo-LabIDEO LAB Dashboard 2026

🚀 Nginx – Reverse Proxy, DĂ©ploiement Django & SĂ©curitĂ©

Guide complet IDEO‑Lab : Serveur web, reverse proxy (Gunicorn), SSL & directives.

1.1 Facile

Vue d'ensemble

Serveur web, Reverse Proxy, asynchrone.

Reverse Proxy Serveur Web
1.2 Facile

Architecture

Event-driven, non-bloquant, Master/Worker.

Event-driven C10k
1.3 Facile

Installation (Linux)

apt (Debian/Ubuntu) & dnf (RHEL/Rocky).

apt dnf
1.4 Moyen

Structure Fichiers

nginx.conf, sites-available vs conf.d.

nginx.conf sites-available
1.5 Facile

Commandes (CLI)

nginx -t, systemctl reload/restart.

nginx -t reload
2.1 Moyen

Contextes (http, server)

Hiérarchie http, server, location.

http {} server {}
2.2 Avancé

Matching location

Priorité : =, ^~, ~, / (Préfixe).

location Regex (~)
2.3 Moyen

Directives (root vs alias)

root (ajoute path), alias (remplace path), try_files.

root alias try_files
2.4 Moyen

Directives Proxy (Gunicorn)

proxy_pass, proxy_set_header, proxy_params.

proxy_pass proxy_set_header
3.1 Moyen

Gunicorn & Systemd

Socket UNIX vs Port TCP, gunicorn.service.

Gunicorn Socket systemd
3.2 Moyen

Config Django (ComplĂšte)

Fichier sites-available complet (static, media, proxy).

Django static media
3.3 Moyen

HTTPS (SSL/Certbot)

certbot --nginx, listen 443, HSTS.

HTTPS Certbot SSL
4.1 Avancé

Load Balancing (upstream)

upstream, least_conn, ip_hash.

upstream Load Balancing
4.2 Avancé

Caching (proxy_cache)

proxy_cache_path, proxy_cache, proxy_cache_valid.

proxy_cache Performance
4.3 Moyen

Sécurité (Headers & Limits)

HSTS, X-Frame-Options, limit_req_zone.

add_header Rate Limit
4.4 Moyen

Debug: Logs (502, 403)

error.log, access.log, 502 (Gunicorn down), 403 (Perms).

502 Bad Gateway 403 Forbidden
5.1 Facile

Cheat-sheet Nginx

Commandes CLI & Directives clés.

cheat nginx -t
1.1 Vue d'ensemble : Le "MaĂźtre d'HĂŽtel" du Web
Nginx (Engine-X)

Nginx est un serveur web haute performance, open-source. Il est connu pour sa stabilité, sa configuration simple, et sa **trÚs faible consommation de ressources**.

Il domine le web moderne et peut agir comme :

  • Serveur Web : Servir des fichiers statiques (HTML, CSS, JS, images).
  • Reverse Proxy (Proxy Inverse) : Le cas d'usage le plus courant. Recevoir les requĂȘtes et les transmettre Ă  un autre serveur (ex: Gunicorn, Node.js, Apache).
  • Load Balancer (RĂ©partiteur de charge) : RĂ©partir le trafic entre plusieurs serveurs d'application.
  • Cache HTTP : Mettre en cache les rĂ©ponses pour accĂ©lĂ©rer le site.
Nginx vs. Apache (ModĂšle de connexion)
CritĂšreNginxApache (worker/prefork)
ArchitectureAsynchrone (Event-Loop)Synchrone (Processus/Thread par requĂȘte)
Connexions1 worker gĂšre 1000s de connexions.1 worker gĂšre 1 connexion Ă  la fois.
RAMTrĂšs faible et prĂ©visible.ÉlevĂ©e (augmente avec les connexions).
Fichiers statiquesExtrĂȘmement rapide.Rapide, mais moins que Nginx.
ConfigLogique (.conf).Complexe (.htaccess, modules).
Analogie (Déploiement Django)

Pensez à votre déploiement comme à un restaurant de luxe :

  • Django (Le Chef) : S'occupe de la logique compliquĂ©e (prĂ©parer les plats, parler Ă  la BDD). Ne parle pas aux clients.
  • Gunicorn (Le GĂ©rant de Cuisine) : GĂšre les "Chefs" (processus Django), s'assure qu'ils travaillent, et les redĂ©marre s'ils Ă©chouent. Parle uniquement au MaĂźtre d'HĂŽtel.
  • Nginx (Le MaĂźtre d'HĂŽtel) : Se tient Ă  l'entrĂ©e (Port 80/443). Il accueille le client, gĂšre le vestiaire (SSL), sert les boissons (fichiers statiques), et transmet la commande de plat (requĂȘte dynamique) Ă  la cuisine (Gunicorn).
1.2 Architecture (Event-driven)
ModĂšle Master / Worker

Nginx utilise un processus Master (lancé en tant que root pour se lier aux ports 80/443) qui lit la configuration et lance plusieurs processus Worker (non-privilégiés, ex: www-data).

ModĂšle Asynchrone (Event-driven)

Chaque Worker est mono-thread et gÚre une boucle d'événements (event loop), un peu comme Node.js. Il peut gérer des milliers de connexions simultanément de maniÚre non-bloquante.

Schéma (Worker Nginx)
RequĂȘte 1 (Client A) ->|
RequĂȘte 2 (Client B) ->|  +----------------+
RequĂȘte 3 (Client C) ->|  | Worker (1 CPU) |
... (1000s)          ->|  | (Event Loop)   |
                        +----------------+
                             | | |
                             | | +-> (Lit Fichier C, non-bloquant)
                             | +---> (Attend Proxy B, non-bloquant)
                             +-----> (Écrit Fichier A, non-bloquant)
1.3 Installation (Linux)
Ubuntu / Debian
sudo apt update
sudo apt install -y nginx
RHEL / Rocky / AlmaLinux

Nginx est dans le dépÎt EPEL (Extra Packages for Enterprise Linux).

# 1. Installer EPEL
sudo dnf install -y epel-release

# 2. Installer Nginx
sudo dnf install -y nginx
Post-Installation (systemd & Firewall)
# Démarrer et activer
sudo systemctl enable --now nginx

# Vérifier le statut
sudo systemctl status nginx

# --- Firewall (UFW - Ubuntu) ---
sudo ufw allow 'Nginx Full' # (Port 80 & 443)
sudo ufw enable

# --- Firewall (firewalld - RHEL) ---
sudo firewall-cmd --add-service=http --permanent
sudo firewall-cmd --add-service=https --permanent
sudo firewall-cmd --reload
1.4 Structure des Fichiers de Configuration
Structure Debian (sites-available)

Cette structure est la plus propre pour gérer plusieurs sites (Virtual Hosts).

/etc/nginx/
├── nginx.conf              (Fichier global, charge http { ... })
│
├── sites-available/        (Dossier: Tous vos fichiers de config)
│   ├── default
│   └── django_projet
│
└── sites-enabled/          (Dossier: Configs activĂ©es)
    └── django_projet       (Lien symbolique vers ../sites-available/)
Flux de travail (Activation d'un site)
# 1. Créer le fichier
sudo nano /etc/nginx/sites-available/django_projet

# 2. Créer le lien symbolique
sudo ln -s /etc/nginx/sites-available/django_projet /etc/nginx/sites-enabled/

# 3. (Désactiver le 'default' s'il existe)
sudo rm /etc/nginx/sites-enabled/default

# 4. Tester & Recharger
sudo nginx -t
sudo systemctl reload nginx
Structure RHEL (conf.d)

RHEL/Rocky utilise une structure plus simple. nginx.conf charge tous les fichiers .conf dans /etc/nginx/conf.d/.

/etc/nginx/
├── nginx.conf              (Fichier global, charge conf.d)
│
└── conf.d/
    ├── django_projet.conf
    └── autre_site.conf

Pour désactiver un site, il faut renommer le fichier (ex: django_projet.conf.disabled) et recharger Nginx.

1.5 Commandes (CLI) : reload vs restart
nginx -t (Tester)

La commande la plus importante. Ne *jamais* recharger Nginx sans tester la configuration d'abord.

nginx -t (Test) va parser tous vos fichiers (nginx.conf, sites-enabled/*) et vérifier les erreurs de syntaxe (ex: } manquant, directive inconnue).

$ sudo nginx -t
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful
reload (Gracieux) vs restart (Coupure)
CommandeActionUsage
sudo systemctl reload nginx(HUP) Charge la nouvelle config, dĂ©marre de nouveaux workers, et arrĂȘte gracieusement les anciens. ZĂ©ro downtime.99% du temps (changer un server).
sudo systemctl restart nginx(Stop/Start) Tue le processus master. Provoque un downtime.Rare. (Changer nginx.conf global, user, ports).
2.1 Contextes : http, server, location

La configuration Nginx est hiérarchique. Les directives sont héritées (Parent -> Enfant).

# (Contexte "main", implicite)
events {
    # Contexte 'events'
    worker_connections 1024;
}

http {
    # Contexte 'http' (s'applique Ă  tous les sites)
    gzip on;
    include /etc/nginx/mime.types;
    
    upstream mon_pool {
        # Contexte 'upstream'
        server 127.0.0.1:8000;
    }
    
    server {
        # Contexte 'server' (un site web)
        listen 80;
        server_name example.com;
        
        location / {
            # Contexte 'location' (une route)
            proxy_pass http://mon_pool;
        }
        
        location /static/ {
            # Un autre 'location'
            root /var/www/static;
        }
    }
}
2.2 Ordre de Priorité du bloc location (Crucial)

Comprendre comment Nginx choisit un bloc location est essentiel. C'est testé dans cet ordre :

PrioritéModificateurDescriptionExemple
1 (Max)=Match Exact. Si ça correspond, Nginx s'arrĂȘte ici.location = /login
2^~Match PrĂ©fixe (Long). Si ça correspond, Nginx s'arrĂȘte (ne teste pas les Regex).location ^~ /static/
3~ ou ~*Regex (~ = sensible casse, ~* = insensible). Testés dans l'ordre du fichier.location ~* \.(jpg|png)$
4 (Min)(Aucun)Match Préfixe (le plus long gagne).location /
Exemple (PiĂšge pour Django)
# RequĂȘte: /static/css/style.css

server {
    # ...
    
    # 1. Correspond ? Non.
    location = / { ... }
    
    # 2. Correspond (Préfixe) ? Oui. Nginx le mémorise.
    location /static/ {
        alias /var/www/static_root/;
    }
    
    # 3. Correspond (Préfixe) ? Oui, mais /static/ est plus long.
    location / {
        proxy_pass http://gunicorn_socket;
    }
}
# Résultat: Le bloc '/static/' est utilisé. (Correct)
2.3 Directives : root, alias, try_files

Objectif : Servir /static/css/style.css depuis le dossier /var/www/projet/static_root/css/style.css (aprĂšs collectstatic).

root (Mauvais pour /static/)

root **ajoute** le path de la location au chemin.

location /static/ {
    root /var/www/projet/static_root;
}
# RequĂȘte: /static/css/style.css
# Nginx cherche: root + location + URI
# /var/www/projet/static_root + /static + /css/style.css
# Résultat: /var/www/projet/static_root/static/css/style.css (404 Not Found)
alias (Correct pour /static/)

alias **remplace** le path de la location par le chemin.

location /static/ {
    alias /var/www/projet/static_root/; # (Le '/' final est important)
}
# RequĂȘte: /static/css/style.css
# Nginx remplace '/static/' par l'alias
# Résultat: /var/www/projet/static_root/css/style.css (200 OK)
try_files (Le Front-Controller)

Utilisé par les frameworks JS (React, Vue, Angular) ou les CMS (WordPress). Il essaie de trouver un fichier/dossier, et s'il échoue, il renvoie vers index.html ou index.php.

Exemple (React/Angular)
location / {
    root /var/www/react-app/dist;
    
    # 1. Cherche le fichier exact (ex: /logo.png)
    # 2. Cherche le dossier (ex: /dossier/)
    # 3. Si échec, renvoie vers /index.html (le routeur React)
    try_files $uri $uri/ /index.html;
}
Exemple (PHP/WordPress)
location / {
    try_files $uri $uri/ /index.php?$query_string;
}
2.4 Directives Proxy (proxy_pass)
proxy_pass

La directive proxy_pass est le cƓur du reverse proxy. Elle dit Ă  Nginx : "ArrĂȘte de chercher un fichier, et passe cette requĂȘte Ă  ce serveur backend (upstream)".

C'est la directive utilisĂ©e pour toutes les requĂȘtes dynamiques (Django, Node.js, FastAPI, etc.).

Les Headers Essentiels (proxy_params)

Quand Nginx transfĂšre la requĂȘte Ă  Gunicorn, Gunicorn ne voit que Nginx (127.0.0.1). Il ne voit ni le vrai client (80.1.2.3), ni le vrai nom d'hĂŽte (ideolab.com).

On doit recopier ces en-tĂȘtes (headers) pour Django (ALLOWED_HOSTS, logs, etc.).

location / {
    # 1. TransfĂ©rer la requĂȘte
    proxy_pass http://unix:/run/gunicorn.sock;
    
    # 2. Recopier les headers
    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;
}
HeaderVariable NginxInfo transmise Ă  Django
Host$hostLe nom d'hĂŽte (ex: ideolab.com).
X-Real-IP$remote_addrL'IP réelle du client (80.1.2.3).
X-Forwarded-For$proxy_add_x...Liste des IPs (si plusieurs proxys).
X-Forwarded-Proto$schemehttp ou https. (Important pour SECURE_PROXY_SSL_HEADER).
3.1 Serveur WSGI (Gunicorn) & Systemd
Serveur WSGI (Web Server Gateway Interface)

Le manage.py runserver de Django est un serveur de **développement**. Il est lent, mono-thread, et non sécurisé.

En production, Nginx (client) ne sait pas parler Ă  Django (Python). On utilise un **serveur WSGI** (comme Gunicorn) pour faire le lien.

(RequĂȘte) -> Nginx -> (Socket) -> Gunicorn -> (WSGI) -> Django
Socket (UNIX) vs TCP (Réseau)

Il y a deux façons de faire communiquer Nginx et Gunicorn (s'ils sont sur la *mĂȘme* machine) :

Socket TCP (Port)

Facile à débugger, mais léger overhead réseau.

# Gunicorn (écoute sur port 8000)
gunicorn --bind 127.0.0.1:8000 ...

# Nginx
proxy_pass http://127.0.0.1:8000;
Socket UNIX (Fichier)

Recommandé en production. Plus rapide (pas d'overhead TCP/IP), et plus sécurisé (permissions de fichier).

# Gunicorn (crée un fichier .sock)
gunicorn --bind unix:/run/gunicorn.sock ...

# Nginx
proxy_pass http://unix:/run/gunicorn.sock;
Service systemd (gunicorn.service)

Créez /etc/systemd/system/gunicorn.service :

[Unit]
Description=Gunicorn daemon for Django Project
After=network.target

[Service]
# Utilisateur/Groupe (doit exister)
User=ideo_user
Group=www-data
# Dossier du 'manage.py'
WorkingDirectory=/home/ideo_user/mon_projet
# Commande (chemin complet venv + socket dans /run)
ExecStart=/home/ideo_user/mon_projet/.venv/bin/gunicorn \
    --access-logfile - \
    --workers 3 \
    --bind unix:/run/gunicorn.sock \
    mon_projet.wsgi:application
Restart=always

[Install]
WantedBy=multi-user.target

Note : Le Group=www-data permet à Nginx (qui tourne en www-data) de lire/écrire sur le socket.

3.2 Configuration Nginx (Django ComplĂšte)

Voici le fichier /etc/nginx/sites-available/django_projet complet, qui gÚre les statiques, les médias, et le proxy vers Gunicorn.

server {
    listen 80;
    server_name ideolab.com www.ideolab.com;
    
    # Taille max des uploads (ex: 50MB)
    client_max_body_size 50M;

    # --- Section Statique (STATIC_ROOT) ---
    # (AprĂšs 'collectstatic')
    location /static/ {
        # 'alias' est la clé (voir 2.3)
        alias /home/ideo_user/mon_projet/static_root/;
        expires 1y;
        access_log off;
        add_header Cache-Control "public, immutable";
    }

    # --- Section Média (MEDIA_ROOT) ---
    location /media/ {
        alias /home/ideo_user/mon_projet/media_root/;
        expires 7d;
        access_log off;
    }

    # --- Section Principale (Django/Gunicorn) ---
    location / {
        # Inclure les headers (Host, X-Forwarded-For...)
        include /etc/nginx/proxy_params;
        
        # Passer au socket Gunicorn
        proxy_pass http://unix:/run/gunicorn.sock;
    }
    
    # (Optionnel) Bloquer l'accÚs aux fichiers cachés
    location ~ /\. {
        deny all;
    }
}
3.3 HTTPS (SSL/TLS avec Certbot)
Certbot (Let's Encrypt)

Certbot est l'outil (gratuit) qui gĂšre l'obtention et le renouvellement des certificats SSL/TLS.

Installation (Ubuntu)
sudo apt install certbot python3-certbot-nginx
Installation (RHEL/Rocky)
sudo dnf install certbot python3-certbot-nginx
Lancement

Le plugin Nginx va lire vos fichiers sites-enabled, trouver vos server_name, et vous demander pour lesquels activer HTTPS.

# (Assurez-vous que votre DNS pointe vers le serveur)
sudo certbot --nginx
# ... (Suivre les instructions) ...
# (Choisir 'Redirect' pour forcer HTTP -> HTTPS)
Config (AprĂšs certbot)

Certbot va modifier votre fichier (ex: /etc/nginx/sites-available/django_projet) pour vous.

server {
    server_name ideolab.com www.ideolab.com;
    
    # (Vos locations /static, /media, / restent identiques)
    location /static/ { ... }
    location /media/ { ... }
    location / { ... }

    # --- BLOC AJOUTÉ PAR CERTBOT ---
    listen 443 ssl; # managed by Certbot
    ssl_certificate /etc/letsencrypt/live/ideolab.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/ideolab.com/privkey.pem;
    include /etc/letsencrypt/options-ssl-nginx.conf;
    ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem;
    # --- FIN BLOC CERTBOT ---
}

# (Certbot ajoute ce bloc pour la redirection HTTP->HTTPS)
server {
    if ($host = www.ideolab.com) {
        return 301 https://$host$request_uri;
    }
    if ($host = ideolab.com) {
        return 301 https://$host$request_uri;
    }

    listen 80;
    server_name ideolab.com www.ideolab.com;
    return 404; # managed by Certbot
}
4.1 Load Balancing (Upstream)
upstream

Le bloc upstream (dĂ©fini dans le contexte http) crĂ©e un "pool" de serveurs backend (ex: plusieurs serveurs Gunicorn, sur la mĂȘme ou diffĂ©rentes machines).

Exemple de configuration
# (Dans nginx.conf ou /etc/nginx/conf.d/upstream.conf)
http {
    # 1. Définir le pool de serveurs
    upstream django_backend_pool {
        server 10.0.0.1:8000;
        server 10.0.0.2:8000;
        server 10.0.0.3:8000 backup; # (N'est utilisé que si 1&2 tombent)
    }

    server {
        listen 80;
        server_name ideolab.com;
        
        location / {
            # 2. Passer au pool (au lieu d'une IP)
            proxy_pass http://django_backend_pool;
            include proxy_params;
        }
    }
}
Méthodes de Load Balancing

Définit *comment* Nginx choisit un serveur dans le pool.

MéthodeDescriptionUsage
(Aucune)Round Robin (défaut). Tour à tour (1, 2, 1, 2...).Usage général.
least_connEnvoie Ă  celui qui a le moins de connexions actives.Connexions longues.
ip_hashGarantit que la mĂȘme IP client va toujours sur le mĂȘme serveur.Sessions "Sticky" (si Gunicorn ne partage pas les sessions).
upstream django_backend_pool {
    ip_hash;
    server 10.0.0.1:8000;
    server 10.0.0.2:8000;
}
4.2 Caching (proxy_cache)
Cache des réponses proxy

Nginx peut mettre en cache (stocker temporairement) les réponses de Gunicorn/Django (ex: une page API ou une page d'accueil) pour ne pas redemander à Django à chaque fois.

1. Définir la zone (dans http)

À mettre dans nginx.conf, dans le bloc http.

# proxy_cache_path /chemin [niveaux] keys_zone=NOM:TAILLE inactive=...

proxy_cache_path /var/cache/nginx/django_cache
                 levels=1:2
                 keys_zone=DJANGO_CACHE:10m
                 max_size=1g
                 inactive=60m;
2. Utiliser le cache (dans server / location)
server {
    ...
    location /api/v1/public_data/ {
        # 1. Utiliser cette zone de cache
        proxy_cache DJANGO_CACHE;
        
        # 2. Temps de validité (200/302 = 10 min)
        proxy_cache_valid 200 302 10m;
        proxy_cache_valid 404 1m;
        
        # 3. Clé de cache (ignorer les query params)
        proxy_cache_key "$scheme$request_method$host$request_uri";
        
        # 4. Transmettre
        proxy_pass http://127.0.0.1:8000;
        include proxy_params;
    }
}
4.3 Sécurité (Headers & Rate Limiting)
Headers de Sécurité (add_header)

Ajoute des en-tĂȘtes HTTP pour "durcir" le client (navigateur).

server {
    ...
    # (Doit ĂȘtre dans le bloc 'server' ou 'location')
    
    # HSTS (Force HTTPS)
    add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
    
    # EmpĂȘche le 'MIME-sniffing'
    add_header X-Content-Type-Options "nosniff" always;
    
    # Anti-Clickjacking
    add_header X-Frame-Options "SAMEORIGIN" always;
    
    # Filtre XSS
    add_header X-XSS-Protection "1; mode=block" always;
}
Rate Limiting (Anti-DDoS/Bruteforce)

Limiter le nombre de requĂȘtes par IP.

1. Définir la zone (dans http)
# (nginx.conf)
# $binary_remote_addr = IP client
# zone=NOM:TAILLE rate=TAUX
limit_req_zone $binary_remote_addr zone=api_limit:10m rate=10r/s;
# (10 requĂȘtes / seconde par IP)
2. Appliquer la zone (dans location)
location /api/login {
    limit_req zone=api_limit burst=20 nodelay;
    
    proxy_pass ...;
}
4.4 Debug: Logs (502, 403, 404)

Quand ça ne marche pas, Nginx vous dit pourquoi. tail -f /var/log/nginx/error.log est votre meilleur ami.

Erreur HTTPMessage error.log (Exemple)Cause probable (Django/Gunicorn)Solution
502 Bad Gatewayconnect() to unix:/run/gunicorn.sock failed (2: No such file or directory)Gunicorn n'est pas démarré, ou le .sock est au mauvais endroit.sudo systemctl start gunicorn. Vérifiez les chemins.
502 Bad Gatewayconnect() to unix:/run/gunicorn.sock failed (13: Permission denied)Nginx (user www-data) n'a pas les droits R/W sur le socket.sudo chown www-data:www-data /run/gunicorn.sock (ou Group=www-data dans gunicorn.service).
403 Forbidden (Statique)(13: Permission denied) while opening file "/var/www/static_root/..."Nginx (user www-data) n'a pas les droits r-x sur le dossier.sudo chmod -R 755 /var/www/static_root (ou chown).
403 Forbidden (Statique)(Rien dans error.log, 403 dans access.log)(RHEL/Rocky) SELinux. Le contexte (ls -Z) n'est pas httpd_sys_content_t.sudo restorecon -vR /var/www/.
404 Not Found (Statique)(2: No such file or directory) while opening file "/var/www/static_root/static/..."Vous avez utilisé root au lieu de alias (voir 2.3).Changer root en alias.
5.1 Cheat-sheet Nginx
Commandes CLI
# Tester la configuration (INDISPENSABLE)
sudo nginx -t

# Recharger (zéro downtime)
sudo systemctl reload nginx

# Redémarrer (avec coupure)
sudo systemctl restart nginx

# DĂ©marrer / ArrĂȘter
sudo systemctl start nginx
sudo systemctl stop nginx

# Activer au boot
sudo systemctl enable nginx

# Activer un site (Debian)
sudo ln -s /etc/nginx/sites-available/mon_site /etc/nginx/sites-enabled/

# Désactiver un site (Debian)
sudo rm /etc/nginx/sites-enabled/mon_site
Hiérarchie & Directives Clés
# http { ... } (Dans nginx.conf)
#   Contient:
#   upstream pool_name { ... }
#   proxy_cache_path ...
#   limit_req_zone ...
#
#   server { ... } (Dans sites-available/)
#     Contient:
#     listen 80;
#     listen 443 ssl;
#     server_name example.com;
#     root /var/www/html;
#     add_header ...;
#
#     location / { ... }
#       Contient:
#       proxy_pass http://pool_name;
#       include proxy_params;
#       proxy_cache ...;
#       limit_req ...;
#
#     location /static/ { ... }
#       Contient:
#       alias /path/to/static_root/;
#       expires ...;
#
#     location ~ \.php$ { ... } (Pour PHP)
#       Contient:
#       fastcgi_pass unix:/run/php/php-fpm.sock;
#       include fastcgi_params;
#   }