# Fichier: python_cheats/cheatsheets/nginx.txt
# Cheatsheet Nginx - Guide Complet du Débutant à l'Expert


[OK] INTRODUCTION À NGINX - QU'EST-CE QUE C'EST ?

# === Qu'est-ce qu'un serveur web ? ===
# Un serveur web est un logiciel qui reçoit des requêtes HTTP (quand vous tapez 
# une URL dans votre navigateur) et renvoie des pages web, images, etc.
# 
# Analogie simple: 
# - Votre navigateur = client qui commande au restaurant
# - Le serveur web (Nginx) = serveur qui prend la commande et apporte le plat
# - Les fichiers HTML/CSS/JS = la nourriture servie

# === Nginx (prononcé "engine-x") ===
# Créé en 2004 par Igor Sysoev pour résoudre le "problème C10k" 
# (gérer 10 000 connexions simultanées)

# Nginx peut faire plusieurs choses:

# 1. SERVEUR WEB STATIQUE
#    Sert des fichiers HTML, CSS, JavaScript, images directement
#    Exemple: Votre site vitrine, portfolio, documentation
#
# 2. REVERSE PROXY
#    Reçoit les requêtes et les transmet à d'autres serveurs
#    Exemple: Nginx reçoit la requête sur le port 80 et la transmet 
#             à votre app Node.js qui tourne sur le port 3000
#
# 3. LOAD BALANCER
#    Répartit les requêtes entre plusieurs serveurs backend
#    Exemple: Vous avez 3 serveurs d'application, Nginx distribue 
#             le trafic équitablement entre eux
#
# 4. CACHE HTTP
#    Stocke les réponses pour les servir plus rapidement
#    Exemple: Une page déjà visitée est mise en cache, 
#             pas besoin de la regénérer à chaque fois
#
# 5. GESTIONNAIRE SSL/TLS
#    Gère le chiffrement HTTPS
#    Exemple: Nginx s'occupe du certificat SSL, votre app backend 
#             peut rester en HTTP simple

# === Pourquoi Nginx plutôt qu'Apache ? ===

# NGINX:
# [OK] Architecture événementielle (asynchrone) - très performant
# [OK] Faible consommation mémoire (environ 2.5 MB par worker)
# [OK] Gère facilement 10 000+ connexions simultanées
# [OK] Excellent pour fichiers statiques
# [OK] Configuration simple et lisible
# [OK] Temps de réponse très rapide
# [OK] Utilisé par Netflix, Airbnb, GitHub, WordPress.com

# APACHE:
# [OK] Plus ancien et très stable
# [OK] Plus de modules disponibles
# [OK] .htaccess (config par dossier)
# [X] Plus gourmand en mémoire
# [X] Moins performant sous forte charge

# === Cas d'usage typiques ===

# 1. Site statique simple (HTML/CSS/JS)
#    Nginx sert directement les fichiers
#
# 2. Application web moderne (React, Vue, Angular)
#    Nginx sert les fichiers buildés et gère le routing
#
# 3. API backend (Node.js, Python, Go)
#    Nginx fait le reverse proxy vers votre application
#
# 4. Microservices
#    Nginx route vers différents services selon l'URL
#
# 5. Application haute disponibilité
#    Nginx fait le load balancing entre plusieurs serveurs

# === Architecture Nginx - Comment ça marche ? ===

# MODÈLE TRADITIONNEL (Apache):
# Chaque connexion = 1 thread/processus dédié
# 10 000 connexions = 10 000 threads = BEAUCOUP de RAM
#
# MODÈLE NGINX:
# 1 processus master (gère la config, lance les workers)
# + plusieurs processus workers (gèrent les connexions)
# Chaque worker peut gérer des milliers de connexions simultanément
# grâce à l'architecture événementielle (boucle d'événements)
#
# Exemple:
# - 4 CPU cores -> 4 workers
# - Chaque worker peut gérer 10 000 connexions
# - Total: 40 000 connexions avec seulement 4 processus !

# === Schéma conceptuel ===
#
# Internet
#    v
# [Port 80/443] <- Nginx écoute ici
#    v
# Nginx décide quoi faire selon la configuration:
#    v
# Option 1: Servir fichier statique directement
#    -> /var/www/html/index.html
#
# Option 2: Proxy vers application backend
#    -> localhost:3000 (Node.js)
#    -> localhost:8000 (Python/Django)
#    -> localhost:8080 (Java/Spring)
#
# Option 3: Load balancing
#    -> Serveur 1 (33%)
#    -> Serveur 2 (33%)
#    -> Serveur 3 (33%)


[OK] INSTALLATION - PREMIERS PAS

# === UBUNTU / DEBIAN (Recommandé pour débuter) ===

# Méthode 1: Installation rapide (dépôt Ubuntu)
# Avantage: Simple et rapide
# Inconvénient: Version peut être un peu ancienne

sudo apt update                    # Met à jour la liste des paquets
sudo apt install nginx             # Installe Nginx

# Après installation, Nginx démarre automatiquement !
# Testez en ouvrant votre navigateur sur http://localhost
# Vous devriez voir "Welcome to nginx!"


# Méthode 2: Installation version stable officielle (RECOMMANDÉ)
# Avantage: Dernière version stable avec toutes les fonctionnalités
# Inconvénient: Un peu plus long

# Étape 1: Installer les outils nécessaires
sudo apt install curl gnupg2 ca-certificates lsb-release ubuntu-keyring

# Étape 2: Ajouter la clé de signature Nginx (sécurité)
# Cela vérifie que les paquets viennent bien de Nginx
curl https://nginx.org/keys/nginx_signing.key | gpg --dearmor | \
    sudo tee /usr/share/keyrings/nginx-archive-keyring.gpg >/dev/null

# Étape 3: Ajouter le dépôt officiel Nginx
echo "deb [signed-by=/usr/share/keyrings/nginx-archive-keyring.gpg] \
http://nginx.org/packages/ubuntu `lsb_release -cs` nginx" | \
    sudo tee /etc/apt/sources.list.d/nginx.list

# Étape 4: Installer Nginx
sudo apt update
sudo apt install nginx

# Explication des commandes:
# - curl: télécharge la clé
# - gpg: gère le chiffrement/signatures
# - tee: écrit dans un fichier avec sudo
# - lsb_release -cs: détecte votre version Ubuntu (focal, jammy, etc.)


# === CENTOS / RHEL ===

# Installation depuis dépôt EPEL
sudo yum install epel-release     # Active dépôt EPEL (Extra Packages)
sudo yum install nginx            # Installe Nginx


# === MAC OS ===

# Avec Homebrew (gestionnaire de paquets Mac)
# Si vous n'avez pas Homebrew: https://brew.sh
brew install nginx

# Nginx s'installe dans: /usr/local/etc/nginx/
# Fichiers web dans: /usr/local/var/www/


# === WINDOWS ===

# 1. Télécharger depuis http://nginx.org/en/download.html
#    Choisir "Stable version" Windows
#
# 2. Extraire l'archive ZIP dans C:\nginx
#
# 3. Ouvrir Command Prompt en tant qu'Administrateur
#
# 4. Naviguer vers le dossier:
cd C:\nginx

# 5. Démarrer Nginx:
start nginx

# Note: Sur Windows, Nginx est moins performant qu'en Linux
# Recommandation: Utilisez WSL2 (Windows Subsystem for Linux)


# === VÉRIFIER L'INSTALLATION ===

# Vérifier que Nginx est installé
nginx -v                          # Affiche: nginx version: nginx/1.24.0

# Version détaillée avec modules compilés
nginx -V                          # Affiche la version + tous les modules

# Vérifier que Nginx fonctionne
sudo systemctl status nginx       # Devrait afficher "active (running)"

# Tester dans le navigateur
# Ouvrir: http://localhost ou http://votre-ip-serveur
# Vous devriez voir la page "Welcome to nginx!"


# === PREMIERS TESTS ===

# Où est la page "Welcome to nginx!" ?
# Ubuntu/Debian: /var/www/html/index.nginx-debian.html
# CentOS: /usr/share/nginx/html/index.html

# Créons notre première page:
echo "<h1>Mon premier site avec Nginx !</h1>" | sudo tee /var/www/html/index.html

# Rechargez http://localhost dans votre navigateur
# Vous devriez voir "Mon premier site avec Nginx !"

# Félicitations ! Vous venez de créer votre premier site web avec Nginx [BRAVO]


[OK] GESTION DU SERVICE - DÉMARRER, ARRÊTER, REDÉMARRER

# === Comprendre systemd ===
# systemd est le gestionnaire de services sur Linux moderne
# Il gère le démarrage/arrêt des programmes comme Nginx
# Pensez à systemd comme un chef d'orchestre qui dirige les services

# === SYSTEMD (Ubuntu/Debian/CentOS 7+) ===

# Démarrer Nginx
sudo systemctl start nginx
# Explication: Lance le service Nginx
# Utilisez quand: Nginx est arrêté et vous voulez le démarrer


# Arrêter Nginx
sudo systemctl stop nginx
# Explication: Arrête complètement Nginx
# Attention: Votre site devient inaccessible !
# Utilisez quand: Vous devez faire une maintenance majeure


# Redémarrer Nginx (arrêt puis démarrage)
sudo systemctl restart nginx
# Explication: Arrête puis redémarre complètement
# Attention: Brève interruption de service (quelques secondes)
# Utilisez quand: Vous avez modifié la config principale


# Recharger la configuration (SANS interruption)
sudo systemctl reload nginx
# Explication: Recharge la config sans couper les connexions actives
# C'est MAGIQUE: Les visiteurs ne sont pas déconnectés !
# Utilisez quand: Vous avez modifié la config (90% des cas)
# C'est la commande que vous utiliserez le plus souvent !


# Activer le démarrage automatique au boot
sudo systemctl enable nginx
# Explication: Nginx démarre automatiquement quand le serveur boot
# Très important en production !
# À faire une fois après l'installation


# Désactiver le démarrage automatique
sudo systemctl disable nginx
# Explication: Nginx ne démarre plus au boot
# Utilisez quand: C'est un serveur de développement


# Vérifier le statut de Nginx
sudo systemctl status nginx
# Affiche plein d'infos utiles:
# - Active: active (running) = Nginx fonctionne [OK]
# - Active: inactive (dead) = Nginx est arrêté [X]
# - Main PID: le numéro du processus principal
# - Les dernières lignes de logs


# Voir les logs en temps réel
sudo journalctl -u nginx -f
# Explication:
# - journalctl: outil de logs systemd
# - -u nginx: filtre pour nginx
# - -f: follow (comme tail -f)
# Appuyez sur Ctrl+C pour quitter
# Très utile pour débugger !


# === COMMANDES NGINX DIRECTES (Alternative à systemctl) ===

# Ces commandes sont plus "bas niveau" et fonctionnent partout
# (même sans systemd)

# Démarrer Nginx
sudo nginx
# Simple et direct, mais utilisez plutôt systemctl


# Arrêter Nginx gracieusement (proprement)
sudo nginx -s quit
# Explication: Attend que les requêtes en cours se terminent
# Les utilisateurs ne sont pas brutalement déconnectés
# Peut prendre quelques secondes


# Arrêter Nginx rapidement
sudo nginx -s stop
# Explication: Arrêt immédiat, coupe les connexions
# Plus brutal mais plus rapide


# Recharger la configuration
sudo nginx -s reload
# Comme systemctl reload
# Très utilisé après modification de la config


# Rouvrir les fichiers de log
sudo nginx -s reopen
# Explication: Ferme et rouvre les logs
# Utile après rotation des logs
# (quand vous archivez les vieux logs)


# Tester la configuration AVANT de recharger
sudo nginx -t
# SUPER IMPORTANT !
# Vérifie la syntaxe de votre config
# Si erreur, Nginx vous dit où et pourquoi
# Exemple de sortie:
#   nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
#   nginx: configuration file /etc/nginx/nginx.conf test is successful
# TOUJOURS faire nginx -t avant reload !


# Tester ET afficher toute la configuration
sudo nginx -T
# Affiche la config complète après traitement des includes
# Utile pour débugger


# Afficher la version
nginx -v
# Affiche: nginx version: nginx/1.24.0


# Afficher version + modules compilés
nginx -V
# Très détaillé, montre tous les modules disponibles
# Utile pour vérifier si un module est présent


# === WORKFLOW TYPIQUE APRÈS MODIFICATION CONFIG ===

# Étape 1: Modifier la config
sudo nano /etc/nginx/sites-available/monsite

# Étape 2: TOUJOURS tester avant !
sudo nginx -t

# Si OK (syntax is ok):
# Étape 3: Recharger
sudo systemctl reload nginx

# Si ERREUR:
# - Nginx affiche l'erreur avec le numéro de ligne
# - Corrigez l'erreur
# - Retestez avec nginx -t
# - Ne faites JAMAIS reload sans tester !


# === EXEMPLE COMPLET DÉBUTANT ===

# Situation: Vous venez de modifier votre site
# Voici les commandes à exécuter:

# 1. Tester la config
sudo nginx -t

# Sortie si OK:
# nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
# nginx: configuration file /etc/nginx/nginx.conf test is successful

# 2. Si test OK, recharger
sudo systemctl reload nginx

# 3. Vérifier que tout marche
sudo systemctl status nginx

# 4. Tester dans le navigateur
# Ouvrir http://localhost


# === COMMANDES DE DIAGNOSTIC ===

# Voir les processus Nginx
ps aux | grep nginx
# Vous verrez:
# - 1 processus master (lancé par root)
# - Plusieurs processus worker (lancés par www-data)


# Compter le nombre de connexions actives
netstat -an | grep :80 | wc -l
# Affiche le nombre de connexions sur le port 80


# Voir qui écoute sur le port 80
sudo lsof -i :80
# Utile si vous avez "Address already in use"


# === ERREURS COURANTES DÉBUTANTS ===

# Erreur: "nginx: [emerg] bind() to 0.0.0.0:80 failed (98: Address already in use)"
# Cause: Un autre service (souvent Apache) utilise déjà le port 80
# Solution:
sudo systemctl stop apache2     # Arrêter Apache
sudo systemctl start nginx      # Démarrer Nginx

# Erreur: "Job for nginx.service failed"
# Cause: Erreur dans la configuration
# Solution:
sudo nginx -t                   # Voir l'erreur exacte
# Corriger l'erreur mentionnée
# Réessayer

# Erreur: "Permission denied"
# Cause: Vous avez oublié sudo
# Solution:
sudo systemctl start nginx      # Avec sudo cette fois !


# === ASTUCE PRO ===

# Créer un alias pour tester + recharger en une commande
echo 'alias nginx-reload="sudo nginx -t && sudo systemctl reload nginx"' >> ~/.bashrc
source ~/.bashrc

# Maintenant vous pouvez simplement faire:
nginx-reload
# Ça teste ET recharge seulement si test OK !


# === RÉSUMÉ POUR DÉBUTANT ===

# Après installation (une seule fois):
sudo systemctl enable nginx     # Démarrage auto au boot

# Après modification de config (à chaque fois):
sudo nginx -t                   # Tester
sudo systemctl reload nginx     # Recharger si OK

# Pour débugger:
sudo systemctl status nginx     # Voir le statut
sudo journalctl -u nginx -f     # Voir les logs en direct

# Pour redémarrer complètement (rare):
sudo systemctl restart nginx


[OK] STRUCTURE DES FICHIERS - OÙ SE TROUVE QUOI ?

# === COMPRENDRE L'ARBORESCENCE ===

# Nginx organise ses fichiers dans plusieurs dossiers
# Chaque dossier a un rôle précis
# C'est comme une bibliothèque bien rangée !


# === UBUNTU/DEBIAN (Structure la plus courante) ===

/etc/nginx/                     # [DOSSIER] RACINE - Configuration principale Nginx
│                               # Tous les fichiers de configuration sont ici
│                               # Chemin standard Debian/Ubuntu
│
├── nginx.conf                  # [CONFIG] FICHIER PRINCIPAL - Configuration globale
│                               # C'est le "cerveau" de Nginx
│                               # Définit les paramètres généraux du serveur
│                               # Contient les blocs : events { }, http { }
│                               # Charge automatiquement sites-enabled/*
│                               # NE MODIFIEZ PAS si débutant (sauf cas précis)
│                               # 
│                               # Structure typique :
│                               # - user www-data;
│                               # - worker_processes auto;
│                               # - events { worker_connections 768; }
│                               # - http { ... include sites-enabled/*; }
│
├── mime.types                  # [FICHIER] Types MIME (extensions de fichiers)
│                               # Dit à Nginx comment interpréter chaque extension
│                               # 
│                               # Exemples de correspondances :
│                               # .html -> text/html
│                               # .css  -> text/css
│                               # .js   -> application/javascript
│                               # .json -> application/json
│                               # .jpg  -> image/jpeg
│                               # .png  -> image/png
│                               # .pdf  -> application/pdf
│                               # .mp4  -> video/mp4
│                               # .woff2 -> font/woff2
│                               # 
│                               # Le navigateur sait ainsi comment afficher
│                               # Géré automatiquement, NE PAS TOUCHER
│
├── fastcgi.conf                # [CONFIG] Configuration FastCGI (pour PHP)
│                               # Paramètres pour communiquer avec PHP-FPM
│                               # Utilisé quand vous servez du PHP
│
├── fastcgi_params              # [LISTE] Paramètres FastCGI
│                               # Variables d'environnement pour PHP
│                               # Ex: SCRIPT_FILENAME, QUERY_STRING
│
├── scgi_params                 # [LISTE] Paramètres SCGI
│                               # Pour applications Python/SCGI
│
├── uwsgi_params                # [LISTE] Paramètres uWSGI
│                               # Pour applications Python (Django/Flask)
│
├── koi-utf                     # [MONDE] Table d'encodage (Cyrillique -> UTF-8)
├── koi-win                     # [MONDE] Table d'encodage (Cyrillique -> Windows)
├── win-utf                     # [MONDE] Table d'encodage (Windows -> UTF-8)
│                               # Rarement utilisés, gérés automatiquement
│
├── proxy_params                # [SYNC] Paramètres pour reverse proxy
│                               # Headers à transmettre lors du proxying
│                               # Ex: X-Real-IP, X-Forwarded-For
│
├── sites-available/            # [DOCS] SITES DISPONIBLES
│   │                           # * DOSSIER OÙ VOUS CRÉEZ VOS CONFIGURATIONS
│   │                           # Tous vos fichiers de config de sites/domaines
│   │                           # Les sites ici ne sont PAS actifs
│   │                           # C'est un "répertoire de stockage"
│   │                           # 
│   │                           # [IDEE] Philosophie Ubuntu :
│   │                           # 1. Créer config ici (sites-available)
│   │                           # 2. Activer avec lien symbolique (sites-enabled)
│   │                           # 3. Désactiver en supprimant le lien
│   │                           # 
│   │                           # Permet de garder configs sans les activer
│   │                           # Pratique pour tester ou archiver
│   │
│   ├── default                 # [WEB] Site par défaut (fourni par Nginx)
│   │                           # Configuration d'exemple
│   │                           # Écoute sur port 80
│   │                           # Sert /var/www/html/
│   │                           # Vous pouvez le modifier ou le remplacer
│   │                           # 
│   │                           # Contenu typique :
│   │                           # server {
│   │                           #     listen 80 default_server;
│   │                           #     root /var/www/html;
│   │                           #     index index.html;
│   │                           #     server_name _;
│   │                           # }
│   │
│   ├── monsite.com             # <- VOS SITES ICI
│   │                           # Exemple : config pour monsite.com
│   │                           # Un fichier par site/domaine
│   │                           # 
│   │                           # Convention de nommage :
│   │                           # - monsite.com (avec extension domaine)
│   │                           # - monsite.com.conf
│   │                           # - api.monsite.com
│   │                           # 
│   │                           # Structure typique :
│   │                           # server {
│   │                           #     listen 80;
│   │                           #     server_name monsite.com www.monsite.com;
│   │                           #     root /var/www/monsite.com/html;
│   │                           #     index index.html index.php;
│   │                           #     
│   │                           #     location / {
│   │                           #         try_files $uri $uri/ =404;
│   │                           #     }
│   │                           # }
│   │
│   ├── api.monsite.com         # <- Configuration pour sous-domaine API
│   │                           # Exemple : API REST
│   │                           # Peut pointer vers application Node.js, Python
│   │                           # 
│   │                           # Exemple reverse proxy :
│   │                           # server {
│   │                           #     listen 80;
│   │                           #     server_name api.monsite.com;
│   │                           #     
│   │                           #     location / {
│   │                           #         proxy_pass http://localhost:3000;
│   │                           #         proxy_set_header Host $host;
│   │                           #     }
│   │                           # }
│   │
│   ├── blog.exemple.org        # <- Autre site (WordPress, Ghost...)
│   │
│   └── monsite.com-ssl         # <- Version HTTPS du site
│                               # Souvent séparée pour clarté
│                               # Ou fusionnée avec redirections
│
├── sites-enabled/              # [LIEN] SITES ACTIFS
│   │                           # [RAPIDE] DOSSIER DES SITES EN PRODUCTION
│   │                           # Contient des liens symboliques (symlinks)
│   │                           # vers les fichiers de sites-available/
│   │                           # 
│   │                           # [IDEE] SEULS les sites ici sont actifs !
│   │                           # Nginx charge UNIQUEMENT ce dossier
│   │                           # (via include sites-enabled/* dans nginx.conf)
│   │                           # 
│   │                           # [LIEN] Lien symbolique = raccourci Linux
│   │                           # Pointe vers le fichier réel dans sites-available
│   │
│   └── default -> ../sites-available/default
│                               # ^ Lien symbolique vers le site default
│                               # La flèche -> indique que c'est un lien
│                               # 
│                               # Commande de création :
│                               # ln -s /etc/nginx/sites-available/default \
│                               #       /etc/nginx/sites-enabled/default
│                               # 
│                               # Pour activer un site :
│                               # sudo ln -s /etc/nginx/sites-available/monsite.com \
│                               #            /etc/nginx/sites-enabled/
│                               # 
│                               # Pour désactiver (sans supprimer config) :
│                               # sudo rm /etc/nginx/sites-enabled/monsite.com
│                               # (Le fichier reste dans sites-available)
│                               # 
│                               # Vérifier les liens :
│                               # ls -la /etc/nginx/sites-enabled/
│
├── snippets/                   # [MODULE] MORCEAUX DE CONFIG RÉUTILISABLES
│   │                           # Bouts de configuration à inclure
│   │                           # Évite la duplication de code
│   │                           # Utilisés avec directive "include"
│   │                           # 
│   │                           # [IDEE] Principe DRY (Don't Repeat Yourself)
│   │                           # Écrivez une fois, réutilisez partout
│   │
│   ├── fastcgi-php.conf        # [POSTGRES] Configuration PHP-FPM
│   │                           # À inclure dans location ~ \.php$
│   │                           # 
│   │                           # Contenu typique :
│   │                           # fastcgi_pass unix:/run/php/php8.1-fpm.sock;
│   │                           # fastcgi_index index.php;
│   │                           # include fastcgi.conf;
│   │                           # 
│   │                           # Utilisation dans votre site :
│   │                           # location ~ \.php$ {
│   │                           #     include snippets/fastcgi-php.conf;
│   │                           # }
│   │
│   ├── ssl-params.conf         # [VERROUILLE] Paramètres SSL/TLS réutilisables
│   │                           # Configuration HTTPS commune
│   │                           # 
│   │                           # Exemple de contenu :
│   │                           # ssl_protocols TLSv1.2 TLSv1.3;
│   │                           # ssl_prefer_server_ciphers on;
│   │                           # ssl_ciphers ECDHE-RSA-AES256-GCM-SHA512:...;
│   │                           # ssl_session_timeout 1d;
│   │                           # ssl_session_cache shared:SSL:50m;
│   │                           # 
│   │                           # Utilisation :
│   │                           # server {
│   │                           #     listen 443 ssl;
│   │                           #     include snippets/ssl-params.conf;
│   │                           # }
│   │
│   └── snakeoil.conf           # [SECURISE] Certificat auto-signé par défaut
│                               # Pour tests SSL en local
│                               # NE PAS utiliser en production !
│                               # (Navigateurs afficheront avertissement)
│
├── conf.d/                     # [CONFIG] CONFIGURATIONS ADDITIONNELLES
│   │                           # Fichiers .conf chargés automatiquement
│   │                           # par nginx.conf (include conf.d/*.conf)
│   │                           # 
│   │                           # [IDEE] Sur Ubuntu, souvent vide ou peu utilisé
│   │                           # (préférence pour sites-available/enabled)
│   │                           # 
│   │                           # Sur CentOS, c'est LE dossier principal
│   │                           # Sur Ubuntu, utilisé pour configs globales
│   │
│   ├── custom-logs.conf        # Exemple : formats de logs personnalisés
│   ├── rate-limiting.conf      # Exemple : limitation de débit
│   └── security-headers.conf   # Exemple : en-têtes de sécurité globaux
│
├── modules-available/          # [PLUGIN] MODULES DISPONIBLES
│   │                           # Modules Nginx dynamiques disponibles
│   │                           # Similaire à sites-available
│   ├── 50-mod-http-geoip.conf
│   ├── 50-mod-http-image-filter.conf
│   ├── 50-mod-http-xslt-filter.conf
│   └── 50-mod-stream.conf
│
├── modules-enabled/            # [LIEN] MODULES ACTIFS
│   │                           # Liens symboliques vers modules-available
│   │                           # Modules chargés au démarrage
│   └── 50-mod-http-geoip.conf -> ../modules-available/50-mod-http-geoip.conf
│
└── .htpasswd                   # [CLE] Fichiers d'authentification (optionnel)
                                # Mots de passe pour auth_basic
                                # Créé manuellement avec htpasswd
                                # 
                                # Création :
                                # sudo htpasswd -c /etc/nginx/.htpasswd user1
                                # 
                                # Utilisation dans site :
                                # location /admin {
                                #     auth_basic "Zone Admin";
                                #     auth_basic_user_file /etc/nginx/.htpasswd;
                                # }


/var/log/nginx/                 # [GRAPHIQUE] LOGS - Fichiers journaux
│                               # Enregistrement de toutes les activités
│                               # [ATTENTION] Peuvent devenir volumineux !
│                               # Rotation automatique via logrotate
│
├── access.log                  # [NOTE] LOG D'ACCÈS - Historique des requêtes
│                               # Enregistre CHAQUE requête HTTP
│                               # 
│                               # Format typique d'une ligne :
│                               # 192.168.1.50 - - [17/Nov/2025:14:25:30 +0000] 
│                               # "GET /api/users HTTP/1.1" 200 1234 
│                               # "https://monsite.com/" 
│                               # "Mozilla/5.0 (Windows NT 10.0; Win64; x64)"
│                               # 
│                               # Décomposition :
│                               # 192.168.1.50          -> IP du visiteur
│                               # -                      -> Utilisateur auth (si auth_basic)
│                               # -                      -> Nom utilisateur
│                               # [17/Nov/2025:14:25:30] -> Date et heure
│                               # GET /api/users         -> Méthode + URL
│                               # HTTP/1.1               -> Version protocole
│                               # 200                    -> Code de statut
│                               # 1234                   -> Taille réponse (octets)
│                               # "https://..."          -> Referer (page origine)
│                               # "Mozilla/5.0..."       -> User-Agent (navigateur)
│                               # 
│                               # [IDEE] Utilisation :
│                               # tail -f /var/log/nginx/access.log
│                               # (suivi en temps réel)
│                               # 
│                               # grep "404" access.log
│                               # (trouver pages non trouvées)
│                               # 
│                               # awk '{print $1}' access.log | sort | uniq -c | sort -nr
│                               # (top IPs visiteurs)
│                               # 
│                               # [RECHERCHE] Utile pour :
│                               # - Statistiques de trafic
│                               # - Analyser comportement utilisateurs
│                               # - Détecter bots et scrapers
│                               # - Audit de sécurité
│                               # - Déboguer problèmes de routing
│
├── error.log                   # [X] LOG D'ERREURS - Problèmes et bugs
│                               # Enregistre erreurs et avertissements
│                               # 
│                               # [RECHERCHE] PREMIER FICHIER À CONSULTER en cas de bug !
│                               # 
│                               # Types d'erreurs courantes :
│                               # 
│                               # 1. Erreurs de configuration :
│                               # [emerg] unexpected "}" in nginx.conf:45
│                               # [emerg] bind() to 0.0.0.0:80 failed
│                               # 
│                               # 2. Fichiers non trouvés (404) :
│                               # [error] open() "/var/www/html/page.html" failed
│                               # (2: No such file or directory)
│                               # 
│                               # 3. Permissions :
│                               # [crit] open() "/var/www/..." failed
│                               # (13: Permission denied)
│                               # 
│                               # 4. Erreurs PHP/FastCGI :
│                               # [error] recv() failed (104: Connection reset)
│                               # upstream: "fastcgi://unix:/run/php/..."
│                               # 
│                               # 5. Problèmes upstream/proxy :
│                               # [error] connect() failed (111: Connection refused)
│                               # upstream: "http://127.0.0.1:3000"
│                               # 
│                               # 6. Limites dépassées :
│                               # [warn] could not build optimal types_hash
│                               # [error] client intended to send too large body
│                               # 
│                               # 7. SSL/TLS :
│                               # [emerg] cannot load certificate
│                               # [error] SSL_do_handshake() failed
│                               # 
│                               # [IDEE] Commandes utiles :
│                               # tail -n 50 /var/log/nginx/error.log
│                               # (50 dernières erreurs)
│                               # 
│                               # tail -f /var/log/nginx/error.log
│                               # (suivi temps réel)
│                               # 
│                               # grep "emerg\|crit\|alert" error.log
│                               # (erreurs critiques uniquement)
│                               # 
│                               # Niveaux de log (du plus au moins grave) :
│                               # emerg  -> Urgence (système inutilisable)
│                               # alert  -> Alerte (action immédiate requise)
│                               # crit   -> Critique
│                               # error  -> Erreur
│                               # warn   -> Avertissement
│                               # notice -> Notice
│                               # info   -> Information
│                               # debug  -> Debug (très verbeux)
│                               # 
│                               # Changer niveau dans nginx.conf :
│                               # error_log /var/log/nginx/error.log warn;
│
├── monsite.com.access.log      # [NOTE] Log spécifique à un site (optionnel)
│                               # Si configuré dans le bloc server :
│                               # access_log /var/log/nginx/monsite.com.access.log;
│                               # 
│                               # [IDEE] Pratique pour :
│                               # - Séparer logs par site
│                               # - Analyser un site spécifiquement
│                               # - Donner accès logs à un client
│
└── monsite.com.error.log       # [X] Erreurs spécifiques à un site (optionnel)
                                # error_log /var/log/nginx/monsite.com.error.log;


/var/www/                       # [WEB] RACINE WEB - Fichiers des sites
│                               # Dossier standard pour héberger sites web
│                               # Convention Ubuntu/Debian
│                               # 
│                               # [IDEE] Organisation recommandée :
│                               # Un sous-dossier par site/domaine
│
├── html/                       # [ACCUEIL] Site par défaut
│   │                           # Servi par /etc/nginx/sites-available/default
│   │                           # C'est ici que pointe root par défaut
│   │
│   ├── index.html              # Page d'accueil par défaut
│   │                           # Page "Welcome to nginx" d'origine
│   │                           # Remplacez par votre site
│   │
│   ├── 50x.html                # Page d'erreur 50x (erreur serveur)
│   │                           # Affichée lors d'erreurs 500, 502, 503, 504
│   │
│   └── assets/                 # Vos ressources (images, CSS, JS...)
│       ├── css/
│       ├── js/
│       └── images/
│
├── monsite.com/                # [DOSSIER] Dossier pour monsite.com
│   │                           # Organisation recommandée par site
│   │
│   ├── html/                   # Racine web publique (root)
│   │   ├── index.html          # Page d'accueil
│   │   ├── about.html
│   │   ├── contact.html
│   │   └── assets/
│   │
│   ├── logs/                   # Logs du site (optionnel)
│   │   ├── access.log
│   │   └── error.log
│   │
│   └── ssl/                    # Certificats SSL (optionnel)
│       ├── cert.pem
│       └── key.pem
│
├── api.monsite.com/            # [DOSSIER] Dossier pour sous-domaine API
│   └── public/                 # Si application Node.js, Python...
│
└── blog.exemple.org/           # [DOSSIER] Autre site
    ├── html/
    └── wp-content/             # Exemple : WordPress


/var/cache/nginx/               # [SAUVEGARDE] CACHE NGINX
│                               # Stockage temporaire pour performance
│                               # Créé automatiquement si proxy_cache activé
│
├── proxy_cache/                # Cache du reverse proxy
│   └── ...                     # Fichiers en cache
│
├── fastcgi_cache/              # Cache FastCGI (PHP)
│   └── ...                     # Réponses PHP en cache
│
└── client_temp/                # Fichiers temporaires uploads clients
    └── ...


/run/nginx.pid                  # [NOTE] Fichier PID (Process ID)
                                # Contient le numéro du processus Nginx master
                                # Exemple de contenu : 1234
                                # 
                                # Utilisé par :
                                # - systemctl pour contrôler Nginx
                                # - Scripts de monitoring
                                # - Commandes nginx -s reload
                                # 
                                # Autres emplacements possibles :
                                # /var/run/nginx.pid


/lib/systemd/system/nginx.service  # [RAPIDE] Service systemd Nginx
                                   # Définit comment démarrer/arrêter Nginx
                                   # Gère le service au boot
                                   # 
                                   # Commandes systemctl :
                                   # sudo systemctl start nginx
                                   # sudo systemctl stop nginx
                                   # sudo systemctl restart nginx
                                   # sudo systemctl reload nginx
                                   # sudo systemctl enable nginx  (démarrage auto)
                                   # sudo systemctl disable nginx
                                   # sudo systemctl status nginx


# ═══════════════════════════════════════════════════════════
# [NOTE] WORKFLOW TYPIQUE SUR UBUNTU
# ═══════════════════════════════════════════════════════════

# 1⃣ Créer une configuration de site
sudo nano /etc/nginx/sites-available/monsite.com

# Exemple de contenu :
# server {
#     listen 80;
#     server_name monsite.com www.monsite.com;
#     root /var/www/monsite.com/html;
#     index index.html index.php;
#     
#     location / {
#         try_files $uri $uri/ =404;
#     }
# }

# 2⃣ Créer le dossier web
sudo mkdir -p /var/www/monsite.com/html
sudo chown -R $USER:$USER /var/www/monsite.com/html
sudo chmod -R 755 /var/www/monsite.com

# 3⃣ Créer une page de test
echo "<h1>Bienvenue sur monsite.com</h1>" | sudo tee /var/www/monsite.com/html/index.html

# 4⃣ Tester la configuration
sudo nginx -t

# 5⃣ Activer le site (créer lien symbolique)
sudo ln -s /etc/nginx/sites-available/monsite.com /etc/nginx/sites-enabled/

# Vérifier le lien :
ls -la /etc/nginx/sites-enabled/

# 6⃣ Désactiver le site par défaut (optionnel)
sudo rm /etc/nginx/sites-enabled/default

# 7⃣ Recharger Nginx
sudo systemctl reload nginx

# 8⃣ Vérifier que ça fonctionne
curl http://localhost
# ou ouvrir dans navigateur : http://votre-ip

# 9⃣ Voir les logs en temps réel
sudo tail -f /var/log/nginx/access.log
sudo tail -f /var/log/nginx/error.log

# [10] Désactiver le site (sans supprimer la config)
sudo rm /etc/nginx/sites-enabled/monsite.com
sudo systemctl reload nginx

# Le fichier reste dans sites-available pour réactivation future


# ═══════════════════════════════════════════════════════════
# [IDEE] ASTUCES UBUNTU
# ═══════════════════════════════════════════════════════════

[OK] Toujours tester avant de recharger :
   sudo nginx -t && sudo systemctl reload nginx

[OK] Voir la configuration complète active :
   sudo nginx -T | less

[OK] Vérifier les sites actifs :
   ls -la /etc/nginx/sites-enabled/

[OK] Vérifier syntaxe d'un fichier spécifique :
   sudo nginx -t -c /etc/nginx/sites-available/monsite.com

[OK] Permissions correctes pour /var/www :
   sudo chown -R www-data:www-data /var/www
   sudo chmod -R 755 /var/www

[OK] Backup avant modification :
   sudo cp /etc/nginx/nginx.conf /etc/nginx/nginx.conf.backup
   sudo cp /etc/nginx/sites-available/default /etc/nginx/sites-available/default.backup

[OK] Rotation des logs (automatique via logrotate) :
   cat /etc/logrotate.d/nginx

[OK] Compresser vieux logs manuellement :
   sudo gzip /var/log/nginx/access.log.1

[OK] Voir l'espace utilisé par les logs :
   du -sh /var/log/nginx/


# ═══════════════════════════════════════════════════════════
# [OUTIL] COMMANDES ESSENTIELLES
# ═══════════════════════════════════════════════════════════

# Gestion du service :
sudo systemctl start nginx              # Démarrer
sudo systemctl stop nginx               # Arrêter
sudo systemctl restart nginx            # Redémarrer (coupe connexions)
sudo systemctl reload nginx             # Recharger (sans couper)
sudo systemctl status nginx             # Voir statut
sudo systemctl enable nginx             # Démarrage automatique au boot
sudo systemctl disable nginx            # Désactiver démarrage auto

# Tests et diagnostics :
sudo nginx -t                           # Tester config
sudo nginx -T                           # Voir config complète
sudo nginx -v                           # Version courte
sudo nginx -V                           # Version + modules compilés

# Commandes Nginx directes :
sudo nginx -s reload                    # Recharger
sudo nginx -s stop                      # Arrêt immédiat
sudo nginx -s quit                      # Arrêt gracieux (finit requêtes)
sudo nginx -s reopen                    # Rouvrir logs (après rotation)

# Logs :
sudo tail -f /var/log/nginx/access.log  # Suivi accès
sudo tail -f /var/log/nginx/error.log   # Suivi erreurs
sudo tail -n 100 /var/log/nginx/error.log  # 100 dernières lignes
sudo grep "error" /var/log/nginx/error.log  # Filtrer erreurs

# Réseau :
sudo netstat -tlnp | grep nginx         # Ports écoutés
sudo lsof -i :80                        # Qui utilise port 80
sudo ss -tlnp | grep nginx              # Alternative moderne


# ═══════════════════════════════════════════════════════════
# [BUG] DÉPANNAGE UBUNTU
# ═══════════════════════════════════════════════════════════

[X] nginx: [emerg] bind() to 0.0.0.0:80 failed (98: Address already in use)
   -> Un autre processus utilise le port 80
   sudo lsof -i :80
   sudo systemctl stop apache2  (si Apache installé)
   sudo kill -9 <PID>

[X] nginx: [emerg] open() "/etc/nginx/nginx.conf" failed (13: Permission denied)
   -> Problème de permissions
   sudo chown root:root /etc/nginx/nginx.conf
   sudo chmod 644 /etc/nginx/nginx.conf

[X] 403 Forbidden sur votre site
   -> Problème de permissions /var/www
   sudo chown -R www-data:www-data /var/www/monsite.com
   sudo chmod -R 755 /var/www/monsite.com

[X] 502 Bad Gateway
   -> Service backend (PHP-FPM, Node.js) non démarré
   sudo systemctl status php8.1-fpm
   sudo systemctl start php8.1-fpm

[X] Le site ne se charge pas après activation
   -> Vérifier que le lien symbolique existe
   ls -la /etc/nginx/sites-enabled/
   -> Vérifier la config
   sudo nginx -t
   -> Recharger Nginx
   sudo systemctl reload nginx

[X] Changes not applied after reload
   -> Faire un restart complet
   sudo systemctl restart nginx

[X] Cannot find error in logs
   -> Augmenter niveau de log
   sudo nano /etc/nginx/nginx.conf
   # Changer : error_log /var/log/nginx/error.log debug;
   sudo systemctl reload nginx


# === COMPRENDRE sites-available vs sites-enabled ===

# ANALOGIE: Interrupteurs de lumière
# 
# sites-available/ = Toutes vos lampes (branchées mais éteintes)
# sites-enabled/   = Les lampes allumées (avec l'interrupteur ON)
#
# Pour "allumer" un site (l'activer):
sudo ln -s /etc/nginx/sites-available/monsite /etc/nginx/sites-enabled/
#          └─ ln -s = créer un lien symbolique (raccourci)
#
# Pour "éteindre" un site (le désactiver):
sudo rm /etc/nginx/sites-enabled/monsite
#
# Le fichier dans sites-available reste intact !
# Vous pouvez le réactiver plus tard


# === EXEMPLE PRATIQUE COMPLET ===

# Situation: Créer un nouveau site "monsite.com"

# Étape 1: Créer le fichier de configuration
sudo nano /etc/nginx/sites-available/monsite.com

# Étape 2: Écrire la config (voir section suivante)

# Étape 3: Activer le site (créer le lien symbolique)
sudo ln -s /etc/nginx/sites-available/monsite.com /etc/nginx/sites-enabled/

# Étape 4: Tester la config
sudo nginx -t

# Étape 5: Recharger Nginx
sudo systemctl reload nginx

# C'est tout ! Votre site est en ligne [BRAVO]


# === CENTOS/RHEL (Plus simple, pas de sites-available) ===

/etc/nginx/                     # [DOSSIER] RACINE - Tous les fichiers de config
│
├── nginx.conf                  # [CONFIG] FICHIER PRINCIPAL - Config globale
│                               # C'est le "cerveau" de Nginx
│                               # Définit les paramètres généraux du serveur
│                               # Charge automatiquement conf.d/*.conf
│                               # NE MODIFIEZ PAS si débutant (sauf cas précis)
│
├── mime.types                  # [FICHIER] Types MIME (HTML, CSS, JS, images...)
│                               # Dit à Nginx comment interpréter les extensions
│                               # (.html -> text/html, .jpg -> image/jpeg)
│                               # Géré automatiquement, ne pas toucher
│
├── fastcgi.conf                # [CONFIG] Config FastCGI (pour PHP)
├── fastcgi_params              # [LISTE] Paramètres FastCGI
├── scgi_params                 # [LISTE] Paramètres SCGI
├── uwsgi_params                # [LISTE] Paramètres uWSGI (Python/Django)
│
├── conf.d/                     # [DOSSIER] CONFIGURATIONS DE SITES
│   │                           # * C'EST ICI QUE TOUT SE PASSE !
│   │                           # Tous les fichiers .conf sont chargés AUTO
│   │                           # Pas besoin de liens symboliques
│   │
│   ├── default.conf            # [WEB] Site par défaut (exemple fourni)
│   │                           # Config du serveur web de base
│   │                           # Écoute sur le port 80
│   │
│   ├── monsite.com.conf        # <- Créez vos sites directement ici
│   ├── api.monsite.com.conf    # <- Un fichier .conf par site
│   └── blog.example.org.conf   # <- Aucun besoin d'activation manuelle
│                               # 
│                               # [IDEE] DIFFÉRENCE MAJEURE avec Ubuntu :
│                               # Pas de sites-available/sites-enabled
│                               # Tout fichier .conf ici est ACTIF !
│
├── default.d/                  # [DOSSIER] Configs incluses par default.conf
│   └── *.conf                  # Petits fichiers de config supplémentaires
│                               # chargés par le site default
│
└── modules/                    # [PLUGIN] MODULES NGINX
    └── *.conf                  # Modules dynamiques disponibles


/var/log/nginx/                 # [GRAPHIQUE] LOGS - Fichiers journaux
├── access.log                  # [NOTE] LOG D'ACCÈS - Historique des requêtes
│                               # Format : IP | Date | Page | Code HTTP
│                               # Exemple : 192.168.1.10 [17/Nov/2025] 
│                               #          "GET /index.html" 200
│
└── error.log                   # [X] LOG D'ERREURS - Problèmes et bugs
                                # Erreurs 404 (page non trouvée)
                                # Erreurs 500 (erreur serveur)
                                # Problèmes de config
                                # [ATTENTION] CONSULTEZ TOUJOURS en cas de souci !


/usr/share/nginx/html/          # [WEB] RACINE WEB PAR DÉFAUT
│                               # Dossier des fichiers du site par défaut
│                               # Équivalent de /var/www/html sous Ubuntu
│
├── index.html                  # [ACCUEIL] Page d'accueil par défaut
├── 404.html                    # Page d'erreur 404
├── 50x.html                    # Page d'erreur 50x (erreurs serveur)
└── nginx-logo.png              # Logo Nginx


/var/cache/nginx/               # [SAUVEGARDE] CACHE NGINX
│                               # Stockage temporaire des fichiers en cache
├── client_temp/                # Cache des uploads clients
├── proxy_temp/                 # Cache du reverse proxy
└── fastcgi_temp/               # Cache FastCGI (PHP)


/etc/sysconfig/nginx            # [CONFIG] OPTIONS DE DÉMARRAGE (spécifique RHEL/CentOS)
                                # Variables d'environnement pour systemd
                                # Rarement modifié


# ═══════════════════════════════════════════════════════════
# [CLE] DIFFÉRENCES CLÉS : CentOS vs Ubuntu
# ═══════════════════════════════════════════════════════════

UBUNTU/DEBIAN                   CENTOS/RHEL
─────────────────────────────────────────────────────────────
/etc/nginx/sites-available/  ->  /etc/nginx/conf.d/
/etc/nginx/sites-enabled/    ->  (N'existe pas - inutile)
/var/www/html/               ->  /usr/share/nginx/html/

Activation d'un site :          Activation d'un site :
ln -s sites-available/site   ->  Créer directement le .conf
      sites-enabled/site        dans conf.d/

Désactiver un site :            Désactiver un site :
rm sites-enabled/site        ->  Renommer en .conf.disabled
                                ou déplacer hors de conf.d/


# ═══════════════════════════════════════════════════════════
# [NOTE] WORKFLOW TYPIQUE SUR CENTOS
# ═══════════════════════════════════════════════════════════

1⃣ Créer une config :
   sudo nano /etc/nginx/conf.d/monsite.com.conf

2⃣ Tester la config :
   sudo nginx -t

3⃣ Recharger Nginx :
   sudo systemctl reload nginx

4⃣ Désactiver temporairement (si besoin) :
   sudo mv /etc/nginx/conf.d/monsite.com.conf \
           /etc/nginx/conf.d/monsite.com.conf.disabled
   sudo systemctl reload nginx

5⃣ Réactiver :
   sudo mv /etc/nginx/conf.d/monsite.com.conf.disabled \
           /etc/nginx/conf.d/monsite.com.conf
   sudo systemctl reload nginx


# ═══════════════════════════════════════════════════════════
# [IDEE] ASTUCES CENTOS
# ═══════════════════════════════════════════════════════════

[OK] Plus simple qu'Ubuntu (pas de gestion de liens)
[OK] Tous les .conf dans conf.d/ sont actifs automatiquement
[OK] Parfait pour les scripts d'automatisation
[ATTENTION] Attention : tout .conf est chargé (pas de "staging")
[IDEE] Convention : utilisez .disabled pour désactiver
[IDEE] Organisez avec des préfixes : 01-main.conf, 02-api.conf

# Sur CentOS, pas besoin de ln -s
# Créez directement vos configs dans conf.d/


# === MAC (Homebrew) ===

/usr/local/etc/nginx/           # [DOSSIER] RACINE - Configuration Nginx (Intel Mac)
│                               # ou /opt/homebrew/etc/nginx/ (Apple Silicon M1/M2/M3)
│                               # Homebrew installe ici au lieu de /etc/
│
├── nginx.conf                  # [CONFIG] FICHIER PRINCIPAL - Config globale
│                               # C'est le "cerveau" de Nginx
│                               # Définit les paramètres généraux
│                               # Structure similaire à Ubuntu/CentOS
│                               # NE MODIFIEZ PAS si débutant (sauf cas précis)
│
├── mime.types                  # [FICHIER] Types MIME (HTML, CSS, JS, images...)
│                               # Dit à Nginx comment interpréter les extensions
│                               # Géré automatiquement, ne pas toucher
│
├── fastcgi.conf                # [CONFIG] Config FastCGI (pour PHP)
├── fastcgi_params              # [LISTE] Paramètres FastCGI
├── scgi_params                 # [LISTE] Paramètres SCGI
├── uwsgi_params                # [LISTE] Paramètres uWSGI (Python/Django)
│
├── koi-utf                     # [MONDE] Tables d'encodage (Russe)
├── koi-win                     # [MONDE] Tables d'encodage (Windows)
├── win-utf                     # [MONDE] Tables d'encodage (UTF)
│
├── servers/                    # [DOSSIER] CONFIGURATIONS DE SITES
│   │                           # * C'EST ICI QUE VOUS CRÉEZ VOS SITES !
│   │                           # Structure propre à Homebrew
│   │                           # Similaire à conf.d/ de CentOS
│   │                           # Tous les fichiers ici sont chargés
│   │
│   ├── default.conf            # [WEB] Site par défaut (si créé)
│   ├── monsite.local.conf      # <- Créez vos sites ici
│   ├── api.local.conf          # <- Un fichier .conf par site
│   └── projet.test.conf        # <- Convention : utilisez .local ou .test
│                               # 
│                               # [IDEE] Sur Mac, pas de sites-available/enabled
│                               # Tout fichier ici est actif automatiquement
│
└── snippets/                   # [MODULE] MORCEAUX RÉUTILISABLES (optionnel)
    │                           # Créez ce dossier si besoin
    ├── ssl-params.conf         # Paramètres SSL réutilisables
    └── php-fpm.conf            # Config PHP-FPM


/usr/local/var/www/             # [WEB] RACINE WEB PAR DÉFAUT (Intel Mac)
│                               # ou /opt/homebrew/var/www/ (Apple Silicon)
│                               # Équivalent de /var/www/html (Linux)
│                               # C'est ICI que vont vos fichiers web
│
├── index.html                  # [ACCUEIL] Page d'accueil par défaut
└── 50x.html                    # Page d'erreur serveur


/usr/local/var/log/nginx/       # [GRAPHIQUE] LOGS - Fichiers journaux (Intel)
│                               # ou /opt/homebrew/var/log/nginx/ (Apple Silicon)
│
├── access.log                  # [NOTE] LOG D'ACCÈS - Toutes les requêtes
│                               # Qui visite ? Quand ? Quelle page ?
│                               # Format : IP | Date | Méthode | URL | Code
│                               # Exemple : 127.0.0.1 [17/Nov/2025:10:30:15] 
│                               #          "GET /api/users HTTP/1.1" 200
│
└── error.log                   # [X] LOG D'ERREURS - Problèmes rencontrés
                                # Erreurs 404, 500, problèmes de config
                                # [ATTENTION] PREMIER ENDROIT À VÉRIFIER en cas de bug
                                # Utilisez : tail -f error.log (suivi temps réel)


/usr/local/Cellar/nginx/        # [PACKAGE] INSTALLATION NGINX (Intel Mac)
│                               # ou /opt/homebrew/Cellar/nginx/ (Apple Silicon)
│                               # Binaires et fichiers d'installation Homebrew
│                               # [ATTENTION] NE PAS MODIFIER - Géré par Homebrew
│
└── 1.25.3/                     # Version installée (exemple)
    ├── bin/nginx               # Exécutable Nginx
    ├── html/                   # Fichiers HTML par défaut
    └── ...


/usr/local/opt/nginx/           # [LIEN] LIEN SYMBOLIQUE (Intel Mac)
│                               # ou /opt/homebrew/opt/nginx/ (Apple Silicon)
│                               # Pointe toujours vers la version active
│                               # Pratique pour les scripts


~/Library/LaunchAgents/         # [RAPIDE] DÉMARRAGE AUTOMATIQUE (optionnel)
└── homebrew.mxcl.nginx.plist   # Fichier LaunchAgent pour démarrage auto
                                # Créé par : brew services start nginx


# ═══════════════════════════════════════════════════════════
# [ITEM] SPÉCIFICITÉS macOS
# ═══════════════════════════════════════════════════════════

CHEMINS SELON ARCHITECTURE :
────────────────────────────────────────────────────────────
Intel Mac (x86_64)           Apple Silicon (M1/M2/M3/M4)
─────────────────────────────────────────────────────────────
/usr/local/etc/nginx/     ->  /opt/homebrew/etc/nginx/
/usr/local/var/www/       ->  /opt/homebrew/var/www/
/usr/local/var/log/nginx/ ->  /opt/homebrew/var/log/nginx/
/usr/local/bin/nginx      ->  /opt/homebrew/bin/nginx


# ═══════════════════════════════════════════════════════════
# [CLE] DIFFÉRENCES CLÉS : macOS vs Linux
# ═══════════════════════════════════════════════════════════

LINUX                           macOS (HOMEBREW)
─────────────────────────────────────────────────────────────
/etc/nginx/                  ->  /usr/local/etc/nginx/
/var/www/html/               ->  /usr/local/var/www/
/var/log/nginx/              ->  /usr/local/var/log/nginx/
systemctl start nginx        ->  brew services start nginx
systemctl reload nginx       ->  nginx -s reload
Démarre avec systemd         ->  Démarre avec LaunchAgent


# ═══════════════════════════════════════════════════════════
# [NOTE] WORKFLOW TYPIQUE SUR macOS
# ═══════════════════════════════════════════════════════════

1⃣ Vérifier votre architecture :
   uname -m
   # x86_64 = Intel | arm64 = Apple Silicon

2⃣ Créer une config de site :
   # Intel :
   nano /usr/local/etc/nginx/servers/monsite.local.conf
   
   # Apple Silicon :
   nano /opt/homebrew/etc/nginx/servers/monsite.local.conf

3⃣ Exemple de config simple :
   server {
       listen 8080;
       server_name monsite.local;
       root /usr/local/var/www/monsite;  # Intel
       # root /opt/homebrew/var/www/monsite;  # Apple Silicon
       
       location / {
           index index.html;
       }
   }

4⃣ Tester la config :
   nginx -t

5⃣ Démarrer/Redémarrer Nginx :
   # Première fois :
   brew services start nginx
   
   # Recharger après modifications :
   nginx -s reload
   
   # Ou redémarrage complet :
   brew services restart nginx

6⃣ Vérifier le statut :
   brew services list | grep nginx

7⃣ Voir les logs en temps réel :
   # Accès :
   tail -f /usr/local/var/log/nginx/access.log  # Intel
   tail -f /opt/homebrew/var/log/nginx/access.log  # Apple Silicon
   
   # Erreurs :
   tail -f /usr/local/var/log/nginx/error.log  # Intel
   tail -f /opt/homebrew/var/log/nginx/error.log  # Apple Silicon

8⃣ Arrêter Nginx :
   brew services stop nginx
   # ou
   nginx -s stop


# ═══════════════════════════════════════════════════════════
# [IDEE] ASTUCES macOS
# ═══════════════════════════════════════════════════════════

[OK] Utiliser .local ou .test pour vos domaines de dev
   Exemple : monsite.local, api.test
   
[OK] Ajouter à /etc/hosts pour accès par nom de domaine :
   sudo nano /etc/hosts
   127.0.0.1  monsite.local
   127.0.0.1  api.test

[OK] Port 80 nécessite sudo (privilèges root)
   [IDEE] Utilisez 8080, 8000, ou 3000 pour éviter sudo

[OK] Commandes pratiques :
   nginx -v              # Version
   nginx -t              # Tester la config
   nginx -s reload       # Recharger
   nginx -s stop         # Arrêter
   nginx -s quit         # Arrêt gracieux

[OK] Mettre à jour Nginx :
   brew update
   brew upgrade nginx

[OK] Voir la config active :
   nginx -T              # Dump complet de la config

[ATTENTION]  Port 80/443 bloqués ? Utilisez 8080/8443
    Pas de systemd sur Mac = pas de gestion privilèges facile

[IDEE] Alternative : utilisez Caddy au lieu de Nginx sur Mac
    brew install caddy
    Plus simple pour le développement local


# ═══════════════════════════════════════════════════════════
# [OUTIL] COMMANDES BREW UTILES
# ═══════════════════════════════════════════════════════════

brew install nginx              # Installer Nginx
brew services start nginx       # Démarrer (auto au boot)
brew services stop nginx        # Arrêter
brew services restart nginx     # Redémarrer
brew services list              # Lister tous les services
brew upgrade nginx              # Mettre à jour Nginx
brew uninstall nginx            # Désinstaller
brew info nginx                 # Infos sur l'installation


# ═══════════════════════════════════════════════════════════
# [BUG] DÉPANNAGE macOS
# ═══════════════════════════════════════════════════════════

[X] "Address already in use" ?
   -> Un autre service utilise le port
   lsof -i :8080                # Voir qui utilise le port
   kill -9 <PID>                # Tuer le processus

[X] Permission denied sur port 80 ?
   -> Utilisez sudo ou changez pour port 8080

[X] Nginx ne démarre pas ?
   -> Vérifiez les logs :
   cat /usr/local/var/log/nginx/error.log

[X] Config non trouvée ?
   -> Vérifiez votre architecture :
   ls /usr/local/etc/nginx/     # Intel
   ls /opt/homebrew/etc/nginx/  # Apple Silicon

[X] brew services ne fonctionne pas ?
   -> Lancez manuellement :
   nginx
   # Arrêt :
   nginx -s stop


# === FICHIER nginx.conf EXPLIQUÉ LIGNE PAR LIGNE ===

# /etc/nginx/nginx.conf

user www-data;                  # Utilisateur qui exécute Nginx
                                # www-data = utilisateur système sans privilèges
                                # Pour la sécurité (si Nginx est hacké)

worker_processes auto;          # Nombre de processus workers
                                # auto = 1 par CPU (optimal)
                                # 4 CPUs = 4 workers

pid /run/nginx.pid;             # Fichier contenant le PID (Process ID)
                                # Utilisé par systemctl pour gérer Nginx

events {                        # [RAPIDE] BLOC ÉVÉNEMENTS
    worker_connections 768;     # Connexions par worker
                                # 4 workers × 768 = 3072 connexions simultanées
                                # Pour site moyen c'est largement suffisant
}

http {                          # [WEB] BLOC HTTP (Toute la config web ici)
    
    # === PARAMÈTRES DE BASE ===
    
    sendfile on;                # Optimisation: envoi rapide de fichiers
                                # Activez TOUJOURS (sauf debug)
    
    tcp_nopush on;              # Optimisation TCP
    tcp_nodelay on;             # Désactive algorithme de Nagle
                                # Ces deux = meilleure performance
    
    keepalive_timeout 65;       # Garde connexion ouverte 65 secondes
                                # Évite de rouvrir connexion à chaque requête
    
    types_hash_max_size 2048;   # Taille table hash types MIME
                                # Valeur par défaut OK
    
    include /etc/nginx/mime.types;      # Inclut définitions types fichiers
    default_type application/octet-stream;  # Type par défaut si inconnu
    
    # === LOGS ===
    
    access_log /var/log/nginx/access.log;   # Où écrire log accès
    error_log /var/log/nginx/error.log;     # Où écrire log erreurs
    
    # === COMPRESSION GZIP ===
    
    gzip on;                    # Active compression (IMPORTANT!)
                                # Réduit taille fichiers envoyés
                                # Site plus rapide !
    
    # === INCLURE VOS SITES ===
    
    include /etc/nginx/conf.d/*.conf;           # Inclut tous .conf de conf.d/
    include /etc/nginx/sites-enabled/*;         # Inclut sites actifs
                                                # C'est ici que vos sites sont chargés !
}

# FIN du fichier nginx.conf

# === FICHIER nginx.conf EXPLIQUÉ LIGNE PAR LIGNE Plus En Détail ===

# /etc/nginx/nginx.conf
# [FICHIER] FICHIER DE CONFIGURATION PRINCIPAL DE NGINX
# Ce fichier contrôle le comportement global du serveur

# ═══════════════════════════════════════════════════════════
# [UTILISATEUR] UTILISATEUR ET SÉCURITÉ
# ═══════════════════════════════════════════════════════════

user www-data;                  # [UTILISATEUR] Utilisateur qui exécute Nginx
                                # www-data = compte système sans privilèges
                                # [VERROUILLE] SÉCURITÉ : Si Nginx est compromis,
                                #    l'attaquant n'a que les droits de www-data
                                #    (pas root = pas accès système complet)
                                # 
                                # VARIATIONS selon OS :
                                # - Ubuntu/Debian : www-data
                                # - CentOS/RHEL : nginx
                                # - macOS : _www ou votre_nom_utilisateur
                                #
                                # [ATTENTION] NE JAMAIS mettre "user root;" (danger!)


# ═══════════════════════════════════════════════════════════
# [CONFIG] PROCESSUS WORKERS (Gestion multi-cœurs)
# ═══════════════════════════════════════════════════════════

worker_processes auto;          # [NOMBRE] Nombre de processus workers
                                # 
                                # Workers = "employés" qui traitent les requêtes
                                # Nginx Master -> Worker 1, Worker 2, Worker 3...
                                # 
                                # auto = 1 worker par cœur CPU (RECOMMANDÉ)
                                # Exemples :
                                # - 2 cœurs CPU -> 2 workers
                                # - 4 cœurs CPU -> 4 workers
                                # - 8 cœurs CPU -> 8 workers
                                # 
                                # Valeur manuelle possible :
                                # worker_processes 4;  # Force 4 workers
                                # 
                                # [IDEE] RÈGLE : Laissez "auto" sauf cas avancé


pid /run/nginx.pid;             # [NOTE] Fichier PID (Process ID)
                                # Stocke le numéro du processus master Nginx
                                # Exemple contenu : 1234
                                # 
                                # Utilisé par :
                                # - systemctl start/stop/restart nginx
                                # - Scripts de monitoring
                                # - Commandes : kill, nginx -s reload
                                # 
                                # Autres chemins possibles :
                                # /var/run/nginx.pid  (CentOS)
                                # /usr/local/var/run/nginx.pid  (macOS)


include /etc/nginx/modules-enabled/*.conf;  
                                # [PLUGIN] Charge les modules dynamiques
                                # Modules = extensions Nginx
                                # Ex: ngx_http_image_filter_module
                                # Présent sur Ubuntu/Debian uniquement


# ═══════════════════════════════════════════════════════════
# [RAPIDE] BLOC EVENTS - Gestion des connexions
# ═══════════════════════════════════════════════════════════

events {
    # Ce bloc contrôle comment Nginx gère les connexions
    
    worker_connections 768;     # [LIEN] Connexions max par worker
                                # 
                                # Calcul capacité totale :
                                # workers × connections = capacité max
                                # 
                                # Exemples :
                                # 4 workers × 768 = 3 072 connexions simultanées
                                # 8 workers × 1024 = 8 192 connexions simultanées
                                # 
                                # [IDEE] Pour un site normal : 768 suffit
                                # [IDEE] Site à fort trafic : augmentez à 1024-2048
                                # 
                                # [ATTENTION] Limite système à vérifier :
                                # ulimit -n  (voir "open files")
                                # Si worker_connections > ulimit, erreur!
    
    # Autres paramètres possibles (avancé) :
    # use epoll;                # Méthode I/O (Linux uniquement)
    # multi_accept on;          # Accepte plusieurs connexions à la fois
}


# ═══════════════════════════════════════════════════════════
# [WEB] BLOC HTTP - Configuration Web (Le plus important!)
# ═══════════════════════════════════════════════════════════

http {
    # [PACKAGE] Tout ce qui concerne les sites web va ici
    # Ce bloc peut contenir des "server" blocs (= vos sites)
    
    
    # ───────────────────────────────────────────────────────
    # [FICHIER] TYPES MIME ET FICHIERS
    # ───────────────────────────────────────────────────────
    
    include /etc/nginx/mime.types;  
                                # [LISTE] Inclut la liste des types de fichiers
                                # Dit à Nginx comment interpréter les extensions
                                # 
                                # Exemples dans mime.types :
                                # .html -> text/html
                                # .css  -> text/css
                                # .js   -> application/javascript
                                # .jpg  -> image/jpeg
                                # .pdf  -> application/pdf
                                # 
                                # Le navigateur sait ainsi comment afficher
    
    default_type application/octet-stream;  
                                # [OUTIL] Type MIME par défaut
                                # Pour fichiers sans extension reconnue
                                # octet-stream = fichier binaire à télécharger
                                # Le navigateur propose de télécharger
    
    
    # ───────────────────────────────────────────────────────
    # [GRAPHIQUE] LOGS - Enregistrement des activités
    # ───────────────────────────────────────────────────────
    
    # FORMAT DES LOGS (optionnel, souvent commenté)
    log_format main '$remote_addr - $remote_user [$time_local] '
                    '"$request" $status $body_bytes_sent '
                    '"$http_referer" "$http_user_agent"';
                                # Définit le format d'enregistrement
                                # Variables expliquées :
                                # $remote_addr = IP du visiteur
                                # $remote_user = Utilisateur authentifié
                                # $time_local = Date/heure de la requête
                                # $request = Requête HTTP (GET /page.html)
                                # $status = Code HTTP (200, 404, 500...)
                                # $body_bytes_sent = Taille réponse
                                # $http_referer = Page d'origine
                                # $http_user_agent = Navigateur
    
    access_log /var/log/nginx/access.log;   
                                # [NOTE] LOG D'ACCÈS
                                # Enregistre TOUTES les requêtes
                                # 
                                # Exemple de ligne :
                                # 192.168.1.10 - - [17/Nov/2025:14:30:15 +0000] 
                                # "GET /index.html HTTP/1.1" 200 612 
                                # "-" "Mozilla/5.0..."
                                # 
                                # Utile pour :
                                # - Statistiques de trafic
                                # - Analyser comportement visiteurs
                                # - Détecter bots/scrapers
                                # 
                                # Commandes utiles :
                                # tail -f access.log  (suivi temps réel)
                                # grep "404" access.log  (trouver erreurs)
    
    error_log /var/log/nginx/error.log;     
                                # [X] LOG D'ERREURS
                                # Enregistre les problèmes
                                # 
                                # Types d'erreurs :
                                # - Erreurs de config
                                # - Fichiers non trouvés (404)
                                # - Erreurs PHP/FastCGI
                                # - Dépassement limites
                                # - Problèmes SSL
                                # 
                                # Niveaux possibles :
                                # error_log /path/to/log debug;   # Très verbeux
                                # error_log /path/to/log info;    # Informatif
                                # error_log /path/to/log notice;  # Avertissements
                                # error_log /path/to/log warn;    # Alertes
                                # error_log /path/to/log error;   # Erreurs (défaut)
                                # error_log /path/to/log crit;    # Critique
                                # 
                                # [RECHERCHE] PREMIER ENDROIT À CONSULTER en cas de bug !
    
    
    # ───────────────────────────────────────────────────────
    # [RAPIDE] OPTIMISATIONS DE PERFORMANCE
    # ───────────────────────────────────────────────────────
    
    sendfile on;                # [RAPIDE] Active sendfile() (IMPORTANT!)
                                # 
                                # Fonctionnement :
                                # OFF : Disque -> Nginx -> Kernel -> Réseau (lent)
                                # ON  : Disque -> Kernel -> Réseau (rapide)
                                # 
                                # Nginx transfère fichiers directement
                                # sans passer par son espace mémoire
                                # 
                                # [IDEE] TOUJOURS activé sauf debug
                                # Gain de performance majeur !
    
    tcp_nopush on;              # [PACKAGE] Optimisation paquets TCP
                                # Envoie headers HTTP + début fichier
                                # dans le même paquet TCP
                                # 
                                # Réduit le nombre de paquets réseau
                                # [ATTENTION] Fonctionne SEULEMENT si sendfile on
                                # 
                                # [IDEE] Activez toujours avec sendfile
    
    tcp_nodelay on;             # [RAPIDE] Désactive algorithme de Nagle
                                # 
                                # Nagle = regroupe petits paquets (latence)
                                # tcp_nodelay = envoie immédiatement (rapide)
                                # 
                                # Idéal pour :
                                # - Applications temps réel
                                # - WebSockets
                                # - APIs réactives
                                # 
                                # [IDEE] Activez pour sites modernes
    
    keepalive_timeout 65;       # [TEMPS] Durée connexion persistante (secondes)
                                # 
                                # HTTP Keep-Alive : garde connexion ouverte
                                # Évite de recréer connexion TCP pour chaque
                                # ressource (HTML, CSS, JS, images...)
                                # 
                                # Exemple avec 1 page + 10 ressources :
                                # OFF : 11 connexions TCP (lent)
                                # ON  : 1 connexion réutilisée (rapide)
                                # 
                                # 65 secondes = bon compromis
                                # Trop court : reconnexions fréquentes
                                # Trop long : connexions inutiles ouvertes
                                # 
                                # Valeurs courantes : 30-75 secondes
    
    types_hash_max_size 2048;   # [DOSSIER] Taille table hash types MIME
                                # Table interne pour mime.types
                                # 2048 = valeur par défaut (OK)
                                # Augmentez si vous avez 100+ types perso
    
    # server_tokens off;        # [VERROUILLE] Cache la version Nginx
                                # OFF : Headers -> "Server: nginx"
                                # ON  : Headers -> "Server: nginx/1.25.3"
                                # 
                                # [IDEE] SÉCURITÉ : Activez en production
                                # Empêche attaquants de connaître version
                                # (exploits ciblés plus difficiles)
    
    # server_names_hash_bucket_size 64;  
                                # [BUCKET] Taille bucket pour noms serveurs
                                # Si vous avez beaucoup de server_name longs
                                # Augmentez si erreur au démarrage
    
    # server_name_in_redirect off;  
                                # Utilise $host au lieu du server_name
                                # dans les redirections
    
    
    # ───────────────────────────────────────────────────────
    # [COMPRESSION] COMPRESSION GZIP (Gain de vitesse énorme!)
    # ───────────────────────────────────────────────────────
    
    gzip on;                    # [OK] Active compression GZIP
                                # 
                                # AVANT : index.html = 50 Ko -> Réseau
                                # APRÈS : index.html = 50 Ko -> 10 Ko -> Réseau
                                # 
                                # Gain typique : 60-80% de réduction
                                # Site 5× plus rapide !
                                # 
                                # [IDEE] TOUJOURS activé (sauf cas très spécifiques)
    
    # Configuration GZIP avancée (à ajouter si besoin) :
    
    # gzip_vary on;             # Ajoute header "Vary: Accept-Encoding"
                                # Dit aux proxies/CDN de gérer versions
                                # compressées et non-compressées
    
    # gzip_proxied any;         # Compresse même pour proxies
                                # "any" = toujours compresser
    
    # gzip_comp_level 6;        # Niveau compression (1-9)
                                # 1 = rapide, peu de compression
                                # 6 = bon compromis (RECOMMANDÉ)
                                # 9 = max compression, CPU++
                                # 
                                # [IDEE] 6 = meilleur ratio vitesse/compression
    
    # gzip_buffers 16 8k;       # Mémoire pour compression
                                # 16 buffers de 8ko chacun
    
    # gzip_http_version 1.1;    # Version HTTP minimum
    
    # gzip_types text/plain text/css application/json 
    #            application/javascript text/xml 
    #            application/xml application/xml+rss 
    #            text/javascript image/svg+xml;
                                # [FICHIER] Types de fichiers à compresser
                                # 
                                # HTML compressé par défaut (pas besoin text/html)
                                # 
                                # À compresser :
                                # [OK] CSS, JS, JSON, XML, SVG, TXT
                                # [OK] Polices WOFF (si non compressées)
                                # 
                                # À NE PAS compresser :
                                # [X] Images JPG/PNG (déjà compressées)
                                # [X] Vidéos MP4 (déjà compressées)
                                # [X] Archives ZIP/GZ (déjà compressées)
                                # -> Perte CPU pour rien !
    
    # gzip_disable "msie6";     # Désactive pour IE6 (buggé avec GZIP)
                                # Obsolète aujourd'hui (IE6 = 2006)
    
    
    # ───────────────────────────────────────────────────────
    # [SORTIE] UPLOAD DE FICHIERS
    # ───────────────────────────────────────────────────────
    
    # client_max_body_size 20M; # [SORTIE] Taille max upload (POST/PUT)
                                # Par défaut : 1M (1 Mo)
                                # 
                                # Augmentez pour :
                                # - Uploads images/vidéos
                                # - Formulaires avec fichiers
                                # - APIs recevant gros JSON
                                # 
                                # Exemples :
                                # 10M = 10 mégaoctets
                                # 100M = 100 mégaoctets
                                # 0 = illimité (déconseillé)
                                # 
                                # [ATTENTION] Doit être ≥ taille max fichier attendue
                                # Erreur si dépassé : 413 Request Entity Too Large
    
    
    # ───────────────────────────────────────────────────────
    # [SECURISE] SSL/TLS (HTTPS)
    # ───────────────────────────────────────────────────────
    
    # Généralement configuré dans les blocs "server"
    # mais peut être défini globalement ici :
    
    # ssl_protocols TLSv1.2 TLSv1.3;  
                                # [VERROUILLE] Versions SSL/TLS autorisées
                                # TLSv1.2 = minimum recommandé
                                # TLSv1.3 = dernière version (plus rapide)
                                # 
                                # [ATTENTION] NE PAS autoriser SSLv3, TLSv1, TLSv1.1
                                # (vulnérabilités connues)
    
    # ssl_prefer_server_ciphers on;  
                                # Serveur choisit l'algorithme de chiffrement
                                # (pas le client)
    
    # ssl_ciphers 'ECDHE-RSA-AES128-GCM-SHA256:...';  
                                # Liste des algorithmes autorisés
                                # Complexe, utilisez générateurs :
                                # https://ssl-config.mozilla.org/
    
    
    # ───────────────────────────────────────────────────────
    # [DOSSIER] INCLUSIONS - Charger vos sites
    # ───────────────────────────────────────────────────────
    
    # UBUNTU/DEBIAN :
    include /etc/nginx/conf.d/*.conf;       
                                # Charge tous les .conf de conf.d/
                                # Souvent vide sur Ubuntu (utilise sites-enabled)
    
    include /etc/nginx/sites-enabled/*;     
                                # * Charge vos sites actifs
                                # Sites = liens symboliques depuis sites-available
                                # 
                                # C'EST ICI que vos configurations de sites
                                # (blocs "server") sont chargées !
    
    # CENTOS/RHEL :
    # include /etc/nginx/conf.d/*.conf;
                                # Charge tous les .conf
                                # Sur CentOS, pas de sites-available/enabled
                                # Créez directement vos sites dans conf.d/
    
    # macOS (HOMEBREW) :
    # include /usr/local/etc/nginx/servers/*;     # Intel
    # include /opt/homebrew/etc/nginx/servers/*;  # Apple Silicon
}

# ═══════════════════════════════════════════════════════════
# [EMAIL] BLOC MAIL (optionnel - rare)
# ═══════════════════════════════════════════════════════════

# Nginx peut aussi être proxy mail (SMTP/IMAP/POP3)
# Rarement utilisé, nécessite module mail
# Commenté par défaut

# mail {
#     server {
#         listen     25;
#         protocol   smtp;
#         proxy      on;
#     }
# }


# ═══════════════════════════════════════════════════════════
# [OBJECTIF] RÉSUMÉ DE LA HIÉRARCHIE
# ═══════════════════════════════════════════════════════════

# nginx.conf (global)
# │
# ├── user, worker_processes, pid  (processus)
# │
# ├── events { }                   (connexions)
# │
# └── http {                       (web)
#     │
#     ├── Paramètres globaux       (logs, gzip, mime...)
#     │
#     ├── include conf.d/*.conf    (configs additionnelles)
#     │
#     └── include sites-enabled/*  (VOS SITES)
#         │
#         └── server {             (un site)
#             │
#             ├── listen 80;
#             ├── server_name example.com;
#             ├── root /var/www/html;
#             │
#             └── location / { }   (routes)
#         }


# ═══════════════════════════════════════════════════════════
# [OUTILS] COMMANDES UTILES
# ═══════════════════════════════════════════════════════════

# Tester la configuration :
# nginx -t

# Recharger sans couper connexions :
# systemctl reload nginx       (Linux)
# nginx -s reload              (macOS)

# Redémarrer complètement :
# systemctl restart nginx

# Voir config complète réelle :
# nginx -T

# Vérifier version :
# nginx -v
# nginx -V  (avec modules compilés)


# ═══════════════════════════════════════════════════════════
# [ATTENTION] ERREURS COURANTES
# ═══════════════════════════════════════════════════════════

# [X] worker_connections trop élevé :
# [emerg] worker_connections exceed open file resource limit
# -> Solution : augmenter ulimit -n

# [X] Port 80 déjà utilisé :
# [emerg] bind() to 0.0.0.0:80 failed (98: Address already in use)
# -> Solution : vérifier avec lsof -i :80

# [X] Syntaxe incorrecte :
# [emerg] unexpected "}" in /etc/nginx/nginx.conf:45
# -> Solution : nginx -t pour localiser l'erreur

# [X] Permission denied :
# [crit] open() "/var/log/nginx/access.log" failed (13: Permission denied)
# -> Solution : chown www-data:www-data ou chmod 644

# FIN du fichier nginx.conf


# === COMMANDES UTILES POUR EXPLORER ===

# Voir la structure complète
tree /etc/nginx/
# (Installer tree: sudo apt install tree)

# Ou sans tree:
ls -lR /etc/nginx/

# Lister les sites disponibles
ls -l /etc/nginx/sites-available/

# Lister les sites actifs
ls -l /etc/nginx/sites-enabled/

# Voir le contenu de nginx.conf
cat /etc/nginx/nginx.conf

# Éditer nginx.conf (ATTENTION!)
sudo nano /etc/nginx/nginx.conf

# Voir les logs en temps réel
sudo tail -f /var/log/nginx/access.log
sudo tail -f /var/log/nginx/error.log


# === OÙ METTRE VOS FICHIERS WEB ? ===

# Convention standard:
/var/www/                       # Racine de tous les sites
├── site1.com/                  # Un dossier par site
│   ├── html/                   # Fichiers publics
│   │   ├── index.html
│   │   ├── style.css
│   │   └── images/
│   └── logs/                   # Logs spécifiques (optionnel)
├── site2.com/
│   └── html/
└── api.example.com/
    └── html/

# Créer structure pour nouveau site:
sudo mkdir -p /var/www/monsite.com/html
sudo chown -R $USER:$USER /var/www/monsite.com/html
sudo chmod -R 755 /var/www/monsite.com

# Créer page test:
echo "<h1>Bienvenue sur monsite.com !</h1>" > /var/www/monsite.com/html/index.html


# === PERMISSIONS - IMPORTANT ! ===

# Nginx doit pouvoir LIRE vos fichiers
# Mais PAS les modifier (sécurité)

# Propriétaire: votre user (pour que vous puissiez modifier)
# Groupe: www-data (pour que Nginx puisse lire)
# Permissions: 755 pour dossiers, 644 pour fichiers

# Fixer permissions:
sudo chown -R $USER:www-data /var/www/monsite.com/
sudo find /var/www/monsite.com/ -type d -exec chmod 755 {} \;
sudo find /var/www/monsite.com/ -type f -exec chmod 644 {} \;

# Explication:
# chown = change owner (propriétaire)
# -R = récursif (tous sous-dossiers)
# chmod 755 = rwxr-xr-x (owner peut tout, autres peuvent lire/exécuter)
# chmod 644 = rw-r--r-- (owner peut lire/écrire, autres juste lire)


# === RÉSUMÉ POUR DÉBUTANT ===

# Fichiers à connaître:
# /etc/nginx/nginx.conf          -> Config globale (rarement modifié)
# /etc/nginx/sites-available/    -> Créer vos sites ICI
# /etc/nginx/sites-enabled/      -> Activer sites avec ln -s
# /var/www/                      -> Vos fichiers HTML/CSS/JS ICI
# /var/log/nginx/                -> Logs pour débugger

# Workflow typique:
# 1. Créer config dans sites-available/
# 2. Créer lien dans sites-enabled/
# 3. Mettre fichiers web dans /var/www/
# 4. Tester avec nginx -t
# 5. Recharger avec systemctl reload nginx


[OK] CONFIGURATION DE BASE - VOTRE PREMIER SITE WEB

# === COMPRENDRE LA STRUCTURE D'UN BLOC SERVER ===

# Un bloc "server" = configuration pour UN site web
# C'est comme une fiche d'identité du site:
# - Sur quel port écouter ?
# - Quel nom de domaine ?
# - Où sont les fichiers ?
# - Que faire selon l'URL demandée ?


# === CONFIGURATION MINIMALE (Le plus simple possible) ===

# Créer le fichier:
sudo nano /etc/nginx/sites-available/monsite

# Contenu minimal:
server {
    listen 80;                  # [PLUGIN] Écouter sur le port 80 (HTTP standard)
                                # Comme un téléphone qui écoute sur un numéro
    
    server_name example.com;    # [NAME_BADGE] Nom de domaine de votre site
                                # Nginx regarde le Host dans la requête HTTP
    
    root /var/www/example;      # [DOSSIER] Où sont vos fichiers HTML/CSS/JS
                                # Nginx cherchera les fichiers ici
    
    index index.html;           # [FICHIER] Fichier par défaut
                                # Si on visite example.com/, Nginx sert index.html
    
    location / {                # [IMPORTANT] Règle pour TOUTES les URLs (/)
        try_files $uri $uri/ =404;  
        # Explication try_files:
        # 1. Essaie de trouver le fichier exact ($uri)
        # 2. Sinon, essaie comme dossier ($uri/)
        # 3. Sinon, retourne erreur 404
        
        # Exemple: Visite de example.com/about.html
        # 1. Cherche /var/www/example/about.html -> existe ? [OK] sert le fichier
        # 2. Sinon cherche /var/www/example/about/ -> existe ? sert index.html du dossier
        # 3. Sinon -> 404 Not Found
    }
}

# Sauvegarder: Ctrl+O puis Entrée, Quitter: Ctrl+X

# Activer le site:
sudo ln -s /etc/nginx/sites-available/monsite /etc/nginx/sites-enabled/

# Tester:
sudo nginx -t

# Recharger:
sudo systemctl reload nginx


# === CONFIGURATION COMPLÈTE EXPLIQUÉE ===

server {
    # === PORTS D'ÉCOUTE ===
    
    listen 80;                          # IPv4 sur port 80
    listen [::]:80;                     # IPv6 sur port 80
                                        # [::] = notation IPv6
    
    # === NOM DE DOMAINE ===
    
    server_name example.com www.example.com;
    # Accepte plusieurs noms séparés par des espaces
    # Nginx compare avec le header "Host" de la requête
    # Si aucun match -> va vers le serveur "default"
    
    # Exemples de server_name:
    # server_name example.com;              # Un seul domaine
    # server_name example.com www.example.com;  # Avec et sans www
    # server_name *.example.com;            # Tous sous-domaines (wildcard)
    # server_name ~^(.+)\.example\.com$;    # Regex pour sous-domaines
    
    # === RACINE WEB ===
    
    root /var/www/monsite;              # Dossier racine
    # IMPORTANT: Ce chemin doit exister !
    # Créez-le avec: sudo mkdir -p /var/www/monsite
    
    index index.html index.htm;         # Fichiers index dans l'ordre
    # Si index.html n'existe pas, essaie index.htm
    # Puis index.php si configuré, etc.
    
    # === LOGS SPÉCIFIQUES ===
    
    access_log /var/log/nginx/monsite_access.log;
    error_log /var/log/nginx/monsite_error.log;
    # Logs séparés par site = plus facile à analyser
    # Optionnel: si omis, utilise les logs par défaut
    
    # === RÈGLE POUR TOUTES LES URLS ===
    
    location / {
        try_files $uri $uri/ =404;
    }
}


# === EXEMPLE PRATIQUE COMPLET ===

# Objectif: Créer un site portfolio sur monportfolio.com

# Étape 1: Créer la structure de fichiers
sudo mkdir -p /var/www/monportfolio.com/html
sudo chown -R $USER:$USER /var/www/monportfolio.com/html

# Étape 2: Créer une page d'accueil simple
cat > /var/www/monportfolio.com/html/index.html << 'EOF'
<!DOCTYPE html>
<html lang="fr">
<head>
    <meta charset="UTF-8">
    <title>Mon Portfolio</title>
    <style>
        body {
            font-family: Arial, sans-serif;
            max-width: 800px;
            margin: 50px auto;
            padding: 20px;
        }
        h1 { color: #333; }
    </style>
</head>
<body>
    <h1>Bienvenue sur mon portfolio !</h1>
    <p>Ceci est ma première page servie par Nginx.</p>
    <img src="/images/photo.jpg" alt="Ma photo">
</body>
</html>
EOF

# Étape 3: Créer dossier images
mkdir /var/www/monportfolio.com/html/images
# (Mettez vos images dedans)

# Étape 4: Créer configuration Nginx
sudo nano /etc/nginx/sites-available/monportfolio.com

# Contenu:
server {
    listen 80;
    listen [::]:80;
    
    server_name monportfolio.com www.monportfolio.com;
    
    root /var/www/monportfolio.com/html;
    index index.html;
    
    # Logs spécifiques
    access_log /var/log/nginx/portfolio_access.log;
    error_log /var/log/nginx/portfolio_error.log;
    
    # Règle principale
    location / {
        try_files $uri $uri/ =404;
    }
    
    # Pas de logs pour favicon (évite pollution logs)
    location = /favicon.ico {
        log_not_found off;      # Ne pas logger si absent
        access_log off;         # Ne pas logger les accès
    }
    
    # Idem pour robots.txt
    location = /robots.txt {
        log_not_found off;
        access_log off;
    }
}

# Étape 5: Activer le site
sudo ln -s /etc/nginx/sites-available/monportfolio.com /etc/nginx/sites-enabled/

# Étape 6: Tester et recharger
sudo nginx -t
sudo systemctl reload nginx

# Étape 7: Tester dans le navigateur
# http://monportfolio.com (ou http://localhost si test local)


# === PLUSIEURS EMPLACEMENTS (location) DANS UN SITE ===

server {
    listen 80;
    server_name example.com;
    root /var/www/example;
    
    # === EMPLACEMENT 1: Page d'accueil ===
    location / {
        index index.html;
        try_files $uri $uri/ =404;
    }
    # Gère: example.com/, example.com/page.html, etc.
    
    # === EMPLACEMENT 2: Dossier images avec listing ===
    location /images/ {
        root /var/www/example;  # Devient /var/www/example/images/
        autoindex on;           # Active liste des fichiers
                                # Comme un explorateur de fichiers
        autoindex_exact_size off;   # Taille lisible (10KB au lieu de 10240)
        autoindex_localtime on;     # Heure locale
    }
    # Accès: example.com/images/
    # Affiche la liste de toutes les images
    
    # === EMPLACEMENT 3: Zone d'administration protégée ===
    location /admin/ {
        auth_basic "Zone Restreinte";  # Message affiché
        auth_basic_user_file /etc/nginx/.htpasswd;  # Fichier mot de passe
        
        # Créer le fichier .htpasswd:
        # sudo apt install apache2-utils
        # sudo htpasswd -c /etc/nginx/.htpasswd admin
        # (demande de créer un mot de passe)
    }
    # Accès: example.com/admin/
    # Demande login/password avant d'entrer
    
    # === EMPLACEMENT 4: Fichiers statiques avec cache navigateur ===
    location ~* \.(jpg|jpeg|png|gif|ico|css|js)$ {
        # ~* = regex insensible à la casse
        # Matche: .jpg, .JPG, .Jpg, etc.
        
        expires 1y;             # Cache navigateur 1 an
                                # Le navigateur ne redemande pas le fichier
        add_header Cache-Control "public, immutable";
        # public = peut être caché par proxy
        # immutable = ne changera jamais (ne pas revérifier)
        
        access_log off;         # Pas de log (fichiers statiques)
    }
    # Ces fichiers sont chargés UNE SEULE FOIS
    # Puis réutilisés du cache navigateur
    # = Site BEAUCOUP plus rapide !
    
    # === EMPLACEMENT 5: API backend (voir section Reverse Proxy) ===
    location /api/ {
        proxy_pass http://localhost:3000;  # Vers app Node.js
        proxy_set_header Host $host;
    }
}


# === COMPRENDRE LES VARIABLES NGINX ===

# Nginx fournit des variables automatiques très utiles
# Format: $nom_variable

# Variables les plus courantes:

$uri                    # URI demandée (sans query string)
                        # Exemple: /about.html

$request_uri           # URI complète avec query string
                        # Exemple: /search?q=nginx

$host                   # Nom de domaine (depuis Host header)
                        # Exemple: example.com

$remote_addr           # IP du visiteur
                        # Exemple: 192.168.1.100

$scheme                # Protocole (http ou https)
                        # Exemple: https

$request_method        # Méthode HTTP
                        # Exemple: GET, POST, PUT, DELETE

$status                # Code statut de la réponse
                        # Exemple: 200, 404, 500

$body_bytes_sent       # Nombre d'octets envoyés
                        # Exemple: 15234

# Exemple d'utilisation:
location /debug {
    return 200 "URI: $uri\nHost: $host\nIP: $remote_addr\n";
    add_header Content-Type text/plain;
}
# Visitez example.com/debug pour voir les variables


# === TESTER LOCALEMENT (sans nom de domaine) ===

# Méthode 1: Utiliser localhost
server {
    listen 80;
    server_name localhost;      # Marche avec http://localhost
    root /var/www/test;
    location / {
        try_files $uri $uri/ =404;
    }
}

# Méthode 2: Utiliser l'IP du serveur
server {
    listen 80;
    server_name 192.168.1.100;  # Remplacer par votre IP
    # ...
}

# Méthode 3: Modifier /etc/hosts (simulation domaine local)
sudo nano /etc/hosts
# Ajouter:
127.0.0.1   monsite.local

# Puis dans Nginx:
server {
    listen 80;
    server_name monsite.local;
    # ...
}
# Visitez http://monsite.local dans le navigateur


# === DÉSACTIVER UN SITE ===

# Méthode 1: Supprimer le lien symbolique (RECOMMANDÉ)
sudo rm /etc/nginx/sites-enabled/monsite
sudo systemctl reload nginx
# Le fichier dans sites-available reste intact
# Vous pouvez le réactiver plus tard

# Méthode 2: Renommer l'extension
sudo mv /etc/nginx/sites-enabled/monsite /etc/nginx/sites-enabled/monsite.disabled
# Nginx ignore les fichiers sans extension .conf (sur CentOS)

# Méthode 3: Commenter tout le contenu
# Ouvrir le fichier et mettre # devant chaque ligne


# === ERREURS COURANTES DÉBUTANTS ===

# Erreur 1: "403 Forbidden"
# Causes possibles:
# - Mauvaises permissions sur les fichiers
# - Pas de fichier index.html
# - Nginx ne peut pas lire le dossier

# Solutions:
# Vérifier permissions:
ls -la /var/www/monsite/
# Doit être lisible par www-data

# Fixer permissions:
sudo chown -R $USER:www-data /var/www/monsite/
sudo chmod -R 755 /var/www/monsite/

# Vérifier qu'index.html existe:
ls /var/www/monsite/index.html


# Erreur 2: "404 Not Found"
# Causes:
# - Mauvais chemin dans "root"
# - Fichier n'existe pas
# - Typo dans le nom du fichier

# Solution:
# Vérifier le chemin exact:
sudo nginx -T | grep root
# Compare avec:
ls /var/www/monsite/


# Erreur 3: "502 Bad Gateway"
# Cause: Backend (proxy_pass) ne répond pas
# Solution: Vérifier que l'application backend tourne
systemctl status mon-app


# Erreur 4: Site ne se charge pas
# Cause probable: Vous avez oublié de recharger Nginx !
# Solution:
sudo nginx -t
sudo systemctl reload nginx


# === RÉSUMÉ CONFIGURATION DE BASE ===

# Structure minimale d'un site:
server {
    listen 80;
    server_name mon-domaine.com;
    root /var/www/mon-site;
    index index.html;
    
    location / {
        try_files $uri $uri/ =404;
    }
}

# Workflow création site:
# 1. Créer dossier web: mkdir -p /var/www/mon-site
# 2. Mettre fichiers HTML dedans
# 3. Créer config: /etc/nginx/sites-available/mon-site
# 4. Activer: ln -s sites-available/mon-site sites-enabled/
# 5. Tester: nginx -t
# 6. Recharger: systemctl reload nginx
# 7. Visiter dans navigateur

# Commandes essentielles:
sudo nginx -t                    # TOUJOURS tester avant reload
sudo systemctl reload nginx      # Appliquer changements
sudo tail -f /var/log/nginx/error.log  # Voir erreurs en direct


[OK] DIRECTIVES LOCATION - COMPRENDRE LES RÈGLES D'URL

# === QU'EST-CE QU'UNE DIRECTIVE LOCATION ? ===

# Une directive "location" dit à Nginx:
# "Quand quelqu'un demande CETTE URL, fais ÇA"
#
# Analogie: C'est comme un aiguillage de train
# - Train arrive avec un ticket (URL)
# - L'aiguilleur (Nginx) regarde le ticket
# - Et envoie le train sur la bonne voie (location)

# Exemple simple:
location / {
    # Toutes les URLs qui commencent par /
    # Donc: TOUTES les URLs !
}

location /images/ {
    # Seulement les URLs qui commencent par /images/
    # Exemple: /images/photo.jpg [OK]
    # Exemple: /images/vacation/beach.png [OK]
    # Exemple: /documents/file.pdf [X]
}


# === LES 5 TYPES DE LOCATION ===

# 1⃣ CORRESPONDANCE EXACTE (=)
#    Le plus prioritaire, doit être EXACTEMENT l'URL

location = /page.html {
    # Correspond SEULEMENT à /page.html
    # PAS à /page.html?param=value (query string ignorée)
    # PAS à /page.html/
    # PAS à /autre-page.html
    return 200 "Page exacte trouvée!\n";
}

# Cas d'usage: Optimisation
# Si vous avez une page très visitée (comme la page d'accueil),
# utiliser = évite à Nginx de vérifier toutes les autres règles


# 2⃣ PRÉFIXE PRIORITAIRE (^~)
#    Plus prioritaire que les regex, mais moins que =

location ^~ /images/ {
    # Correspond à tout ce qui commence par /images/
    # ET empêche Nginx de vérifier les regex après
    root /var/www;
    # Si fichier dans /var/www/images/, sert directement
    # Sans vérifier d'autres règles
}

# Cas d'usage: Performance
# Pour dossiers de fichiers statiques fréquemment accédés
# Évite de vérifier toutes les règles regex après


# 3⃣ REGEX SENSIBLE À LA CASSE (~)
#    Utilise expressions régulières (regex)

location ~ \.php$ {
    # ~ = regex sensible casse
    # \.php$ = se termine par .php
    # $ = fin de chaîne
    
    # Correspond à:
    # /index.php [OK]
    # /admin/login.php [OK]
    # /API/script.php [OK]
    
    # Ne correspond PAS à:
    # /index.PHP [X] (casse différente)
    # /index.php5 [X] (ne finit pas par .php)
    
    # Traiter avec PHP-FPM
    fastcgi_pass unix:/var/run/php/php8.1-fpm.sock;
}

# Cas d'usage: Fichiers dynamiques
# Pour exécuter PHP, Python, etc. selon l'extension


# 4⃣ REGEX INSENSIBLE À LA CASSE (~*)
#    Comme ~ mais ignore majuscules/minuscules

location ~* \.(jpg|jpeg|png|gif|ico)$ {
    # ~* = regex insensible casse
    # \. = point littéral (échappé)
    # | = OU
    # $ = fin de chaîne
    
    # Correspond à:
    # /image.jpg [OK]
    # /image.JPG [OK] (insensible casse)
    # /image.JpG [OK]
    # /photos/vacation.PNG [OK]
    
    # Ne correspond PAS à:
    # /image.jpg.txt [X] (ne finit pas par jpg)
    
    expires 30d;        # Cache 30 jours
    access_log off;     # Pas de log (optimisation)
}

# Cas d'usage: Fichiers statiques
# Images, CSS, JS avec cache navigateur


# 5⃣ PRÉFIXE NORMAL (pas de modificateur)
#    Le moins prioritaire, match le plus long gagne

location /documents/ {
    # Correspond à tout ce qui commence par /documents/
    root /var/www;
    autoindex on;       # Liste des fichiers
}

location /documents/private/ {
    # Plus spécifique, donc prioritaire sur /documents/
    auth_basic "Privé";
    auth_basic_user_file /etc/nginx/.htpasswd;
}


# === ORDRE DE PRIORITÉ (du plus au moins prioritaire) ===

# 1. = (exact)              location = /page.html
# 2. ^~ (préfixe prioritaire)  location ^~ /static/
# 3. ~ et ~* (regex)        location ~ \.php$
#    -> Dans l'ordre d'apparition dans le fichier !
# 4. Préfixe normal         location /documents/
#    -> Le match le PLUS LONG gagne


# === EXEMPLE COMPLET AVEC EXPLICATION ===

server {
    listen 80;
    server_name example.com;
    root /var/www/example;
    
    # RÈGLE 1: Page d'accueil exacte (priorité max)
    location = / {
        # Seulement example.com/ (rien après)
        try_files /index.html =404;
        # Cherche /var/www/example/index.html
    }
    
    # RÈGLE 2: Dossier images (prioritaire, pas de regex)
    location ^~ /images/ {
        # example.com/images/photo.jpg
        root /var/www/example;
        # Devient /var/www/example/images/photo.jpg
        expires 1y;
        add_header Cache-Control "public, immutable";
    }
    
    # RÈGLE 3: Fichiers PHP (regex)
    location ~ \.php$ {
        # example.com/admin/login.php
        include fastcgi_params;
        fastcgi_pass unix:/var/run/php/php8.1-fpm.sock;
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
    }
    
    # RÈGLE 4: Extensions images (regex insensible)
    location ~* \.(jpg|jpeg|png|gif|ico|svg)$ {
        # example.com/logo.PNG
        expires 1M;
        access_log off;
    }
    
    # RÈGLE 5: Extensions CSS/JS
    location ~* \.(css|js)$ {
        # example.com/styles/main.css
        expires 1M;
        add_header Cache-Control "public";
    }
    
    # RÈGLE 6: Bloquer fichiers cachés (sécurité)
    location ~ /\. {
        # example.com/.git/config
        # example.com/.env
        deny all;           # Accès interdit !
        access_log off;
        log_not_found off;
    }
    
    # RÈGLE 7: Dossier API (préfixe normal)
    location /api/ {
        # example.com/api/users
        proxy_pass http://localhost:3000;
        proxy_set_header Host $host;
    }
    
    # RÈGLE 8: Tout le reste (catch-all)
    location / {
        # example.com/about.html
        # example.com/contact
        try_files $uri $uri/ =404;
    }
}


# === TRY_FILES EXPLIQUÉ ===

# try_files essaie plusieurs options dans l'ordre
# Format: try_files option1 option2 option3 ... dernière_option;

# Exemple 1: Site statique simple
location / {
    try_files $uri $uri/ =404;
    
    # Visite de /about.html:
    # 1. Essaie $uri -> /var/www/site/about.html
    #    Existe ? [OK] Sert le fichier
    # 2. Sinon essaie $uri/ -> /var/www/site/about.html/
    #    Dossier ? Cherche index.html dedans
    # 3. Sinon =404 -> Erreur 404
}

# Exemple 2: Application single-page (React/Vue/Angular)
location / {
    try_files $uri $uri/ /index.html;
    
    # Visite de /dashboard:
    # 1. Fichier /dashboard existe ? Non
    # 2. Dossier /dashboard/ existe ? Non
    # 3. Sert /index.html (qui gère le routing côté client)
    
    # Permet le routing côté client de fonctionner !
}

# Exemple 3: WordPress/CMS
location / {
    try_files $uri $uri/ /index.php?$args;
    
    # Visite de /blog/mon-article:
    # 1. Fichier existe ? Non
    # 2. Dossier existe ? Non
    # 3. Passe à index.php avec query string
    #    -> index.php gère le routing
}


# === VARIABLES UTILES DANS LOCATION ===

$uri                # URI normalisée (sans query string)
                    # /about.html

$request_uri       # URI complète avec query string
                    # /about.html?page=2

$document_root     # Racine définie dans "root"
                    # /var/www/example

$realpath_root     # Chemin absolu réel (résout symlinks)
                    # /home/user/www/example

# Exemple d'utilisation:
location /debug {
    return 200 "Document root: $document_root\nURI: $uri\nRequest URI: $request_uri\n";
    add_header Content-Type text/plain;
}


# === EXEMPLES PRATIQUES COURANTS ===

# 1. SITE STATIQUE SIMPLE
location / {
    try_files $uri $uri/ =404;
}

# 2. APPLICATION REACT/VUE/ANGULAR (SPA)
location / {
    try_files $uri $uri/ /index.html;
}

# 3. WORDPRESS
location / {
    try_files $uri $uri/ /index.php?$args;
}

location ~ \.php$ {
    fastcgi_pass unix:/var/run/php/php-fpm.sock;
    fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
    include fastcgi_params;
}

# 4. REVERSE PROXY VERS API
location /api/ {
    proxy_pass http://localhost:3000/;
    proxy_set_header Host $host;
    proxy_set_header X-Real-IP $remote_addr;
}

# 5. FICHIERS STATIQUES OPTIMISÉS
location ~* \.(jpg|jpeg|png|gif|ico|css|js|svg|woff|woff2)$ {
    expires 1y;
    add_header Cache-Control "public, immutable";
    access_log off;
}

# 6. SÉCURITÉ: BLOQUER FICHIERS SENSIBLES
location ~ /\.(git|env|htaccess) {
    deny all;
    return 404;
}

# 7. DOSSIER AVEC LISTING ACTIVÉ
location /downloads/ {
    autoindex on;
    autoindex_exact_size off;   # Taille lisible
    autoindex_localtime on;     # Heure locale
}

# 8. AUTHENTIFICATION BASIQUE
location /admin/ {
    auth_basic "Zone Admin";
    auth_basic_user_file /etc/nginx/.htpasswd;
    try_files $uri $uri/ =404;
}


# === TESTER VOS RÈGLES LOCATION ===

# Méthode 1: Ajouter des headers de debug
location /test {
    add_header X-Location "test location";
    return 200 "Vous êtes dans /test\n";
}

# Tester:
curl -I http://localhost/test
# Vous verrez X-Location dans les headers

# Méthode 2: Utiliser return avec message
location = /debug {
    return 200 "Location matched!\nURI: $uri\n";
    add_header Content-Type text/plain;
}

# Tester:
curl http://localhost/debug


# === ERREURS COURANTES ===

# [X] ERREUR 1: Oublier le / à la fin
location /api {              # [X] Sans /
    proxy_pass http://backend;
}
# Matche: /api, /api-v2, /apitest (pas ce qu'on veut!)

location /api/ {             # [OK] Avec /
    proxy_pass http://backend;
}
# Matche seulement: /api/, /api/users, etc.


# [X] ERREUR 2: Ordre des règles regex
location ~ \.php$ {
    # Règle PHP
}

location ~ \.html$ {
    # Règle HTML
}
# Si fichier .php.html, la PREMIÈRE règle qui matche gagne (PHP)


# [X] ERREUR 3: Oublier $ dans regex
location ~ \.php {           # [X] Sans $
    # ...
}
# Matche: index.php, index.php.bak, index.php5 (trop large!)

location ~ \.php$ {          # [OK] Avec $
    # ...
}
# Matche SEULEMENT: index.php (ce qu'on veut)


# [X] ERREUR 4: root vs alias confusion
location /static/ {
    root /var/www;
    # Cherche: /var/www/static/ (ajoute /static/)
}

location /static/ {
    alias /var/www/files/;
    # Cherche: /var/www/files/ (remplace /static/)
}


# === RÉSUMÉ LOCATION ===

# Types (par priorité):
# 1. location = /exact    -> Match exact
# 2. location ^~ /prefix  -> Préfixe prioritaire
# 3. location ~ regex     -> Regex sensible casse
# 4. location ~* regex    -> Regex insensible casse
# 5. location /prefix     -> Préfixe normal (plus long gagne)

# Commandes essentielles:
try_files $uri $uri/ =404;      # Site statique
try_files $uri $uri/ /index.html;   # SPA (React/Vue)
try_files $uri $uri/ /index.php?$args;  # WordPress

# Sécurité:
location ~ /\. { deny all; }    # Bloquer fichiers cachés

# Performance:
location ~* \.(jpg|css|js)$ {   # Cache fichiers statiques
    expires 1y;
}

# Test:
curl -I http://localhost/votre-url  # Tester règles


[OK] REVERSE PROXY - FAIRE LE PONT VERS VOS APPLICATIONS

# === QU'EST-CE QU'UN REVERSE PROXY ? ===

# Imaginons un restaurant:
# - Client (navigateur) -> Maître d'hôtel (Nginx) -> Cuisine (votre app backend)
# - Le client ne voit jamais la cuisine
# - Le maître d'hôtel prend la commande et la transmet
# - Puis ramène le plat préparé par la cuisine

# SANS REVERSE PROXY:
# Navigateur -> http://monsite.com:3000 (port visible, pas professionnel)
# 
# AVEC REVERSE PROXY:
# Navigateur -> http://monsite.com (port 80, propre)
#           v
#      Nginx (port 80)
#           v
#      Votre app Node.js/Python/etc (port 3000, invisible)

# Avantages du reverse proxy:
# [OK] Cache les ports non-standards (3000, 8080, etc.)
# [OK] Gère SSL/HTTPS (votre app backend peut rester en HTTP)
# [OK] Load balancing (répartir sur plusieurs serveurs)
# [OK] Cache les réponses
# [OK] Compression (gzip)
# [OK] Sécurité (rate limiting, blocage IP)
# [OK] Logs centralisés


# === REVERSE PROXY SIMPLE (Débutant) ===

# Situation: Vous avez une app Node.js qui tourne sur localhost:3000
# Objectif: Rendre accessible via http://monsite.com

server {
    listen 80;
    server_name monsite.com;
    
    location / {
        proxy_pass http://localhost:3000;
        # Nginx prend TOUTES les requêtes
        # et les envoie à localhost:3000
        
        # Headers essentiels (voir section suivante)
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
    }
}

# Test:
# 1. Votre app Node.js tourne sur port 3000
# 2. Visitez http://monsite.com (port 80)
# 3. Nginx transmet à localhost:3000
# 4. Votre app répond
# 5. Nginx renvoie la réponse au navigateur


# === COMPRENDRE LES HEADERS PROXY ===

# Quand Nginx fait du proxy, il doit dire au backend:
# "Voici des infos sur la requête originale"

location / {
    proxy_pass http://localhost:3000;
    
    # 1. HOST - Nom de domaine demandé
    proxy_set_header Host $host;
    # $host = monsite.com
    # Sans ça, backend voit "localhost" au lieu de "monsite.com"
    # Important pour: virtual hosts, génération URLs absolues
    
    # 2. X-Real-IP - Vraie IP du visiteur
    proxy_set_header X-Real-IP $remote_addr;
    # $remote_addr = 203.0.113.45 (IP du visiteur)
    # Sans ça, backend voit toujours 127.0.0.1 (localhost)
    # Important pour: géolocalisation, logs, sécurité
    
    # 3. X-Forwarded-For - Chaîne des proxies
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    # Garde trace de tous les proxies traversés
    # Exemple: 203.0.113.45, 198.51.100.12
    # Important pour: plusieurs proxies en cascade
    
    # 4. X-Forwarded-Proto - Protocole original (http/https)
    proxy_set_header X-Forwarded-Proto $scheme;
    # $scheme = https si connexion SSL
    # Sans ça, backend pense que c'est du HTTP même si HTTPS
    # Important pour: redirections, génération URLs correctes
}

# Dans votre app backend (exemple Node.js):
app.get('/', (req, res) => {
    console.log('Host:', req.headers['host']);              // monsite.com
    console.log('Real IP:', req.headers['x-real-ip']);      // 203.0.113.45
    console.log('Protocol:', req.headers['x-forwarded-proto']); // https
});


# === PROXY COMPLET AVEC TOUTES LES OPTIONS ===

server {
    listen 80;
    server_name app.monsite.com;
    
    location / {
        # Backend
        proxy_pass http://localhost:8080;
        
        # === 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;
        
        # === TIMEOUTS ===
        # Si votre backend est lent à répondre
        proxy_connect_timeout 60s;      # Temps pour établir connexion
        proxy_send_timeout 60s;         # Temps pour envoyer requête
        proxy_read_timeout 60s;         # Temps pour lire réponse
        
        # Exemple: Si votre API prend 2min pour traiter:
        # proxy_read_timeout 120s;
        
        # === BUFFERING ===
        # Nginx stocke temporairement la réponse
        proxy_buffering on;             # Active buffering (recommandé)
        proxy_buffer_size 4k;           # Taille buffer pour headers
        proxy_buffers 8 4k;             # 8 buffers de 4k chacun
        proxy_busy_buffers_size 8k;     # Taille buffers occupés
        
        # Pourquoi buffering ?
        # - Libère backend plus rapidement
        # - Gère clients lents
        # - Meilleure performance globale
        
        # === REDIRECTIONS ===
        proxy_redirect off;             # Désactive réécriture redirections
        # Ou:
        # proxy_redirect http://localhost:8080/ http://monsite.com/;
        # Réécrit les redirections du backend
        
        # === HTTP VERSION ===
        proxy_http_version 1.1;         # Utilise HTTP/1.1
        # Nécessaire pour WebSocket et keep-alive
        
        # === KEEP-ALIVE ===
        proxy_set_header Connection "";
        # Garde connexion ouverte vers backend
        # Meilleure performance (évite reconnexions)
    }
}


# === PROXY WEBSOCKET (Chat, temps réel) ===

# WebSocket = connexion persistante bidirectionnelle
# Exemple: Chat, notifications temps réel, jeux en ligne

# Astuce: Utiliser map pour gérer Upgrade header
map $http_upgrade $connection_upgrade {
    default upgrade;        # Si header Upgrade existe -> "upgrade"
    '' close;               # Sinon -> "close"
}

server {
    listen 80;
    server_name chat.monsite.com;
    
    location / {
        proxy_pass http://localhost:3000;
        
        # Headers standard
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        
        # === SPÉCIFIQUE WEBSOCKET ===
        proxy_http_version 1.1;                     # Obligatoire
        proxy_set_header Upgrade $http_upgrade;     # Header Upgrade
        proxy_set_header Connection $connection_upgrade;  # Utilise map
        
        # Timeouts longs pour WebSocket
        proxy_connect_timeout 7d;       # 7 jours max connexion
        proxy_send_timeout 7d;
        proxy_read_timeout 7d;
        
        # Désactive buffering (temps réel)
        proxy_buffering off;
    }
}

# Test WebSocket:
# Dans votre navigateur (console F12):
# const ws = new WebSocket('ws://chat.monsite.com');
# ws.onopen = () => console.log('Connecté!');


# === PROXY AVEC UPSTREAM (Meilleure pratique) ===

# upstream = définir un groupe de serveurs backend
# Avantages:
# - Code plus propre et réutilisable
# - Load balancing automatique
# - Health checks
# - Facile à maintenir

# Définir l'upstream (en dehors du bloc server)
upstream backend_app {
    # Un seul serveur
    server 127.0.0.1:8080;
    
    # Ou plusieurs serveurs (load balancing automatique)
    # server 127.0.0.1:8080;
    # server 127.0.0.1:8081;
    # server 127.0.0.1:8082;
}

server {
    listen 80;
    server_name app.monsite.com;
    
    location / {
        proxy_pass http://backend_app;  # Référence l'upstream
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
    }
}


# === EXEMPLES PRATIQUES PAR TECHNOLOGIE ===

# 1⃣ NODE.JS / EXPRESS
upstream nodejs {
    server localhost:3000;
}

server {
    listen 80;
    server_name node.example.com;
    
    location / {
        proxy_pass http://nodejs;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection 'upgrade';
        proxy_set_header Host $host;
        proxy_cache_bypass $http_upgrade;
    }
}

# Démarrer app Node.js:
# node server.js  (écoute sur port 3000)


# 2⃣ PYTHON / DJANGO
upstream django {
    server localhost:8000;
}

server {
    listen 80;
    server_name django.example.com;
    
    location / {
        proxy_pass http://django;
        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;
    }
    
    # Fichiers statiques (collectstatic)
    location /static/ {
        alias /var/www/django/static/;
        expires 30d;
    }
    
    location /media/ {
        alias /var/www/django/media/;
        expires 30d;
    }
}

# Démarrer Django:
# python manage.py runserver 0.0.0.0:8000
# Ou avec gunicorn:
# gunicorn myproject.wsgi:application --bind 127.0.0.1:8000


# 3⃣ PYTHON / FLASK
upstream flask {
    server localhost:5000;
}

server {
    listen 80;
    server_name flask.example.com;
    
    location / {
        proxy_pass http://flask;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
    }
}

# Démarrer Flask:
# flask run --host=0.0.0.0 --port=5000
# Ou avec gunicorn:
# gunicorn -w 4 -b 127.0.0.1:5000 app:app


# 4⃣ JAVA / SPRING BOOT
upstream springboot {
    server localhost:8080;
}

server {
    listen 80;
    server_name spring.example.com;
    
    location / {
        proxy_pass http://springboot;
        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;
        
        # Spring Boot peut être lent à démarrer
        proxy_read_timeout 300s;
    }
}

# Démarrer Spring Boot:
# java -jar application.jar


# 5⃣ DOCKER CONTAINERS
upstream docker_app {
    server 172.17.0.2:8080;  # IP du container
    # Ou utiliser nom du service dans docker-compose:
    # server app:8080;
}

server {
    listen 80;
    server_name docker.example.com;
    
    location / {
        proxy_pass http://docker_app;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
    }
}


# === MULTI-APPLICATIONS SUR UN MÊME SERVEUR ===

# Situation: Plusieurs apps sur un serveur
# Solution: Proxy selon le sous-domaine ou le path

# Méthode 1: Par sous-domaine
# app1.monsite.com -> localhost:3000
# app2.monsite.com -> localhost:4000
# api.monsite.com  -> localhost:5000

upstream app1 {
    server localhost:3000;
}

upstream app2 {
    server localhost:4000;
}

upstream api {
    server localhost:5000;
}

server {
    listen 80;
    server_name app1.monsite.com;
    
    location / {
        proxy_pass http://app1;
        proxy_set_header Host $host;
    }
}

server {
    listen 80;
    server_name app2.monsite.com;
    
    location / {
        proxy_pass http://app2;
        proxy_set_header Host $host;
    }
}

server {
    listen 80;
    server_name api.monsite.com;
    
    location / {
        proxy_pass http://api;
        proxy_set_header Host $host;
    }
}


# Méthode 2: Par path (chemin)
# monsite.com/app1 -> localhost:3000
# monsite.com/app2 -> localhost:4000
# monsite.com/api  -> localhost:5000

server {
    listen 80;
    server_name monsite.com;
    
    # App 1
    location /app1/ {
        proxy_pass http://localhost:3000/;
        # Note le / à la fin de proxy_pass
        # Enlève /app1/ de l'URL envoyée au backend
        proxy_set_header Host $host;
    }
    
    # App 2
    location /app2/ {
        proxy_pass http://localhost:4000/;
        proxy_set_header Host $host;
    }
    
    # API
    location /api/ {
        proxy_pass http://localhost:5000/;
        proxy_set_header Host $host;
    }
    
    # Site principal
    location / {
        root /var/www/monsite;
        try_files $uri $uri/ /index.html;
    }
}


# === PROXY AVEC SLASH FINAL - ATTENTION ! ===

# C'est TRÈS important et source de bugs courants !

# CAS 1: Sans / à la fin de proxy_pass
location /api/ {
    proxy_pass http://localhost:3000;
    # Requête: /api/users
    # Backend reçoit: /api/users (chemin complet conservé)
}

# CAS 2: Avec / à la fin de proxy_pass
location /api/ {
    proxy_pass http://localhost:3000/;
    # Requête: /api/users
    # Backend reçoit: /users (préfixe /api/ enlevé)
}

# Exemple concret:
# Backend Node.js a ces routes:
# app.get('/users', ...)    -> PAS /api/users !

# Bonne config:
location /api/ {
    proxy_pass http://localhost:3000/;  # Avec /
    # /api/users -> /users [OK]
}

# Mauvaise config:
location /api/ {
    proxy_pass http://localhost:3000;   # Sans /
    # /api/users -> /api/users [X] (route n'existe pas dans backend)
}


# === DÉBUGGER UN REVERSE PROXY ===

# Méthode 1: Ajouter headers de debug
location / {
    proxy_pass http://localhost:3000;
    
    # Headers visibles dans navigateur (F12 -> Network)
    add_header X-Backend "localhost:3000";
    add_header X-Debug-Uri "$uri";
    add_header X-Debug-Request-Uri "$request_uri";
}

# Méthode 2: Logger dans fichier séparé
location / {
    proxy_pass http://localhost:3000;
    
    # Log toutes les requêtes proxy
    access_log /var/log/nginx/proxy_access.log;
    error_log /var/log/nginx/proxy_error.log;
}

# Voir logs:
sudo tail -f /var/log/nginx/proxy_error.log


# Méthode 3: Tester backend directement
# 1. Tester que backend répond:
curl http://localhost:3000

# 2. Si OK, tester via Nginx:
curl http://monsite.com

# 3. Comparer les réponses


# === ERREURS COURANTES ===

# [X] ERREUR 1: "502 Bad Gateway"
# Cause: Backend ne répond pas
# Solutions:
# - Vérifier que backend tourne:
ps aux | grep node    # ou python, java, etc.

# - Vérifier le port:
netstat -tulpn | grep 3000

# - Tester backend directement:
curl http://localhost:3000

# - Vérifier logs Nginx:
sudo tail -f /var/log/nginx/error.log


# [X] ERREUR 2: "504 Gateway Timeout"
# Cause: Backend trop lent à répondre
# Solution: Augmenter timeouts
proxy_connect_timeout 300s;
proxy_send_timeout 300s;
proxy_read_timeout 300s;


# [X] ERREUR 3: Redirections cassées
# Cause: Backend génère URLs avec mauvais host/port
# Solution: Headers corrects
proxy_set_header Host $host;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Forwarded-Host $host;


# [X] ERREUR 4: IP du client toujours 127.0.0.1
# Cause: Oubli de X-Real-IP header
# Solution:
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;


# === SNIPPET RÉUTILISABLE ===

# Créer un snippet pour éviter répétition
# /etc/nginx/snippets/proxy-params.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;
proxy_http_version 1.1;
proxy_set_header Connection "";

# Utilisation dans vos sites:
server {
    listen 80;
    server_name monsite.com;
    
    location / {
        include snippets/proxy-params.conf;  # Inclut tous les headers
        proxy_pass http://localhost:3000;
    }
}


# === RÉSUMÉ REVERSE PROXY ===

# Configuration minimale:
location / {
    proxy_pass http://localhost:3000;
    proxy_set_header Host $host;
    proxy_set_header X-Real-IP $remote_addr;
}

# Configuration complète recommandée:
location / {
    proxy_pass http://localhost:3000;
    
    # Headers essentiels
    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;
    
    # HTTP/1.1 et keep-alive
    proxy_http_version 1.1;
    proxy_set_header Connection "";
    
    # Timeouts (ajuster selon besoin)
    proxy_connect_timeout 60s;
    proxy_send_timeout 60s;
    proxy_read_timeout 60s;
}

# WebSocket:
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $connection_upgrade;

# Test:
# 1. Backend tourne sur port X
# 2. Tester: curl http://localhost:X
# 3. Config Nginx avec proxy_pass
# 4. nginx -t && systemctl reload nginx
# 5. Tester: curl http://monsite.com
# 6. Comparer réponses


[OK] LOAD BALANCING - RÉPARTIR LA CHARGE ENTRE SERVEURS

# === QU'EST-CE QUE LE LOAD BALANCING ? ===

# Imaginez un supermarché avec plusieurs caisses:
# - 1 caisse ouverte = longue file d'attente (lent)
# - 5 caisses ouvertes = clients répartis (rapide)
#
# Load balancing = Répartir les visiteurs entre plusieurs serveurs
# pour améliorer performance et disponibilité

# SANS LOAD BALANCING:
# Tous les visiteurs -> Serveur unique -> Surcharge/Crash
#
# AVEC LOAD BALANCING:
# Visiteurs -> Nginx (répartiteur) -> Serveur 1 (33%)
#                                  -> Serveur 2 (33%)
#                                  -> Serveur 3 (33%)

# Avantages:
# [OK] Meilleure performance (charge répartie)
# [OK] Haute disponibilité (si un serveur tombe, les autres prennent le relais)
# [OK] Scalabilité horizontale (ajouter serveurs facilement)
# [OK] Maintenance sans interruption (arrêter un serveur à la fois)


# === LOAD BALANCING BASIQUE (Round Robin) ===

# Round Robin = "Chacun son tour"
# Requête 1 -> Serveur 1
# Requête 2 -> Serveur 2
# Requête 3 -> Serveur 3
# Requête 4 -> Serveur 1 (on recommence)
# etc.

# C'est la méthode PAR DÉFAUT de Nginx (pas besoin de la spécifier)

upstream backend {
    # Liste des serveurs backend
    server 192.168.1.101:8080;
    server 192.168.1.102:8080;
    server 192.168.1.103:8080;
}

server {
    listen 80;
    server_name monsite.com;
    
    location / {
        proxy_pass http://backend;  # Nginx répartit automatiquement
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
    }
}

# Test simple avec serveurs locaux:
upstream backend {
    server localhost:3000;  # Instance 1 de votre app
    server localhost:3001;  # Instance 2 de votre app
    server localhost:3002;  # Instance 3 de votre app
}

# Démarrer 3 instances de votre app sur ports différents:
# Terminal 1: node app.js --port 3000
# Terminal 2: node app.js --port 3001
# Terminal 3: node app.js --port 3002


# === MÉTHODE LEAST CONNECTIONS ===

# Least Conn = "Qui a le moins de clients"
# Envoie la requête au serveur qui a le MOINS de connexions actives
# Idéal pour: Requêtes de durée variable

# Exemple:
# Serveur 1: 5 connexions actives
# Serveur 2: 12 connexions actives
# Serveur 3: 3 connexions actives
# -> Nouvelle requête va au Serveur 3

upstream backend {
    least_conn;     # Active la méthode least connections
    
    server 192.168.1.101:8080;
    server 192.168.1.102:8080;
    server 192.168.1.103:8080;
}

# Quand utiliser least_conn ?
# - Requêtes avec temps de traitement variable
# - Certaines requêtes prennent 1s, d'autres 30s
# - Exemple: Upload de fichiers, traitement vidéo


# === MÉTHODE IP HASH (Sticky Sessions) ===

# IP Hash = "Même client -> Même serveur"
# Calcule un hash de l'IP du client
# Envoie toujours ce client vers le même serveur

# Pourquoi c'est important ?
# Si votre app stocke la session en mémoire:
# - Sans IP hash: User se connecte sur Serveur 1, puis requête suivante 
#                 va sur Serveur 2 qui ne connaît pas la session -> LOGOUT!
# - Avec IP hash: User reste toujours sur Serveur 1 -> Session OK

upstream backend {
    ip_hash;        # Active sticky sessions par IP
    
    server 192.168.1.101:8080;
    server 192.168.1.102:8080;
    server 192.168.1.103:8080;
}

# Exemple concret:
# Client IP 203.0.113.45 -> hash = abc123 -> Serveur 2
# Toutes les futures requêtes de 203.0.113.45 -> Serveur 2

# Quand utiliser ip_hash ?
# [OK] Sessions stockées en mémoire (pas Redis/database)
# [OK] Applications stateful
# [X] NE PAS utiliser si clients derrière proxy (tous ont même IP)
# [X] NE PAS utiliser si sessions en Redis/database (pas besoin)


# === PONDÉRATION (Weight) ===

# Weight = Donner plus de poids à certains serveurs
# Serveur puissant = plus de requêtes
# Serveur faible = moins de requêtes

upstream backend {
    server 192.168.1.101:8080 weight=3;  # Reçoit 3x plus
    server 192.168.1.102:8080 weight=2;  # Reçoit 2x
    server 192.168.1.103:8080 weight=1;  # Reçoit 1x
    
    # Répartition: 
    # Serveur 1: 50% (3/6)
    # Serveur 2: 33% (2/6)
    # Serveur 3: 17% (1/6)
}

# Exemple: 6 requêtes arrivent:
# Requête 1 -> Serveur 1
# Requête 2 -> Serveur 1
# Requête 3 -> Serveur 1
# Requête 4 -> Serveur 2
# Requête 5 -> Serveur 2
# Requête 6 -> Serveur 3

# Cas d'usage:
# - Serveur avec SSD vs HDD
# - Serveur 16GB RAM vs 8GB RAM
# - Serveur dédié vs VPS


# === SERVEURS DE BACKUP ===

# Backup = Serveur utilisé SEULEMENT si autres sont down
# Comme une roue de secours !

upstream backend {
    server 192.168.1.101:8080;
    server 192.168.1.102:8080;
    server 192.168.1.103:8080 backup;  # Utilisé si les 2 autres down
}

# Fonctionnement:
# - Normal: Requêtes réparties entre Serveur 1 et 2
# - Serveur 1 down: Requêtes sur Serveur 2 uniquement
# - Serveur 1 et 2 down: Serveur 3 (backup) prend le relais
# - Serveur 1 revient: Serveur 3 redevient backup

# Cas d'usage:
# - Serveur de secours moins puissant
# - Ancien serveur gardé en backup
# - Serveur dans autre datacenter (latence élevée)


# === HEALTH CHECKS (Vérification santé) ===

# Nginx teste automatiquement si serveurs répondent
# Si serveur ne répond pas -> marqué comme "down"
# Nginx arrête d'envoyer requêtes vers ce serveur

upstream backend {
    server 192.168.1.101:8080 max_fails=3 fail_timeout=30s;
    server 192.168.1.102:8080 max_fails=3 fail_timeout=30s;
    server 192.168.1.103:8080 max_fails=3 fail_timeout=30s;
}

# Explication:
# max_fails=3       -> Après 3 échecs consécutifs, marquer comme down
# fail_timeout=30s  -> Attendre 30s avant de retester le serveur
#
# Exemple:
# 1. Requête vers Serveur 1 -> Timeout (échec 1)
# 2. Requête vers Serveur 1 -> Timeout (échec 2)
# 3. Requête vers Serveur 1 -> Timeout (échec 3)
# -> Serveur 1 marqué DOWN pour 30 secondes
# 4. Après 30s, Nginx reteste Serveur 1
# 5. Si OK, Serveur 1 redevient UP

# Ajuster selon vos besoins:
# - API stable: max_fails=2 fail_timeout=10s (détection rapide)
# - App instable: max_fails=5 fail_timeout=60s (tolérant)


# === CONFIGURATION COMPLÈTE PROFESSIONNELLE ===

upstream backend_production {
    # Méthode: Least connections (requêtes durée variable)
    least_conn;
    
    # Serveur principal (puissant)
    server 192.168.1.101:8080 weight=5 max_fails=3 fail_timeout=30s;
    
    # Serveurs secondaires
    server 192.168.1.102:8080 weight=3 max_fails=3 fail_timeout=30s;
    server 192.168.1.103:8080 weight=2 max_fails=3 fail_timeout=30s;
    
    # Serveur de backup (datacenter secondaire)
    server 192.168.2.100:8080 backup;
    
    # Keep-alive vers backends (IMPORTANT pour performance)
    keepalive 32;       # Garde 32 connexions ouvertes vers backends
                        # Évite de rouvrir connexion à chaque requête
}

server {
    listen 80;
    server_name app.monsite.com;
    
    location / {
        proxy_pass http://backend_production;
        
        # Headers standard
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        
        # Pour utiliser keepalive vers backends
        proxy_http_version 1.1;
        proxy_set_header Connection "";
        
        # Timeouts
        proxy_connect_timeout 5s;   # Court: détecter serveur down rapidement
        proxy_send_timeout 60s;
        proxy_read_timeout 60s;
        
        # Si backend ne répond pas, essayer suivant
        proxy_next_upstream error timeout http_500 http_502 http_503;
    }
}


# === LOAD BALANCING LOCAL (Test/Développement) ===

# Situation: Tester load balancing sur votre machine
# Solution: Lancer plusieurs instances de votre app

# Exemple avec Node.js Express:
# app.js
const express = require('express');
const app = express();
const port = process.env.PORT || 3000;

app.get('/', (req, res) => {
    res.send(`Réponse du serveur sur port ${port}`);
});

app.listen(port, () => {
    console.log(`Serveur démarré sur port ${port}`);
});

# Lancer 3 instances:
# Terminal 1: PORT=3000 node app.js
# Terminal 2: PORT=3001 node app.js
# Terminal 3: PORT=3002 node app.js

# Configuration Nginx:
upstream local_backend {
    server localhost:3000;
    server localhost:3001;
    server localhost:3002;
}

server {
    listen 80;
    server_name localhost;
    
    location / {
        proxy_pass http://local_backend;
        proxy_set_header Host $host;
        
        # Header pour voir quel serveur répond
        add_header X-Backend-Port $upstream_addr;
    }
}

# Test:
# Visitez http://localhost plusieurs fois
# Vous verrez "port 3000", puis "port 3001", puis "port 3002"
# Regardez header X-Backend-Port dans DevTools (F12)


# === LOAD BALANCING AVEC DOCKER ===

# docker-compose.yml
version: '3.8'

services:
  nginx:
    image: nginx:alpine
    ports:
      - "80:80"
    volumes:
      - ./nginx.conf:/etc/nginx/nginx.conf
    depends_on:
      - app1
      - app2
      - app3

  app1:
    image: mon-app:latest
    expose:
      - "3000"

  app2:
    image: mon-app:latest
    expose:
      - "3000"

  app3:
    image: mon-app:latest
    expose:
      - "3000"

# nginx.conf (dans le container)
upstream docker_backend {
    server app1:3000;  # Nom du service Docker
    server app2:3000;
    server app3:3000;
}

server {
    listen 80;
    location / {
        proxy_pass http://docker_backend;
    }
}


# === MÉTHODES AVANCÉES (Nginx Plus uniquement) ===

# Note: Ces fonctionnalités nécessitent Nginx Plus (payant)
# Mais bon à connaître !

# 1. LEAST TIME
# Choisit serveur avec temps de réponse le plus court
upstream backend {
    least_time header;  # Temps pour recevoir headers
    # ou: least_time last_byte;  # Temps pour recevoir réponse complète
    
    server 192.168.1.101:8080;
    server 192.168.1.102:8080;
}

# 2. RANDOM
# Choisit serveur aléatoirement (avec pondération possible)
upstream backend {
    random two least_conn;  # Choisit 2 random, puis least_conn entre eux
    
    server 192.168.1.101:8080;
    server 192.168.1.102:8080;
}

# 3. HASH
# Hash sur n'importe quelle variable
upstream backend {
    hash $request_uri consistent;  # Hash basé sur l'URI
    # Même URI -> Même serveur (cache backend)
    
    server 192.168.1.101:8080;
    server 192.168.1.102:8080;
}


# === MONITORING LOAD BALANCER ===

# Ajouter un endpoint de status
server {
    listen 127.0.0.1:8080;  # Accessible seulement en local
    
    location /status {
        stub_status;
        access_log off;
    }
}

# Accéder:
curl http://localhost:8080/status

# Sortie:
# Active connections: 291
# server accepts handled requests
#  16630948 16630948 31070465
# Reading: 6 Writing: 179 Waiting: 106

# Avec upstream_status (module séparé):
location /upstream_status {
    upstream_status;
}
# Affiche état de chaque serveur backend


# === TESTER LE LOAD BALANCING ===

# Méthode 1: curl en boucle
for i in {1..10}; do
    curl http://localhost
done
# Devrait afficher réponses de différents serveurs

# Méthode 2: ab (Apache Bench)
ab -n 1000 -c 10 http://localhost/
# -n 1000 = 1000 requêtes
# -c 10 = 10 connexions simultanées

# Méthode 3: wrk (plus moderne)
wrk -t4 -c100 -d30s http://localhost/
# -t4 = 4 threads
# -c100 = 100 connexions
# -d30s = durée 30 secondes

# Vérifier les logs de chaque backend:
# Vous devriez voir requêtes réparties équitablement


# === ERREURS COURANTES ===

# [X] ERREUR 1: "no live upstreams"
# Cause: Tous les serveurs backend sont down
# Solution:
# - Vérifier que backends tournent:
ps aux | grep node
netstat -tulpn | grep 3000

# - Tester backends directement:
curl http://localhost:3000

# - Vérifier health check settings:
max_fails=3 fail_timeout=30s


# [X] ERREUR 2: Toujours le même serveur répond
# Cause: ip_hash activé ou un seul serveur UP
# Solution:
# - Retirer ip_hash si pas nécessaire
# - Vérifier que tous backends répondent
# - Regarder logs: /var/log/nginx/error.log


# [X] ERREUR 3: Sessions perdues
# Cause: Round-robin sans sticky sessions
# Solution: Utiliser ip_hash ou sessions en Redis/database
upstream backend {
    ip_hash;  # Active sticky sessions
    # ...
}


# [X] ERREUR 4: Un serveur reçoit trop de requêtes
# Cause: Pondération incorrecte
# Solution: Ajuster weight
server 192.168.1.101:8080 weight=1;  # Réduire poids


# === MAINTENANCE SANS INTERRUPTION (Zero Downtime Deployment)===

# ═══════════════════════════════════════════════════════════
# [OUTIL] MAINTENANCE D'UN SERVEUR SANS COUPURE DE SERVICE
# ═══════════════════════════════════════════════════════════

# [IMPORTANT] SITUATION : Vous devez mettre à jour le Serveur 1
# [OBJECTIF] OBJECTIF : Maintenir le service actif pendant la maintenance
# [IDEE] SOLUTION : Marquer le serveur "down" temporairement

upstream backend {
    # [ROUGE] Serveur en maintenance (marqué "down")
    server 192.168.1.101:8080 down;  
                                # [ATTENTION] Modification temporaire uniquement !
                                # "down" = Nginx n'envoie AUCUNE requête ici
                                # Le serveur est exclu de la rotation
                                # Mais reste dans la config (facile à réactiver)
                                # 
                                # [ATTENTION] ATTENTION : Ne pas confondre avec :
                                # - Commenter # server 192.168.1.101 
                                #   (nécessite reload pour réactiver)
                                # - Supprimer la ligne 
                                #   (perte de la config)
    
    # [OK] Serveurs actifs (continuent de servir le trafic)
    server 192.168.1.102:8080;  # Prend le relais
    server 192.168.1.103:8080;  # Prend le relais
    
    # [IDEE] Pendant la maintenance de 101 :
    # 102 et 103 se partagent 100% du trafic
    # Les utilisateurs ne voient aucune interruption
}

server {
    listen 80;
    server_name monsite.com;
    
    location / {
        proxy_pass http://backend;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
    }
}


# ═══════════════════════════════════════════════════════════
# [LISTE] WORKFLOW COMPLET DE MAINTENANCE (Step-by-step)
# ═══════════════════════════════════════════════════════════

# ─────────────────────────────────────────────────────────
# ÉTAPE 1⃣ : MARQUER LE SERVEUR COMME "DOWN"
# ─────────────────────────────────────────────────────────

sudo nano /etc/nginx/conf.d/backend.conf

# Ajouter "down" après l'adresse du serveur :
upstream backend {
    server 192.168.1.101:8080 down;  # <- Ajout
    server 192.168.1.102:8080;
    server 192.168.1.103:8080;
}

# [IDEE] Alternative : Commenter temporairement
# server 192.168.1.101:8080;


# ─────────────────────────────────────────────────────────
# ÉTAPE 2⃣ : TESTER ET RECHARGER NGINX
# ─────────────────────────────────────────────────────────

# Tester la configuration (CRITIQUE !)
sudo nginx -t

# Si OK, recharger Nginx (sans coupure)
sudo systemctl reload nginx

# [OK] Résultat : Nginx arrête immédiatement d'envoyer
#              de nouvelles requêtes vers 192.168.1.101
# 
# [ATTENTION] Les connexions existantes vers 101 continuent
#    jusqu'à leur fin (pas de coupure brutale)


# ─────────────────────────────────────────────────────────
# ÉTAPE 3⃣ : VÉRIFIER QUE LE TRAFIC EST REDIRIGÉ
# ─────────────────────────────────────────────────────────

# Surveiller les logs Nginx en temps réel
sudo tail -f /var/log/nginx/access.log

# Faire quelques requêtes de test
for i in {1..10}; do curl http://monsite.com; sleep 1; done

# [OK] Vous devriez voir uniquement des requêtes vers :
# - 192.168.1.102:8080
# - 192.168.1.103:8080
# 
# [X] Plus aucune vers 192.168.1.101:8080


# ─────────────────────────────────────────────────────────
# ÉTAPE 4⃣ : EFFECTUER LA MAINTENANCE SUR LE SERVEUR
# ─────────────────────────────────────────────────────────

# Sur le serveur 192.168.1.101 :

# Attendre que les connexions existantes se terminent
# (généralement quelques secondes à quelques minutes)
netstat -an | grep :8080 | grep ESTABLISHED
# ou
ss -an | grep :8080 | grep ESTAB

# Quand plus de connexions actives, arrêter l'application
sudo systemctl stop mon-application

# Effectuer les mises à jour
sudo apt update && sudo apt upgrade -y
# ou déployer nouvelle version
git pull origin main
npm install
npm run build

# Redémarrer l'application
sudo systemctl start mon-application

# Vérifier que l'application démarre correctement
sudo systemctl status mon-application


# ─────────────────────────────────────────────────────────
# ÉTAPE 5⃣ : TESTER LE SERVEUR LOCALEMENT
# ─────────────────────────────────────────────────────────

# Tester directement le serveur (bypass Nginx)
curl http://192.168.1.101:8080
curl http://192.168.1.101:8080/health  # Si endpoint health check

# Vérifier les logs de l'application
sudo journalctl -u mon-application -f

# [OK] S'assurer que tout fonctionne avant de remettre en production


# ─────────────────────────────────────────────────────────
# ÉTAPE 6⃣ : RÉACTIVER LE SERVEUR DANS NGINX
# ─────────────────────────────────────────────────────────

sudo nano /etc/nginx/conf.d/backend.conf

# Retirer "down" :
upstream backend {
    server 192.168.1.101:8080;       # <- "down" retiré
    server 192.168.1.102:8080;
    server 192.168.1.103:8080;
}


# ─────────────────────────────────────────────────────────
# ÉTAPE 7⃣ : RECHARGER NGINX ET VÉRIFIER
# ─────────────────────────────────────────────────────────

sudo nginx -t && sudo systemctl reload nginx

# Surveiller que le trafic revient progressivement
sudo tail -f /var/log/nginx/access.log

# Tester la répartition
for i in {1..30}; do curl http://monsite.com; done

# [OK] Le serveur 192.168.1.101 reçoit à nouveau du trafic


# ─────────────────────────────────────────────────────────
# ÉTAPE 8⃣ : RÉPÉTER POUR LES AUTRES SERVEURS
# ─────────────────────────────────────────────────────────

# Maintenant que 101 est à jour, faire 102 :

upstream backend {
    server 192.168.1.101:8080;       # [OK] À jour
    server 192.168.1.102:8080 down;  # [OUTIL] En maintenance
    server 192.168.1.103:8080;
}

# Puis 103 :

upstream backend {
    server 192.168.1.101:8080;       # [OK] À jour
    server 192.168.1.102:8080;       # [OK] À jour
    server 192.168.1.103:8080 down;  # [OUTIL] En maintenance
}

# Enfin, tout remettre en service :

upstream backend {
    server 192.168.1.101:8080;       # [OK] À jour
    server 192.168.1.102:8080;       # [OK] À jour
    server 192.168.1.103:8080;       # [OK] À jour
}


# ═══════════════════════════════════════════════════════════
# [OBJECTIF] STRATÉGIES AVANCÉES DE MAINTENANCE
# ═══════════════════════════════════════════════════════════

# ─────────────────────────────────────────────────────────
# STRATÉGIE 1 : ROLLING DEPLOYMENT (Déploiement progressif)
# ─────────────────────────────────────────────────────────

# Principe : Mettre à jour serveur par serveur
# Avantage : Service toujours disponible
# Durée : Plus long mais zéro downtime garanti

# Ordre recommandé :
# 1. Marquer serveur 1 "down" -> Mettre à jour -> Réactiver
# 2. Marquer serveur 2 "down" -> Mettre à jour -> Réactiver
# 3. Marquer serveur 3 "down" -> Mettre à jour -> Réactiver

upstream backend {
    server backend1:8080;  # Étape 1 : down -> update -> up
    server backend2:8080;  # Étape 2 : down -> update -> up
    server backend3:8080;  # Étape 3 : down -> update -> up
}


# ─────────────────────────────────────────────────────────
# STRATÉGIE 2 : BLUE-GREEN DEPLOYMENT
# ─────────────────────────────────────────────────────────

# Principe : Deux environnements complets (Blue et Green)
# Blue = Production actuelle
# Green = Nouvelle version

# Configuration initiale (Blue actif) :
upstream backend {
    server blue1:8080;
    server blue2:8080;
    server blue3:8080;
}

# Déployer et tester Green en parallèle :
# - Installer nouvelle version sur serveurs Green
# - Tester Green sans trafic production
# - Quand prêt, basculer :

upstream backend {
    server green1:8080;  # Nouveau !
    server green2:8080;  # Nouveau !
    server green3:8080;  # Nouveau !
}

# Rollback instantané si problème :
upstream backend {
    server blue1:8080;   # Retour arrière
    server blue2:8080;
    server blue3:8080;
}


# ─────────────────────────────────────────────────────────
# STRATÉGIE 3 : CANARY DEPLOYMENT (Déploiement Canary)
# ─────────────────────────────────────────────────────────

# Principe : Tester nouvelle version sur petit % de trafic
# Avantage : Détection précoce des bugs

# Phase 1 : 10% trafic vers nouvelle version
upstream backend {
    server old-version:8080 weight=9;    # 90% trafic
    server new-version:8080 weight=1;    # 10% trafic
}

# Phase 2 : Si stable, augmenter progressivement
upstream backend {
    server old-version:8080 weight=5;    # 50% trafic
    server new-version:8080 weight=5;    # 50% trafic
}

# Phase 3 : Basculement complet
upstream backend {
    server new-version:8080;             # 100% trafic
}


# ─────────────────────────────────────────────────────────
# STRATÉGIE 4 : UTILISER UN SERVEUR BACKUP
# ─────────────────────────────────────────────────────────

# Principe : Serveur de secours activé uniquement si besoin

upstream backend {
    server backend1:8080 max_fails=3 fail_timeout=30s;
    server backend2:8080 max_fails=3 fail_timeout=30s;
    server backend3:8080 backup;  # 🆘 Utilisé seulement si 1 et 2 down
}

# Utilisation en maintenance :
# 1. backend3 (backup) reste toujours actif en arrière-plan
# 2. Mettre backend1 et backend2 en maintenance
# 3. Le trafic bascule automatiquement sur backend3
# 4. Remettre backend1 et backend2 en service
# 5. backend3 redevient backup


# ═══════════════════════════════════════════════════════════
# [GRAPHIQUE] RÉSUMÉ LOAD BALANCING (Récapitulatif complet)
# ═══════════════════════════════════════════════════════════

# ─────────────────────────────────────────────────────────
# [SYNC] MÉTHODES DE RÉPARTITION (Algorithmes)
# ─────────────────────────────────────────────────────────

# 1. ROUND ROBIN (Défaut - Chacun son tour)
upstream backend {
    # Pas de directive spéciale nécessaire
    server backend1:8080;
    server backend2:8080;
    server backend3:8080;
}
# Fonctionnement : A -> B -> C -> A -> B -> C -> ...
# [OK] Simple et efficace pour serveurs identiques
# [X] Ne tient pas compte de la charge réelle


# 2. LEAST CONNECTIONS (Moins de connexions actives)
upstream backend {
    least_conn;  # <- Active l'algorithme
    server backend1:8080;
    server backend2:8080;
    server backend3:8080;
}
# Fonctionnement : Envoie vers serveur avec moins de connexions
# [OK] Meilleur pour requêtes de durée variable
# [OK] Équilibrage plus intelligent
# [IDEE] Recommandé pour applications temps réel (WebSocket, SSE)


# 3. IP HASH (Sticky sessions par IP client)
upstream backend {
    ip_hash;  # <- Active l'algorithme
    server backend1:8080;
    server backend2:8080;
    server backend3:8080;
}
# Fonctionnement : Même IP -> toujours même serveur
# Calcul : hash(IP_client) % nombre_serveurs
# [OK] Essentiel si application stocke session en mémoire
# [OK] Utilisateur garde sa session (panier, login...)
# [X] Répartition peut être inégale si peu de clients
# [ATTENTION]  Incompatible avec "weight" et "backup"


# 4. GENERIC HASH (Hash personnalisé)
upstream backend {
    hash $request_uri consistent;  # Hash basé sur URL
    server backend1:8080;
    server backend2:8080;
    server backend3:8080;
}
# Fonctionnement : Hash d'une variable Nginx
# Exemples de variables :
# - $request_uri    -> Même URL -> même serveur (cache)
# - $cookie_userid  -> Même cookie -> même serveur (session)
# - $arg_sessionid  -> Même param -> même serveur
# 
# "consistent" = consistent hashing (ajoute/retire serveur sans tout redistribuer)


# 5. LEAST TIME (Commercial - Nginx Plus uniquement)
upstream backend {
    least_time header;  # Temps réponse le plus court
    server backend1:8080;
    server backend2:8080;
}
# Fonctionnement : Mesure latence et envoie vers le plus rapide
# Options : header | last_byte
# [ATTENTION]  Nécessite licence Nginx Plus


# 6. RANDOM (Aléatoire - Nginx 1.15.1+)
upstream backend {
    random two least_conn;  # Choisit 2 aléatoirement, prend le moins chargé
    server backend1:8080;
    server backend2:8080;
    server backend3:8080;
}
# Fonctionnement : Sélection aléatoire avec critère secondaire
# Utile pour très grand nombre de serveurs


# ─────────────────────────────────────────────────────────
# [CONFIG] OPTIONS IMPORTANTES PAR SERVEUR
# ─────────────────────────────────────────────────────────

upstream backend {
    server backend1:8080 
        weight=3                  # [SCALES] Pondération (force relative)
        max_fails=3               # [X] Échecs avant de marquer "down"
        fail_timeout=30s          # [TEMPS] Temps d'attente avant retest
        max_conns=100             # [NOMBRE] Connexions max simultanées
        backup                    # 🆘 Serveur de secours
        down;                     # [ROUGE] Désactivé temporairement
    
    server backend2:8080;
    server backend3:8080;
}

# Explications détaillées :

# weight (Pondération)
server backend1:8080 weight=3;  # Reçoit 3× plus de requêtes
server backend2:8080 weight=2;  # Reçoit 2× plus de requêtes
server backend3:8080 weight=1;  # Référence (1×)
# 
# Ratio final : 3:2:1
# Sur 60 requêtes -> backend1=30, backend2=20, backend3=10
# 
# [IDEE] Usage : Serveurs avec capacités différentes
# Exemple : Serveur puissant (weight=5) vs faible (weight=1)


# max_fails (Échecs avant down)
server backend1:8080 max_fails=3 fail_timeout=30s;
# 
# Fonctionnement :
# 1. Nginx détecte 3 échecs consécutifs
# 2. Marque le serveur comme "indisponible"
# 3. Attend 30 secondes
# 4. Retente 1 requête (health check passif)
# 5. Si succès -> serveur réactivé
# 6. Si échec -> attend encore 30s
# 
# [IDEE] Échec = timeout, erreur connexion, ou erreur HTTP (502, 503, 504)
# [ATTENTION]  max_fails=0 désactive le mécanisme (toujours actif)


# max_conns (Limite de connexions)
server backend1:8080 max_conns=100;
# 
# Limite le nombre de connexions simultanées vers ce serveur
# Quand limite atteinte -> requêtes vont vers autres serveurs
# 
# [IDEE] Utile pour protéger serveurs moins puissants
# [IDEE] Évite de surcharger un serveur


# backup (Serveur de secours)
server backend1:8080;
server backend2:8080;
server backup-server:8080 backup;
# 
# backup-server n'est utilisé QUE si backend1 ET backend2 sont down
# 
# [IDEE] Cas d'usage :
# - Serveur de maintenance avec message "Maintenance en cours"
# - Serveur de capacité réduite (ex: old hardware)
# - Mode dégradé de l'application


# down (Désactivation temporaire)
server backend1:8080 down;
# 
# Serveur gardé dans config mais exclu de la rotation
# Aucune nouvelle requête envoyée
# 
# [IDEE] Usage : Maintenance programmée
# [IDEE] Plus simple que commenter/décommenter la ligne


# ─────────────────────────────────────────────────────────
# [LIEN] KEEPALIVE (Connexions persistantes)
# ─────────────────────────────────────────────────────────

upstream backend {
    server backend1:8080;
    server backend2:8080;
    
    keepalive 32;  # [PLUGIN] Garde 32 connexions ouvertes (par worker)
}

server {
    location / {
        proxy_pass http://backend;
        proxy_http_version 1.1;              # Requis pour keepalive
        proxy_set_header Connection "";      # Réinitialise header Connection
    }
}

# Fonctionnement :
# Sans keepalive : Nouvelle connexion TCP pour chaque requête
# Avec keepalive : Réutilise connexions existantes
# 
# Bénéfices :
# [OK] Réduit latence (pas de 3-way handshake TCP)
# [OK] Moins de charge CPU
# [OK] Moins de TIME_WAIT sockets
# 
# Calcul recommandé :
# keepalive = connexions_par_seconde / nombre_workers
# Exemple : 1000 req/s, 4 workers -> keepalive 250


# ─────────────────────────────────────────────────────────
# [LISTE] CONFIGURATION TYPE COMPLÈTE (Best Practices)
# ─────────────────────────────────────────────────────────

upstream backend {
    # Algorithme de répartition
    least_conn;  # Choisir selon besoin : least_conn, ip_hash, ou défaut
    
    # Serveurs avec configuration optimale
    server backend1:8080 
        weight=3                # Serveur puissant
        max_fails=3             # 3 échecs avant down
        fail_timeout=30s        # Retest après 30s
        max_conns=200;          # Max 200 connexions
    
    server backend2:8080 
        weight=2                # Serveur moyen
        max_fails=3 
        fail_timeout=30s
        max_conns=150;
    
    server backend3:8080 
        backup;                 # Serveur de secours
    
    # Connexions persistantes
    keepalive 32;               # 32 connexions réutilisables
    keepalive_requests 100;     # Max 100 requêtes par connexion
    keepalive_timeout 60s;      # Timeout connexion idle
}

server {
    listen 80;
    server_name monsite.com;
    
    location / {
        # Proxying vers upstream
        proxy_pass http://backend;
        
        # Headers essentiels
        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;
        
        # Keepalive (requis pour upstream keepalive)
        proxy_http_version 1.1;
        proxy_set_header Connection "";
        
        # Timeouts
        proxy_connect_timeout 5s;      # Timeout connexion backend
        proxy_send_timeout 60s;        # Timeout envoi requête
        proxy_read_timeout 60s;        # Timeout lecture réponse
        
        # Buffers (performance)
        proxy_buffering on;
        proxy_buffer_size 4k;
        proxy_buffers 8 4k;
        proxy_busy_buffers_size 8k;
        
        # Gestion des erreurs
        proxy_next_upstream error timeout invalid_header http_500 http_502 http_503;
        proxy_next_upstream_tries 2;   # Max 2 tentatives sur autres serveurs
        proxy_next_upstream_timeout 10s;
    }
    
    # Page d'erreur custom si tous backends down
    error_page 502 503 504 /maintenance.html;
    location = /maintenance.html {
        root /var/www/errors;
        internal;
    }
}


# ═══════════════════════════════════════════════════════════
# [TEST] TESTS ET VALIDATION
# ═══════════════════════════════════════════════════════════

# ─────────────────────────────────────────────────────────
# 1⃣ PRÉPARATION : LANCER PLUSIEURS INSTANCES
# ─────────────────────────────────────────────────────────

# Option A : Applications Node.js sur ports différents
node app.js --port 8001 &
node app.js --port 8002 &
node app.js --port 8003 &

# Option B : Python Flask
flask run --port 8001 &
flask run --port 8002 &
flask run --port 8003 &

# Option C : Docker containers
docker run -d -p 8001:80 nginx
docker run -d -p 8002:80 nginx
docker run -d -p 8003:80 nginx


# ─────────────────────────────────────────────────────────
# 2⃣ CONFIGURER UPSTREAM
# ─────────────────────────────────────────────────────────

upstream backend {
    server localhost:8001;
    server localhost:8002;
    server localhost:8003;
}

server {
    listen 80;
    location / {
        proxy_pass http://backend;
        proxy_set_header Host $host;
        # Ajouter header pour identifier serveur backend
        add_header X-Backend-Server $upstream_addr;
    }
}


# ─────────────────────────────────────────────────────────
# 3⃣ TESTER LA CONFIGURATION
# ─────────────────────────────────────────────────────────

sudo nginx -t && sudo systemctl reload nginx


# ─────────────────────────────────────────────────────────
# 4⃣ TESTER LA RÉPARTITION
# ─────────────────────────────────────────────────────────

# Test simple : 10 requêtes
for i in {1..10}; do 
    curl -s http://localhost
    echo ""
done

# Test avec affichage du serveur backend
for i in {1..10}; do 
    curl -s -I http://localhost | grep X-Backend-Server
done

# Test de charge avec Apache Bench
ab -n 1000 -c 10 http://localhost/

# Test de charge avec wrk
wrk -t4 -c100 -d30s http://localhost/

# Surveillance en temps réel des logs
sudo tail -f /var/log/nginx/access.log | grep --line-buffered "GET /"


# ─────────────────────────────────────────────────────────
# 5⃣ VÉRIFIER LA RÉPARTITION DANS LES LOGS
# ─────────────────────────────────────────────────────────

# Compter requêtes par backend
grep "GET /" /var/log/nginx/access.log | \
    awk '{print $1}' | sort | uniq -c | sort -nr

# Voir distribution avec upstream_addr
grep "upstream:" /var/log/nginx/access.log | \
    cut -d: -f4 | sort | uniq -c


# ─────────────────────────────────────────────────────────
# 6⃣ TESTER LE FAILOVER (Basculement)
# ─────────────────────────────────────────────────────────

# Arrêter backend1
kill $(lsof -t -i:8001)

# Faire des requêtes
for i in {1..20}; do curl http://localhost; done

# [OK] Les requêtes doivent être réparties uniquement sur 8002 et 8003
# [OK] Nginx détecte automatiquement que 8001 est down

# Redémarrer backend1
node app.js --port 8001 &

# Attendre fail_timeout (30s par défaut)
# Nginx retentera automatiquement backend1


# ═══════════════════════════════════════════════════════════
# [HAUSSE] MONITORING ET DEBUGGING
# ═══════════════════════════════════════════════════════════

# Voir statistiques upstream (Nginx Plus uniquement)
curl http://localhost/status

# Alternative : Module stub_status (gratuit)
server {
    location /nginx_status {
        stub_status;
        allow 127.0.0.1;
        deny all;
    }
}

# Accès : curl http://localhost/nginx_status
# Affiche :
# Active connections: 42
# server accepts handled requests
#  12345 12345 98765
# Reading: 1 Writing: 5 Waiting: 36


# Logs détaillés avec upstream
log_format upstreamlog '$remote_addr - $remote_user [$time_local] '
                       '"$request" $status $body_bytes_sent '
                       '"$http_referer" upstream: $upstream_addr '
                       'upstream_status: $upstream_status '
                       'request_time: $request_time '
                       'upstream_response_time: $upstream_response_time';

access_log /var/log/nginx/upstream.log upstreamlog;


# ═══════════════════════════════════════════════════════════
# [ATTENTION] ERREURS COURANTES ET SOLUTIONS
# ═══════════════════════════════════════════════════════════

# [X] no live upstreams while connecting to upstream
# -> Tous les backends sont down
# Solution : Vérifier que les applications tournent
netstat -tlnp | grep 8080
systemctl status mon-application

# [X] upstream sent too big header
# -> Headers de réponse trop gros
# Solution : Augmenter buffers
proxy_buffer_size 16k;
proxy_buffers 8 16k;

# [X] upstream timed out
# -> Backend trop lent à répondre
# Solution : Augmenter timeouts
proxy_read_timeout 300s;
proxy_connect_timeout 10s;

# [X] conflicting parameter "ip_hash"
# -> ip_hash incompatible avec weight/backup
# Solution : Choisir soit ip_hash, soit weight

# [X] no servers are inside upstream
# -> Aucun serveur défini ou tous down
# Solution : Vérifier config upstream


[OK] SÉCURITÉ - PROTÉGER VOTRE SITE

# === POURQUOI LA SÉCURITÉ EST CRUCIALE ? ===

# Internet = environnement hostile
# Bots, hackers, scripts automatiques scannent CONSTAMMENT
# Un site mal sécurisé = porte ouverte aux attaquants

# Risques principaux:
# - DDoS (Denial of Service) - Saturer serveur de requêtes
# - Injection SQL - Voler données base de données
# - XSS (Cross-Site Scripting) - Injecter code malveillant
# - Brute force - Deviner mots de passe
# - Accès fichiers sensibles (.env, .git, etc.)
# - Bots malveillants - Spam, scraping


# === HEADERS DE SÉCURITÉ (INDISPENSABLES) ===

server {
    listen 443 ssl http2;
    server_name example.com;
    
    # === 1. HSTS (HTTP Strict Transport Security) ===
    # Force HTTPS pendant durée spécifiée
    add_header Strict-Transport-Security "max-age=31536000; includeSubDomains; preload" always;
    # max-age=31536000 = 1 an (en secondes)
    # includeSubDomains = Applique aussi aux sous-domaines
    # preload = Demander inclusion dans liste navigateurs
    # always = Ajouter même en cas d'erreur
    
    # Effet: Après première visite, navigateur refuse HTTP
    # Toutes futures requêtes seront HTTPS automatiquement
    
    
    # === 2. X-Frame-Options ===
    # Empêche affichage site dans iframe (protection clickjacking)
    add_header X-Frame-Options "SAMEORIGIN" always;
    # SAMEORIGIN = Iframe OK seulement depuis même domaine
    # DENY = Jamais autoriser iframe
    # ALLOW-FROM https://example.com = Autoriser domaine spécifique
    
    # Protection contre: Clickjacking
    # (Site malveillant cache votre site dans iframe invisible)
    
    
    # === 3. X-Content-Type-Options ===
    # Empêche navigateur de "deviner" type MIME
    add_header X-Content-Type-Options "nosniff" always;
    
    # Sans: Navigateur peut interpréter .txt comme .js -> Danger!
    # Avec: Navigateur respecte Content-Type exact
    
    
    # === 4. X-XSS-Protection ===
    # Active filtre XSS navigateur (ancien mais toujours utile)
    add_header X-XSS-Protection "1; mode=block" always;
    # 1 = Activer filtre
    # mode=block = Bloquer page si XSS détecté
    
    # Note: Obsolète sur navigateurs modernes (ont protection intégrée)
    # Mais garde pour vieux navigateurs
    
    
    # === 5. Referrer-Policy ===
    # Contrôle infos envoyées dans header Referer
    add_header Referrer-Policy "strict-origin-when-cross-origin" always;
    # strict-origin-when-cross-origin = Envoie seulement origine pour autres domaines
    # no-referrer = Jamais envoyer referer (max privacité)
    # same-origin = Envoyer seulement pour même domaine
    
    
    # === 6. Content-Security-Policy (CSP) - AVANCÉ ===
    # Définit sources autorisées pour ressources (scripts, styles, images)
    add_header Content-Security-Policy "default-src 'self'; script-src 'self' 'unsafe-inline'; style-src 'self' 'unsafe-inline'; img-src 'self' data: https:; font-src 'self' data:;" always;
    
    # Explication:
    # default-src 'self' = Par défaut, seulement même domaine
    # script-src 'self' 'unsafe-inline' = Scripts: même domaine + inline OK
    # style-src 'self' 'unsafe-inline' = Styles: même domaine + inline OK
    # img-src 'self' data: https: = Images: même domaine + data URIs + HTTPS
    # font-src 'self' data: = Fonts: même domaine + data URIs
    
    # Protection contre: XSS, injection code malveillant
    # Note: CSP peut casser fonctionnalités! Tester attentivement
    
    
    # === 7. Permissions-Policy ===
    # Contrôle accès APIs navigateur (géolocalisation, caméra, etc.)
    add_header Permissions-Policy "geolocation=(), microphone=(), camera=()" always;
    # () = Personne ne peut utiliser
    # (self) = Seulement même domaine
    # (self "https://example.com") = Domaine spécifique
    
    # Protection contre: Sites malveillants accédant caméra/micro
    
    
    # === 8. Masquer version Nginx ===
    server_tokens off;
    # Sans: "Server: nginx/1.18.0" dans headers
    # Avec: "Server: nginx"
    # Empêche attaquants de connaître version exacte
}

# Test headers de sécurité:
# https://securityheaders.com/
# Entrez votre domaine, objectif: Score A+


# === BLOQUER REQUÊTES MALVEILLANTES ===

server {
    listen 80;
    server_name example.com;
    
    # === BLOQUER USER AGENTS SUSPECTS ===
    # Bots, scrapers, scanners de vulnérabilités
    if ($http_user_agent ~* (bot|crawler|spider|scraper|scanner|nikto|sqlmap)) {
        return 403 "Bot détecté";
    }
    
    # Exemples User-Agent malveillants:
    # - nikto (scanner vulnérabilités)
    # - sqlmap (scanner SQL injection)
    # - Scrapers génériques
    
    
    # === BLOQUER MÉTHODES HTTP DANGEREUSES ===
    # Autoriser seulement GET, HEAD, POST
    if ($request_method !~ ^(GET|HEAD|POST)$) {
        return 405 "Méthode non autorisée";
    }
    # Bloque: PUT, DELETE, TRACE, OPTIONS (sauf si nécessaire)
    
    
    # === BLOQUER HOST INVALIDES ===
    # Protège contre attaques scan de masse
    if ($host !~* ^(example\.com|www\.example\.com)$) {
        return 444;  # 444 = ferme connexion sans réponse
    }
    # Si requête arrive avec Host: 192.168.1.1 -> Bloqué
    
    
    # === BLOQUER FICHIERS SENSIBLES ===
    # Fichiers configuration, git, etc.
    location ~ /\.(git|svn|env|htaccess|htpasswd) {
        deny all;
        return 404;  # Prétendre que fichier n'existe pas
    }
    
    # Protège:
    # /.git/config (historique Git)
    # /.env (variables d'environnement)
    # /.htaccess (config Apache)
    
    
    # === BLOQUER EXÉCUTION PHP DANS UPLOADS ===
    # Empêche upload de backdoor PHP
    location ~* /uploads/.*\.php$ {
        deny all;
        return 404;
    }
    
    # Sans: Attaquant upload shell.php -> Exécuté -> Serveur compromis!
    # Avec: shell.php non exécuté -> Sécurité [OK]
    
    
    # === BLOQUER XMLRPC.PHP (WordPress) ===
    # Souvent utilisé pour brute force et DDoS
    location = /xmlrpc.php {
        deny all;
        access_log off;
        log_not_found off;
    }
}


# === AUTHENTIFICATION BASIQUE ===

# Protéger zone admin, API, etc. avec login/password

# Étape 1: Créer fichier mot de passe
# Installer apache2-utils:
sudo apt install apache2-utils

# Créer utilisateur (remplacer "admin" par votre nom):
sudo htpasswd -c /etc/nginx/.htpasswd admin
# Tape password quand demandé

# Ajouter autre utilisateur (SANS -c):
sudo htpasswd /etc/nginx/.htpasswd user2

# Étape 2: Protéger location avec Nginx
server {
    listen 80;
    server_name example.com;
    
    # Zone publique (pas de protection)
    location / {
        root /var/www/example;
        try_files $uri $uri/ =404;
    }
    
    # Zone admin (protégée)
    location /admin/ {
        auth_basic "Zone Administrateur";          # Message affiché
        auth_basic_user_file /etc/nginx/.htpasswd; # Fichier passwords
        
        # Si authentifié, afficher contenu
        root /var/www/example;
        try_files $uri $uri/ =404;
    }
}

# Test: Visitez http://example.com/admin/
# Popup demande login/password


# === RATE LIMITING (Limitation débit) ===

# Rate limiting = Limiter nombre de requêtes par IP
# Protège contre: Brute force, DDoS, scrapers agressifs

http {
    # === DÉFINIR ZONES DE RATE LIMITING ===
    
    # Zone générale: 1 requête/seconde par IP
    limit_req_zone $binary_remote_addr zone=one:10m rate=1r/s;
    # $binary_remote_addr = IP en binaire (économise mémoire)
    # zone=one:10m = Nom zone + 10MB mémoire (stocke ~160k IPs)
    # rate=1r/s = 1 requête par seconde
    
    # Zone API: 10 requêtes/seconde par IP
    limit_req_zone $binary_remote_addr zone=api:10m rate=10r/s;
    
    # Zone login: 5 requêtes/minute par IP (anti brute force)
    limit_req_zone $binary_remote_addr zone=login:10m rate=5r/m;
    # rate=5r/m = 5 requêtes par minute
    
    # === LIMITER CONNEXIONS SIMULTANÉES ===
    limit_conn_zone $binary_remote_addr zone=addr:10m;
    # Limite nombre connexions simultanées par IP
    
    
    server {
        listen 80;
        server_name example.com;
        
        # === APPLIQUER RATE LIMIT GÉNÉRAL ===
        location / {
            limit_req zone=one burst=5 nodelay;
            # zone=one = Utilise zone définie plus haut
            # burst=5 = Autorise pic de 5 requêtes d'un coup
            # nodelay = Ne pas mettre en file d'attente
            
            # Exemple: User fait 6 requêtes en 1 seconde
            # Requêtes 1-6: OK (burst)
            # Requête 7: 503 Service Temporarily Unavailable
            
            limit_conn addr 10;  # Max 10 connexions simultanées/IP
            
            root /var/www/example;
            try_files $uri $uri/ =404;
        }
        
        # === RATE LIMIT API (plus permissif) ===
        location /api/ {
            limit_req zone=api burst=20 nodelay;
            proxy_pass http://localhost:3000;
        }
        
        # === RATE LIMIT LOGIN (très strict) ===
        location /login {
            limit_req zone=login burst=3 nodelay;
            # Seulement 5 tentatives/minute
            # Protège contre brute force
            proxy_pass http://localhost:3000;
        }
    }
}

# Test rate limiting:
# for i in {1..10}; do curl http://example.com; done
# Premières requêtes: 200 OK
# Après burst: 503 Service Temporarily Unavailable


# === RESTRICTION PAR IP ===

# Autoriser seulement certaines IPs (zone admin, API interne)

server {
    listen 80;
    server_name admin.example.com;
    
    # === MÉTHODE 1: Allow/Deny simple ===
    location / {
        # Autoriser IPs spécifiques
        allow 192.168.1.0/24;    # Réseau local
        allow 203.0.113.50;       # IP bureau
        allow 198.51.100.0/24;    # Autre réseau
        deny all;                 # Bloquer tout le reste
        
        root /var/www/admin;
    }
    
    # === MÉTHODE 2: Avec module geo (plus flexible) ===
    # Dans bloc http:
}

http {
    geo $admin_access {
        default 0;                    # Par défaut: bloqué
        192.168.1.0/24 1;             # Réseau local: autorisé
        203.0.113.50 1;               # IP bureau: autorisé
    }
    
    server {
        listen 80;
        server_name admin.example.com;
        
        location / {
            if ($admin_access = 0) {
                return 403 "Accès refusé";
            }
            
            root /var/www/admin;
        }
    }
}


# === FAIL2BAN (Bannir IPs malveillantes) ===

# Fail2ban = Surveille logs et bannit IPs suspectes automatiquement
# Exemple: 5 tentatives login échouées -> IP bannie 1 heure

# Installation:
sudo apt install fail2ban

# Configuration pour Nginx:
# /etc/fail2ban/jail.local
sudo tee /etc/fail2ban/jail.local <<EOF
[nginx-http-auth]
enabled = true
port = http,https
logpath = /var/log/nginx/error.log
maxretry = 3
bantime = 3600
findtime = 600

[nginx-noscript]
enabled = true
port = http,https
logpath = /var/log/nginx/access.log
maxretry = 6
bantime = 3600
findtime = 600

[nginx-badbots]
enabled = true
port = http,https
logpath = /var/log/nginx/access.log
maxretry = 2
bantime = 86400
findtime = 600

[nginx-noproxy]
enabled = true
port = http,https
logpath = /var/log/nginx/access.log
maxretry = 2
bantime = 86400
findtime = 600
EOF

# Redémarrer Fail2ban:
sudo systemctl restart fail2ban

# Vérifier IPs bannies:
sudo fail2ban-client status nginx-http-auth

# Débannir IP manuellement:
sudo fail2ban-client set nginx-http-auth unbanip 203.0.113.45


# === PROTECTION DDOS (Attaque par déni de service) ===

# DDoS = Saturer serveur avec énormément de requêtes

http {
    # === RATE LIMITS AGRESSIFS ===
    limit_req_zone $binary_remote_addr zone=ddos:10m rate=100r/s;
    limit_conn_zone $binary_remote_addr zone=conn:10m;
    
    # === TIMEOUTS COURTS ===
    client_body_timeout 10s;      # Timeout envoi body requête
    client_header_timeout 10s;    # Timeout envoi headers
    keepalive_timeout 5s 5s;      # Timeout keep-alive
    send_timeout 10s;             # Timeout envoi réponse
    
    # === LIMITES TAILLE ===
    client_body_buffer_size 128k;     # Taille buffer body
    client_max_body_size 10m;         # Taille max body (uploads)
    client_header_buffer_size 1k;     # Taille buffer headers
    large_client_header_buffers 4 8k; # Buffers headers larges
    
    server {
        listen 80;
        server_name example.com;
        
        location / {
            # Rate limiting agressif
            limit_req zone=ddos burst=200 nodelay;
            limit_conn conn 20;  # Max 20 connexions/IP
            
            proxy_pass http://backend;
        }
    }
}


# === CONFIGURATION SÉCURITÉ COMPLÈTE ===

# Exemple configuration production avec toutes sécurités

http {
    # Rate limiting
    limit_req_zone $binary_remote_addr zone=general:10m rate=10r/s;
    limit_req_zone $binary_remote_addr zone=api:10m rate=50r/s;
    limit_req_zone $binary_remote_addr zone=login:10m rate=5r/m;
    limit_conn_zone $binary_remote_addr zone=conn:10m;
    
    # Timeouts
    client_body_timeout 12s;
    client_header_timeout 12s;
    keepalive_timeout 15s;
    send_timeout 10s;
    
    # Limites
    client_max_body_size 20m;
    
    # Masquer version
    server_tokens off;
    
    server {
        # Redirection HTTP -> HTTPS
        listen 80;
        server_name example.com www.example.com;
        return 301 https://example.com$request_uri;
    }
    
    server {
        # HTTPS
        listen 443 ssl http2;
        server_name example.com;
        
        # SSL
        ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
        ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;
        ssl_protocols TLSv1.2 TLSv1.3;
        
        # Headers sécurité
        add_header Strict-Transport-Security "max-age=31536000; includeSubDomains; preload" always;
        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;
        
        # Bloquer méthodes dangereuses
        if ($request_method !~ ^(GET|HEAD|POST)$) {
            return 405;
        }
        
        # Rate limiting général
        limit_req zone=general burst=20 nodelay;
        limit_conn conn 50;
        
        # Fichiers sensibles bloqués
        location ~ /\.(git|env|htaccess) {
            deny all;
            return 404;
        }
        
        # Zone publique
        location / {
            root /var/www/example;
            try_files $uri $uri/ =404;
        }
        
        # API
        location /api/ {
            limit_req zone=api burst=100 nodelay;
            proxy_pass http://localhost:3000;
            proxy_set_header Host $host;
            proxy_set_header X-Real-IP $remote_addr;
        }
        
        # Login (protection brute force)
        location = /login {
            limit_req zone=login burst=3 nodelay;
            proxy_pass http://localhost:3000;
        }
        
        # Admin (auth + IP restriction)
        location /admin/ {
            auth_basic "Zone Admin";
            auth_basic_user_file /etc/nginx/.htpasswd;
            
            allow 192.168.1.0/24;
            deny all;
            
            proxy_pass http://localhost:3000;
        }
    }
}


# === TESTER VOTRE SÉCURITÉ ===

# 1. Security Headers
# https://securityheaders.com/
# Objectif: Score A+

# 2. SSL Labs
# https://www.ssllabs.com/ssltest/
# Objectif: Score A+

# 3. Mozilla Observatory
# https://observatory.mozilla.org/
# Objectif: Score A+

# 4. Test rate limiting
for i in {1..20}; do
    curl -w "%{http_code}\n" http://example.com
done
# Devrait voir 503 après burst

# 5. Test fichiers sensibles
curl http://example.com/.git/config
curl http://example.com/.env
# Devrait retourner 404

# 6. Test auth basique
curl http://example.com/admin/
# Devrait retourner 401 Unauthorized


# === CHECKLIST SÉCURITÉ ===

[ ] HTTPS activé avec Let's Encrypt
[ ] Redirection HTTP -> HTTPS
[ ] Headers de sécurité (HSTS, X-Frame-Options, etc.)
[ ] server_tokens off (masquer version)
[ ] Rate limiting sur endpoints sensibles
[ ] Authentification sur zones admin
[ ] Bloquer fichiers sensibles (.git, .env)
[ ] Bloquer user agents suspects
[ ] Limiter méthodes HTTP
[ ] Fail2ban installé et configuré
[ ] Logs surveillés régulièrement
[ ] Firewall actif (UFW/iptables)
[ ] Mises à jour régulières du serveur


# === RÉSUMÉ SÉCURITÉ ===

# Headers essentiels:
add_header Strict-Transport-Security "max-age=31536000" always;
add_header X-Frame-Options "SAMEORIGIN" always;
add_header X-Content-Type-Options "nosniff" always;
server_tokens off;

# Rate limiting:
limit_req_zone $binary_remote_addr zone=one:10m rate=10r/s;
limit_req zone=one burst=20 nodelay;

# Authentification:
auth_basic "Zone Restreinte";
auth_basic_user_file /etc/nginx/.htpasswd;

# Bloquer fichiers:
location ~ /\.(git|env) {
    deny all;
    return 404;
}

# Restriction IP:
allow 192.168.1.0/24;
deny all;

# Tests:
# - https://securityheaders.com
# - https://www.ssllabs.com/ssltest/
# - Fail2ban actif
# - Logs surveillés

# Sécurité = multicouche! Plus de protections = mieux!

# === QU'EST-CE QUE LE CACHE ? ===

# Cache = Stocker temporairement des réponses pour les réutiliser
# Au lieu de régénérer la même réponse 1000 fois, on la garde en mémoire

# Analogie restaurant:
# Sans cache: Chef prépare burger à chaque commande (2 min/burger)
# Avec cache: Chef prépare 10 burgers à l'avance, sert immédiatement (5 sec)

# Types de cache dans Nginx:
# 1. Cache NAVIGATEUR - Fichiers statiques (CSS, JS, images)
#    Stockés sur ordinateur du visiteur
#
# 2. Cache PROXY - Réponses backend (HTML, API)
#    Stockés sur serveur Nginx
#
# 3. Cache FASTCGI - Réponses PHP
#    Spécifique pour PHP-FPM

# Avantages:
# [OK] Site BEAUCOUP plus rapide (10-100x)
# [OK] Moins de charge serveur backend
# [OK] Supporte plus de visiteurs simultanés
# [OK] Facture serveur réduite


# === CACHE NAVIGATEUR (Fichiers statiques) ===

# Le plus simple et le plus efficace !
# Fichiers CSS, JS, images stockés dans navigateur visiteur

server {
    listen 80;
    server_name example.com;
    root /var/www/example;
    
    # === IMAGES (cache 1 an) ===
    location ~* \.(jpg|jpeg|png|gif|ico|svg|webp)$ {
        expires 1y;                     # Cache 1 an
        add_header Cache-Control "public, immutable";
        # public = peut être caché par proxies intermédiaires
        # immutable = ne changera JAMAIS (ne pas revérifier)
        
        access_log off;                 # Pas de log (optimisation)
    }
    
    # === CSS/JS (cache 1 mois) ===
    location ~* \.(css|js)$ {
        expires 1M;                     # Cache 1 mois
        add_header Cache-Control "public";
        access_log off;
    }
    
    # === FONTS (cache 1 an) ===
    location ~* \.(woff|woff2|ttf|otf|eot)$ {
        expires 1y;
        add_header Cache-Control "public, immutable";
        add_header Access-Control-Allow-Origin "*";  # CORS pour fonts
        access_log off;
    }
    
    # === VIDÉOS (cache 1 an) ===
    location ~* \.(mp4|webm|ogg|mp3)$ {
        expires 1y;
        add_header Cache-Control "public";
        access_log off;
    }
    
    # === HTML (cache court ou pas de cache) ===
    location ~* \.html$ {
        expires 10m;                    # Cache 10 minutes seulement
        add_header Cache-Control "public, must-revalidate";
        # must-revalidate = vérifier si toujours valide
    }
}

# Explication "expires":
# expires 1y;   -> 1 an
# expires 1M;   -> 1 mois
# expires 1w;   -> 1 semaine
# expires 1d;   -> 1 jour
# expires 12h;  -> 12 heures
# expires 30m;  -> 30 minutes
# expires -1;   -> Désactiver cache (toujours revérifier)


# === TEST CACHE NAVIGATEUR ===

# Méthode 1: DevTools navigateur
# 1. F12 -> Onglet Network
# 2. Rechargez page
# 3. Cliquez sur fichier CSS/JS/image
# 4. Regardez "Response Headers"
# 5. Cherchez:
#    Cache-Control: public, max-age=31536000
#    Expires: (date dans 1 an)

# Méthode 2: curl
curl -I https://example.com/style.css

# Devrait afficher:
# Cache-Control: public, immutable
# Expires: Thu, 31 Dec 2025 23:59:59 GMT

# Méthode 3: Recharger page
# 1. Première visite: Fichiers téléchargés (200 OK)
# 2. Rechargez: Fichiers depuis cache (304 Not Modified ou disk cache)


# === CACHE PROXY (Backend/API) ===

# Cache les réponses de votre backend (Node.js, Python, etc.)
# Utile pour: API, pages dynamiques qui changent peu

# Configuration zone de cache (dans bloc http, hors server)
http {
    # Définir zone de cache
    proxy_cache_path /var/cache/nginx/proxy
                     levels=1:2                  # Structure dossiers (optimisation)
                     keys_zone=my_cache:10m      # Nom zone + taille mémoire (10MB)
                     max_size=1g                 # Taille max disque (1GB)
                     inactive=60m                # Supprimer si pas accédé 60min
                     use_temp_path=off;          # Optimisation écriture
    
    server {
        listen 80;
        server_name api.example.com;
        
        location / {
            proxy_pass http://localhost:3000;
            
            # === ACTIVER CACHE ===
            proxy_cache my_cache;                # Utilise zone définie plus haut
            
            # === DURÉE CACHE PAR CODE STATUT ===
            proxy_cache_valid 200 302 10m;       # Code 200/302: cache 10 minutes
            proxy_cache_valid 404 1m;            # Code 404: cache 1 minute
            proxy_cache_valid any 5m;            # Autres codes: cache 5 minutes
            
            # === STRATÉGIES CACHE ===
            # Servir cache même si backend down
            proxy_cache_use_stale error timeout http_500 http_502 http_503;
            
            # Mettre à jour cache en arrière-plan
            proxy_cache_background_update on;
            
            # Éviter "thundering herd" (tous régénèrent en même temps)
            proxy_cache_lock on;
            
            # === HEADER DEBUG (voir si cache utilisé) ===
            add_header X-Cache-Status $upstream_cache_status;
            # Valeurs possibles:
            # HIT = Servi depuis cache [OK]
            # MISS = Pas en cache, contacté backend
            # EXPIRED = Cache expiré, rafraîchi
            # STALE = Cache périmé mais servi quand même
            # BYPASS = Cache ignoré volontairement
            # UPDATING = Cache en cours de mise à jour
            
            # Headers proxy standard
            proxy_set_header Host $host;
            proxy_set_header X-Real-IP $remote_addr;
        }
    }
}

# Créer dossier cache:
sudo mkdir -p /var/cache/nginx/proxy
sudo chown -R www-data:www-data /var/cache/nginx


# === CACHE AVANCÉ AVEC CONDITIONS ===

http {
    proxy_cache_path /var/cache/nginx/main
                     levels=1:2
                     keys_zone=main_cache:50m
                     max_size=10g
                     inactive=1h
                     use_temp_path=off;
    
    # === CLÉ DE CACHE PERSONNALISÉE ===
    # Par défaut: $scheme$request_method$host$request_uri
    # Personnaliser pour inclure cookies, etc:
    proxy_cache_key "$scheme$request_method$host$request_uri$cookie_user";
    
    # === CONDITIONS BYPASS (Ignorer cache) ===
    # Map pour méthode POST
    map $request_method $skip_cache_method {
        default 0;
        POST    1;      # Ne JAMAIS cacher POST
    }
    
    # Map pour URLs spécifiques
    map $request_uri $skip_cache_uri {
        default 0;
        ~*/admin/   1;  # Ne pas cacher /admin/*
        ~*/api/auth 1;  # Ne pas cacher /api/auth
    }
    
    # Map pour cookies
    map $http_cookie $skip_cache_cookie {
        default 0;
        ~*logged_in 1;  # Ne pas cacher si cookie "logged_in" existe
        ~*session   1;  # Ne pas cacher si cookie "session" existe
    }
    
    server {
        listen 80;
        server_name example.com;
        
        location / {
            proxy_pass http://localhost:3000;
            
            proxy_cache main_cache;
            proxy_cache_valid 200 10m;
            
            # === APPLIQUER CONDITIONS BYPASS ===
            proxy_cache_bypass $skip_cache_method $skip_cache_uri $skip_cache_cookie;
            proxy_no_cache $skip_cache_method $skip_cache_uri $skip_cache_cookie;
            # proxy_cache_bypass = Ne pas servir depuis cache
            # proxy_no_cache = Ne pas stocker dans cache
            
            add_header X-Cache-Status $upstream_cache_status;
            
            proxy_set_header Host $host;
        }
    }
}


# === PURGE CACHE (Vider manuellement) ===

# Méthode 1: Supprimer dossier cache (simple mais brutal)
sudo rm -rf /var/cache/nginx/proxy/*
sudo systemctl reload nginx

# Méthode 2: Module ngx_cache_purge (plus propre)
# Nécessite compilation Nginx avec module
# https://github.com/FRiCKLE/ngx_cache_purge

# Configuration avec cache_purge:
location ~ /purge(/.*) {
    allow 127.0.0.1;        # Seulement localhost
    deny all;
    proxy_cache_purge main_cache "$scheme$request_method$host$1";
}

# Utilisation:
# Purger https://example.com/page.html
curl -X PURGE http://localhost/purge/page.html

# Méthode 3: Script automatique après déploiement
#!/bin/bash
# deploy.sh
git pull
npm run build
sudo rm -rf /var/cache/nginx/proxy/*
sudo systemctl reload nginx


# === FASTCGI CACHE (Pour PHP) ===

# Cache spécifique pour PHP-FPM
# Très efficace pour WordPress, Laravel, etc.

http {
    # Zone cache FastCGI
    fastcgi_cache_path /var/cache/nginx/fastcgi
                       levels=1:2
                       keys_zone=php_cache:100m
                       max_size=10g
                       inactive=60m
                       use_temp_path=off;
    
    # Clé de cache
    fastcgi_cache_key "$scheme$request_method$host$request_uri";
    
    server {
        listen 80;
        server_name wordpress.example.com;
        root /var/www/wordpress;
        index index.php;
        
        # === CONDITIONS SKIP CACHE POUR WORDPRESS ===
        set $skip_cache 0;
        
        # POST requests = jamais cacher
        if ($request_method = POST) {
            set $skip_cache 1;
        }
        
        # Query string = jamais cacher
        if ($query_string != "") {
            set $skip_cache 1;
        }
        
        # URLs admin/login = jamais cacher
        if ($request_uri ~* "/(wp-admin|wp-login.php|login|admin)") {
            set $skip_cache 1;
        }
        
        # Utilisateur connecté = jamais cacher
        if ($http_cookie ~* "wordpress_logged_in|comment_author") {
            set $skip_cache 1;
        }
        
        location / {
            try_files $uri $uri/ /index.php?$args;
        }
        
        location ~ \.php$ {
            try_files $uri =404;
            include fastcgi_params;
            fastcgi_pass unix:/var/run/php/php8.1-fpm.sock;
            fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
            
            # === ACTIVER CACHE FASTCGI ===
            fastcgi_cache php_cache;
            fastcgi_cache_valid 200 60m;        # Cache 60 minutes
            fastcgi_cache_bypass $skip_cache;   # Appliquer conditions
            fastcgi_no_cache $skip_cache;
            
            # Header debug
            add_header X-Cache-Status $upstream_cache_status;
            add_header X-Cache-Skip $skip_cache;
        }
    }
}

# Créer dossier:
sudo mkdir -p /var/cache/nginx/fastcgi
sudo chown -R www-data:www-data /var/cache/nginx/fastcgi


# === MICROCACHING (Cache ultra-court) ===

# Microcaching = Cache de 1-10 secondes
# Parfait pour: Sites haute trafic, API publiques

# Problème sans cache:
# 1000 requêtes/seconde -> Backend génère 1000 réponses/seconde -> Crash!
#
# Avec microcaching 1 seconde:
# 1000 requêtes/seconde -> Backend génère 1 réponse/seconde -> Facile!

http {
    proxy_cache_path /var/cache/nginx/micro
                     levels=1:2
                     keys_zone=micro:10m
                     max_size=1g
                     inactive=10s;      # Supprime après 10 secondes inactif
    
    server {
        listen 80;
        server_name api.example.com;
        
        location / {
            proxy_pass http://localhost:3000;
            
            # === MICROCACHE 1 SECONDE ===
            proxy_cache micro;
            proxy_cache_valid 200 1s;           # Cache 1 seconde seulement!
            proxy_cache_lock on;                # Évite rafraîchir en même temps
            proxy_cache_use_stale updating;     # Sert ancien pendant update
            
            add_header X-Cache-Status $upstream_cache_status;
            proxy_set_header Host $host;
        }
    }
}

# Résultat:
# Pendant 1 seconde, TOUTES les requêtes servent même réponse
# Après 1 seconde, backend régénère réponse fraîche
# Backend sollicité 1 fois/seconde au lieu de 1000 fois/seconde!


# === CACHE SÉLECTIF PAR URL ===

server {
    listen 80;
    server_name example.com;
    
    # Pages statiques: cache long
    location ~* ^/(about|contact|faq)$ {
        proxy_pass http://localhost:3000;
        proxy_cache my_cache;
        proxy_cache_valid 200 24h;      # Cache 24 heures
        add_header X-Cache-Status $upstream_cache_status;
    }
    
    # API publique: microcache
    location /api/public/ {
        proxy_pass http://localhost:3000;
        proxy_cache my_cache;
        proxy_cache_valid 200 10s;      # Cache 10 secondes
        add_header X-Cache-Status $upstream_cache_status;
    }
    
    # API privée: pas de cache
    location /api/private/ {
        proxy_pass http://localhost:3000;
        proxy_cache_bypass 1;           # Toujours bypass
        add_header X-Cache-Status $upstream_cache_status;
    }
    
    # Dashboard temps réel: pas de cache
    location /dashboard {
        proxy_pass http://localhost:3000;
        proxy_cache_bypass 1;
        add_header Cache-Control "no-store, no-cache, must-revalidate";
    }
}


# === VÉRIFIER EFFICACITÉ DU CACHE ===

# Méthode 1: Headers X-Cache-Status
curl -I https://example.com/page.html

# Première requête:
# X-Cache-Status: MISS         (pas en cache)

# Deuxième requête immédiatement après:
# X-Cache-Status: HIT          (servi depuis cache [OK])


# Méthode 2: Temps de réponse
# Sans cache:
time curl https://example.com/api/data
# real: 0m2.345s  (2.3 secondes)

# Avec cache:
time curl https://example.com/api/data
# real: 0m0.015s  (15 millisecondes!)
# 150x plus rapide! [RAPIDE]


# Méthode 3: Logs Nginx
tail -f /var/log/nginx/access.log

# Regardez le $upstream_cache_status si configuré dans log_format


# Méthode 4: Taille du cache
du -sh /var/cache/nginx/proxy/
# Affiche: 234M (234 méga-octets utilisés)


# === STRATÉGIES DE CACHE PAR TYPE DE SITE ===

# 1⃣ SITE VITRINE (contenu change rarement)
# - Images/CSS/JS: 1 an
# - Pages HTML: 1 jour ou 1 semaine
location / {
    proxy_cache my_cache;
    proxy_cache_valid 200 1w;  # 1 semaine
}

# 2⃣ BLOG / NEWS (nouveau contenu régulier)
# - Images/CSS/JS: 1 mois
# - Articles: 1 heure à 1 jour
# - Page d'accueil: 10-30 minutes
location / {
    proxy_cache my_cache;
    proxy_cache_valid 200 1h;  # 1 heure
}

# 3⃣ E-COMMERCE (prix changent)
# - Produits: 5-15 minutes
# - Panier: PAS de cache
# - Images: 1 an
location /products/ {
    proxy_cache my_cache;
    proxy_cache_valid 200 10m;  # 10 minutes
}
location /cart/ {
    proxy_cache_bypass 1;  # Jamais cacher panier
}

# 4⃣ API PUBLIQUE (données temps réel)
# - Microcache: 1-10 secondes
location /api/ {
    proxy_cache my_cache;
    proxy_cache_valid 200 5s;  # 5 secondes
}

# 5⃣ APPLICATION TEMPS RÉEL (chat, dashboard)
# - PAS de cache serveur
# - Seulement cache navigateur pour assets
location /app/ {
    proxy_cache_bypass 1;
    proxy_no_cache 1;
}


# === ERREURS COURANTES ===

# [X] ERREUR 1: Cache jamais HIT
# Cause possible: Cookies ou query string différents
# Solution: Vérifier cache key
proxy_cache_key "$scheme$request_method$host$request_uri";
# Si cookies varient, ajouter:
proxy_ignore_headers Set-Cookie;

# [X] ERREUR 2: Contenu obsolète affiché
# Cause: Cache trop long
# Solution: Réduire durée ou purger cache
proxy_cache_valid 200 5m;  # Au lieu de 1h

# [X] ERREUR 3: Espace disque plein
# Cause: max_size trop grand
# Solution: Réduire ou nettoyer
sudo rm -rf /var/cache/nginx/proxy/*

# [X] ERREUR 4: Utilisateurs voient données d'autres users
# Cause: Cache réponses personnalisées
# Solution: Bypass cache pour users connectés
if ($http_cookie ~* "session") {
    set $skip_cache 1;
}


# === RÉSUMÉ CACHE ===

# 1. Cache navigateur (fichiers statiques):
location ~* \.(jpg|css|js)$ {
    expires 1y;
    add_header Cache-Control "public, immutable";
}

# 2. Cache proxy (backend):
http {
    proxy_cache_path /var/cache/nginx/proxy
                     keys_zone=my_cache:10m
                     max_size=1g;
    
    server {
        location / {
            proxy_cache my_cache;
            proxy_cache_valid 200 10m;
            add_header X-Cache-Status $upstream_cache_status;
        }
    }
}

# 3. Bypass cache (conditions):
proxy_cache_bypass $skip_cache;
proxy_no_cache $skip_cache;

# 4. Test:
curl -I https://example.com/page
# Regarder X-Cache-Status: HIT/MISS

# 5. Purge:
sudo rm -rf /var/cache/nginx/proxy/*
sudo systemctl reload nginx

# Gains typiques:
# Sans cache: 500ms-2s par page
# Avec cache: 10-50ms par page
# Amélioration: 10-100x plus rapide! [RAPIDE]

# === QU'EST-CE QUE SSL/TLS ? ===

# HTTP = Communication en clair (non chiffrée)
# Comme envoyer une carte postale: tout le monde peut lire
#
# HTTPS = Communication chiffrée (sécurisée)
# Comme une lettre dans une enveloppe scellée: seul le destinataire peut lire

# Pourquoi HTTPS est OBLIGATOIRE aujourd'hui ?
# [OK] Sécurité: Données chiffrées (mots de passe, infos bancaires)
# [OK] Confiance: Cadenas vert dans navigateur
# [OK] SEO: Google favorise sites HTTPS dans classement
# [OK] Performance: HTTP/2 nécessite HTTPS (plus rapide)
# [OK] APIs: Beaucoup d'APIs modernes exigent HTTPS
# [OK] Cookies sécurisés: Cookies avec flag "Secure"

# SSL vs TLS:
# SSL = Ancien protocole (obsolète, non sécurisé)
# TLS = Nouveau protocole (remplace SSL)
# On dit souvent "SSL" mais on parle en fait de TLS
# TLS 1.2 et TLS 1.3 = versions modernes et sécurisées


# === CERTIFICAT SSL: QU'EST-CE QUE C'EST ? ===

# Un certificat SSL contient:
# 1. Votre nom de domaine (example.com)
# 2. Votre clé publique
# 3. Signature d'une autorité de certification (CA)
# 4. Date d'expiration (généralement 90 jours avec Let's Encrypt)

# Analogie: Comme une carte d'identité pour votre site web
# - Prouve que vous êtes bien propriétaire du domaine
# - Permet de chiffrer communications

# Types de certificats:
# 1. Domain Validation (DV) - Basique, gratuit avec Let's Encrypt
#    Vérifie seulement que vous possédez le domaine
#
# 2. Organization Validation (OV) - Moyen, payant
#    Vérifie l'organisation derrière le site
#
# 3. Extended Validation (EV) - Premium, payant
#    Vérification poussée, affiche nom entreprise dans barre adresse


# === OBTENIR UN CERTIFICAT GRATUIT AVEC LET'S ENCRYPT ===

# Let's Encrypt = Autorité de certification gratuite
# Certificats valides 90 jours, renouvellement automatique
# Utilisé par des millions de sites (même par grandes entreprises)

# Étape 1: Installer Certbot (client Let's Encrypt)
# Ubuntu/Debian:
sudo apt update
sudo apt install certbot python3-certbot-nginx

# CentOS/RHEL:
sudo yum install certbot python3-certbot-nginx

# Étape 2: Obtenir certificat (méthode AUTOMATIQUE - recommandée)
sudo certbot --nginx -d example.com -d www.example.com

# Explication de la commande:
# --nginx           -> Certbot modifie automatiquement config Nginx
# -d example.com    -> Premier domaine
# -d www.example.com -> Deuxième domaine (optionnel)

# Certbot va:
# 1. Vérifier que vous possédez le domaine
# 2. Obtenir le certificat
# 3. Modifier automatiquement votre config Nginx
# 4. Configurer redirection HTTP -> HTTPS
# 5. Configurer renouvellement automatique

# Questions posées par Certbot:
# "Email address" -> Votre email (pour alertes expiration)
# "Terms of Service" -> A = Accepter
# "Share email" -> N = Non (optionnel)
# "Redirect HTTP to HTTPS?" -> 2 = Oui (recommandé)

# Étape 3: Tester dans navigateur
# Visitez https://example.com
# Vous devriez voir le cadenas vert ! [VERROUILLE]


# === RENOUVELLEMENT AUTOMATIQUE ===

# Certificats Let's Encrypt expirent après 90 jours
# Mais Certbot configure AUTOMATIQUEMENT le renouvellement !

# Vérifier que renouvellement auto fonctionne:
sudo certbot renew --dry-run

# Si "Congratulations, all simulated renewals succeeded"
# -> Tout est OK ! Renouvellement automatique configuré

# Certbot ajoute une tâche cron ou systemd timer:
# Ubuntu: /etc/cron.d/certbot
# CentOS: systemd timer

# Vérifier le timer (Ubuntu/Debian moderne):
sudo systemctl list-timers | grep certbot

# Forcer renouvellement manuel (pas besoin normalement):
sudo certbot renew

# Voir tous vos certificats:
sudo certbot certificates


# === CONFIGURATION SSL DE BASE (Créée par Certbot) ===

# Après certbot --nginx, voici à quoi ressemble votre config:

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

server {
    listen 443 ssl http2;      # Port 443 = HTTPS, http2 = HTTP/2
    listen [::]:443 ssl http2; # IPv6
    
    server_name example.com www.example.com;
    
    # Chemins certificats
    ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;
    
    # Config SSL automatique de Certbot
    include /etc/letsencrypt/options-ssl-nginx.conf;
    ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem;
    
    # Votre configuration habituelle
    root /var/www/example;
    index index.html;
    
    location / {
        try_files $uri $uri/ =404;
    }
}


# === COMPRENDRE LES FICHIERS CERTIFICAT ===

# Let's Encrypt crée plusieurs fichiers dans:
# /etc/letsencrypt/live/example.com/

# cert.pem           -> Certificat de votre domaine uniquement
# chain.pem          -> Chaîne des certificats intermédiaires
# fullchain.pem      -> cert.pem + chain.pem (UTILISEZ CELUI-CI)
# privkey.pem        -> Clé privée (GARDER SECRET!)

# Dans Nginx, toujours utiliser:
ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;

# IMPORTANT: Ne JAMAIS partager ou commiter privkey.pem !
# C'est comme le mot de passe de votre certificat


# === CONFIGURATION SSL OPTIMALE (Sécurité maximale) ===

server {
    # Redirection HTTP -> HTTPS
    listen 80;
    listen [::]:80;
    server_name example.com www.example.com;
    return 301 https://$server_name$request_uri;
}

server {
    # HTTPS
    listen 443 ssl http2;
    listen [::]:443 ssl http2;
    server_name example.com www.example.com;
    
    # === CERTIFICATS ===
    ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;
    
    # === PROTOCOLES SSL/TLS ===
    # Utiliser SEULEMENT TLS 1.2 et 1.3 (sécurisés)
    ssl_protocols TLSv1.2 TLSv1.3;
    
    # NE PAS utiliser:
    # ssl_protocols TLSv1 TLSv1.1;  # Obsolètes et vulnérables
    
    # === CIPHERS (Algorithmes de chiffrement) ===
    # Liste des ciphers sécurisés
    ssl_ciphers 'ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305';
    
    # Laisser client choisir (TLS 1.3)
    ssl_prefer_server_ciphers off;
    
    # === DH PARAMETERS (Diffie-Hellman) ===
    # Pour Perfect Forward Secrecy
    ssl_dhparam /etc/ssl/certs/dhparam.pem;
    
    # Générer dhparam (une seule fois, prend du temps):
    # sudo openssl dhparam -out /etc/ssl/certs/dhparam.pem 4096
    
    # === SESSION CACHE ===
    # Réutilise session SSL (performance)
    ssl_session_cache shared:SSL:10m;  # 10MB partagés entre workers
    ssl_session_timeout 10m;           # Session valide 10 minutes
    ssl_session_tickets off;           # Désactiver tickets (sécurité)
    
    # === OCSP STAPLING ===
    # Vérifie révocation certificat (performance)
    ssl_stapling on;
    ssl_stapling_verify on;
    ssl_trusted_certificate /etc/letsencrypt/live/example.com/chain.pem;
    resolver 8.8.8.8 8.8.4.4 valid=300s;  # DNS Google
    resolver_timeout 5s;
    
    # === HEADERS DE SÉCURITÉ ===
    # HSTS: Force HTTPS pendant 2 ans
    add_header Strict-Transport-Security "max-age=63072000; includeSubDomains; preload" always;
    
    # Empêche affichage dans iframe (clickjacking)
    add_header X-Frame-Options "SAMEORIGIN" always;
    
    # Empêche sniffing MIME type
    add_header X-Content-Type-Options "nosniff" always;
    
    # Protection XSS (obsolète mais toujours bon)
    add_header X-XSS-Protection "1; mode=block" always;
    
    # Votre configuration habituelle
    root /var/www/example;
    location / {
        try_files $uri $uri/ =404;
    }
}


# === GÉNÉRER DH PARAMETERS ===

# C'est une étape optionnelle mais recommandée pour sécurité maximale
# Génère paramètres Diffie-Hellman pour Perfect Forward Secrecy

# Générer fichier dhparam (PREND DU TEMPS - 5 à 30 minutes):
sudo openssl dhparam -out /etc/ssl/certs/dhparam.pem 4096

# Ou plus rapide (moins sécurisé mais acceptable):
sudo openssl dhparam -out /etc/ssl/certs/dhparam.pem 2048

# Ajouter dans votre config:
ssl_dhparam /etc/ssl/certs/dhparam.pem;

# Note: Certbot crée déjà un dhparam dans:
# /etc/letsencrypt/ssl-dhparams.pem
# Vous pouvez l'utiliser au lieu d'en créer un nouveau


# === TESTER VOTRE CONFIGURATION SSL ===

# 1. Test local basique
curl -I https://example.com

# Devrait afficher HTTP/2 200 sans erreurs SSL

# 2. Test SSL Labs (TRÈS COMPLET - RECOMMANDÉ)
# Visitez: https://www.ssllabs.com/ssltest/
# Entrez votre domaine
# Attendez 2-3 minutes
# Objectif: Score A+ !

# 3. Test en ligne de commande
openssl s_client -connect example.com:443 -servername example.com

# Vérifier:
# - Protocol: TLSv1.3 ou TLSv1.2 [OK]
# - Cipher: ECDHE-RSA-AES256-GCM-SHA384 ou similaire [OK]
# - Verify return code: 0 (ok) [OK]

# 4. Vérifier date expiration
echo | openssl s_client -connect example.com:443 2>/dev/null | openssl x509 -noout -dates

# Affiche:
# notBefore=...
# notAfter=... (date expiration)


# === CERTIFICAT WILDCARD (Sous-domaines) ===

# Certificat wildcard = Couvre *.example.com
# Fonctionne pour: app.example.com, api.example.com, blog.example.com

# Obtenir certificat wildcard avec Let's Encrypt:
sudo certbot certonly --manual --preferred-challenges dns -d example.com -d *.example.com

# Certbot demandera:
# "Add DNS TXT record: _acme-challenge.example.com with value: xxx"
#
# Étapes:
# 1. Aller dans panneau DNS de votre hébergeur
# 2. Ajouter enregistrement TXT:
#    Nom: _acme-challenge
#    Valeur: (celle donnée par Certbot)
# 3. Attendre propagation DNS (1-30 minutes)
#    Vérifier: dig _acme-challenge.example.com TXT
# 4. Appuyer Enter dans Certbot
# 5. Certificat émis !

# Utiliser dans Nginx:
server {
    listen 443 ssl http2;
    server_name *.example.com;  # Tous sous-domaines
    
    ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;
    
    # ...
}


# === PLUSIEURS CERTIFICATS (Multi-domaines) ===

# Situation: Plusieurs sites sur même serveur
# Solution: Un certificat par site

# Site 1: example.com
server {
    listen 443 ssl http2;
    server_name example.com www.example.com;
    
    ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;
    
    root /var/www/example;
}

# Site 2: autresite.com
server {
    listen 443 ssl http2;
    server_name autresite.com www.autresite.com;
    
    ssl_certificate /etc/letsencrypt/live/autresite.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/autresite.com/privkey.pem;
    
    root /var/www/autresite;
}

# Obtenir certificats:
sudo certbot --nginx -d example.com -d www.example.com
sudo certbot --nginx -d autresite.com -d www.autresite.com


# === REDIRECTION WWW <-> NON-WWW ===

# Décision à prendre: example.com OU www.example.com ?
# Google les considère comme 2 sites différents !
# Choisissez un et redirigez l'autre

# Option 1: Rediriger www -> non-www
server {
    listen 443 ssl http2;
    server_name www.example.com;  # Avec www
    
    ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;
    
    # Redirection vers version sans www
    return 301 https://example.com$request_uri;
}

server {
    listen 443 ssl http2;
    server_name example.com;  # Sans www (version principale)
    
    ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;
    
    root /var/www/example;
    # ... votre config normale
}


# Option 2: Rediriger non-www -> www
server {
    listen 443 ssl http2;
    server_name example.com;  # Sans www
    
    ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;
    
    # Redirection vers version avec www
    return 301 https://www.example.com$request_uri;
}

server {
    listen 443 ssl http2;
    server_name www.example.com;  # Avec www (version principale)
    
    ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;
    
    root /var/www/example;
    # ... votre config normale
}


# === HTTPS AVEC REVERSE PROXY ===

# Situation: Nginx en HTTPS, backend en HTTP
# C'est le cas le plus courant !

server {
    # HTTP -> HTTPS
    listen 80;
    server_name app.example.com;
    return 301 https://$server_name$request_uri;
}

server {
    # HTTPS
    listen 443 ssl http2;
    server_name app.example.com;
    
    # Certificats
    ssl_certificate /etc/letsencrypt/live/app.example.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/app.example.com/privkey.pem;
    include /etc/letsencrypt/options-ssl-nginx.conf;
    
    location / {
        # Backend en HTTP (pas de 's')
        proxy_pass http://localhost:3000;
        
        # Important: Dire au backend que requête originale était HTTPS
        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;  # https
        
        # Si backend génère URLs, il saura qu'il faut HTTPS
    }
}

# Votre app backend reste en HTTP simple:
# const app = express();
# app.listen(3000, 'localhost');  // HTTP sur localhost seulement
#
# Nginx gère tout le SSL !


# === ERREURS COURANTES ===

# [X] ERREUR 1: "NET::ERR_CERT_AUTHORITY_INVALID"
# Cause: Certificat pas encore actif ou mal configuré
# Solution:
# - Vérifier certificat existe:
ls -l /etc/letsencrypt/live/example.com/
# - Vérifier permissions:
sudo chmod 644 /etc/letsencrypt/live/example.com/fullchain.pem
# - Tester config:
sudo nginx -t
# - Vérifier que domaine pointe vers votre serveur:
dig example.com


# [X] ERREUR 2: "Too many certificates already issued"
# Cause: Let's Encrypt limite à 50 certificats/semaine par domaine
# Solution:
# - Attendre 7 jours
# - Utiliser staging (test):
sudo certbot --nginx --staging -d example.com


# [X] ERREUR 3: Renouvellement échoue
# Cause: Nginx bloque /.well-known/acme-challenge/
# Solution: Ajouter dans votre config:
location ~ /.well-known/acme-challenge {
    allow all;
    root /var/www/example;
}


# [X] ERREUR 4: Mixed content (cadenas barré)
# Cause: Page HTTPS charge ressources HTTP
# Exemple: <img src="http://example.com/image.jpg">
# Solution: Utiliser HTTPS partout ou chemins relatifs
# <img src="/image.jpg"> ou <img src="https://example.com/image.jpg">


# [X] ERREUR 5: "ssl_certificate not found"
# Cause: Chemin incorrect
# Solution:
# Vérifier chemin exact:
sudo certbot certificates
# Copier chemin affiché


# === CERTIFICAT AUTO-SIGNÉ (Pour test local UNIQUEMENT) ===

# Pour développement local (PAS pour production!)

# Générer certificat auto-signé:
sudo openssl req -x509 -nodes -days 365 -newkey rsa:2048 \
    -keyout /etc/ssl/private/nginx-selfsigned.key \
    -out /etc/ssl/certs/nginx-selfsigned.crt

# Répondre aux questions (peu importe pour test):
# Common Name: localhost

# Config Nginx:
server {
    listen 443 ssl http2;
    server_name localhost;
    
    ssl_certificate /etc/ssl/certs/nginx-selfsigned.crt;
    ssl_certificate_key /etc/ssl/private/nginx-selfsigned.key;
    
    # ...
}

# Note: Navigateur affichera avertissement sécurité
# C'est normal ! Cliquez "Avancé" -> "Continuer vers le site"
# À utiliser SEULEMENT en développement local !


# === SNIPPET SSL RÉUTILISABLE ===

# Créer snippet pour éviter répétition
# /etc/nginx/snippets/ssl-params.conf
ssl_protocols TLSv1.2 TLSv1.3;
ssl_prefer_server_ciphers off;
ssl_ciphers 'ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384';
ssl_session_cache shared:SSL:10m;
ssl_session_timeout 10m;
ssl_session_tickets off;
ssl_stapling on;
ssl_stapling_verify on;
resolver 8.8.8.8 8.8.4.4 valid=300s;
resolver_timeout 5s;

# Headers sécurité
add_header Strict-Transport-Security "max-age=63072000; includeSubDomains; preload" always;
add_header X-Frame-Options "SAMEORIGIN" always;
add_header X-Content-Type-Options "nosniff" always;

# Utilisation:
server {
    listen 443 ssl http2;
    server_name example.com;
    
    ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;
    
    include snippets/ssl-params.conf;  # Inclut toute la config SSL
    
    # ... votre config
}


# === RÉSUMÉ SSL/TLS ===

# Installation Let's Encrypt:
sudo apt install certbot python3-certbot-nginx

# Obtenir certificat (automatique):
sudo certbot --nginx -d example.com -d www.example.com

# Configuration minimale:
server {
    listen 443 ssl http2;
    server_name example.com;
    
    ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;
    include /etc/letsencrypt/options-ssl-nginx.conf;
    
    # votre config...
}

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

# Test:
# 1. https://www.ssllabs.com/ssltest/
# 2. Visitez https://example.com
# 3. Vérifiez cadenas vert [VERROUILLE]

# Renouvellement automatique:
sudo certbot renew --dry-run  # Test
# Certbot renouvelle automatiquement avant expiration


# === Configuration SSL de base ===

server {
    listen 443 ssl http2;
    listen [::]:443 ssl http2;
    
    server_name example.com www.example.com;
    
    # Certificats
    ssl_certificate /etc/ssl/certs/example.com.crt;
    ssl_certificate_key /etc/ssl/private/example.com.key;
    
    # Configuration SSL
    ssl_protocols TLSv1.2 TLSv1.3;
    ssl_prefer_server_ciphers on;
    ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384;
    
    root /var/www/example;
    index index.html;
    
    location / {
        try_files $uri $uri/ =404;
    }
}

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


# === SSL avec Let's Encrypt ===

# 1. Installer Certbot
sudo apt install certbot python3-certbot-nginx

# 2. Obtenir certificat
sudo certbot --nginx -d example.com -d www.example.com

# 3. Renouvellement automatique (déjà configuré)
sudo certbot renew --dry-run

# Configuration générée par Certbot
server {
    listen 443 ssl http2;
    server_name example.com www.example.com;
    
    ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;
    include /etc/letsencrypt/options-ssl-nginx.conf;
    ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem;
    
    # Votre configuration...
}


# === Configuration SSL optimale ===

server {
    listen 443 ssl http2;
    server_name example.com;
    
    # Certificats
    ssl_certificate /etc/ssl/certs/example.com.crt;
    ssl_certificate_key /etc/ssl/private/example.com.key;
    
    # Protocoles (seulement TLS 1.2 et 1.3)
    ssl_protocols TLSv1.2 TLSv1.3;
    
    # Ciphers
    ssl_ciphers 'ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384';
    ssl_prefer_server_ciphers off;
    
    # DH parameters
    ssl_dhparam /etc/ssl/certs/dhparam.pem;
    
    # Session cache
    ssl_session_cache shared:SSL:10m;
    ssl_session_timeout 10m;
    ssl_session_tickets off;
    
    # OCSP Stapling
    ssl_stapling on;
    ssl_stapling_verify on;
    ssl_trusted_certificate /etc/ssl/certs/chain.pem;
    resolver 8.8.8.8 8.8.4.4 valid=300s;
    resolver_timeout 5s;
    
    # Security headers
    add_header Strict-Transport-Security "max-age=63072000; includeSubDomains; preload" always;
    add_header X-Frame-Options "SAMEORIGIN" always;
    add_header X-Content-Type-Options "nosniff" always;
    add_header X-XSS-Protection "1; mode=block" always;
    
    # Votre configuration...
}

# Générer DH parameters
sudo openssl dhparam -out /etc/ssl/certs/dhparam.pem 4096


# === SSL avec client certificate (mTLS) ===

server {
    listen 443 ssl http2;
    server_name secure.example.com;
    
    ssl_certificate /etc/ssl/certs/server.crt;
    ssl_certificate_key /etc/ssl/private/server.key;
    
    # Client certificate
    ssl_client_certificate /etc/ssl/certs/ca.crt;
    ssl_verify_client on;                   # Obligatoire
    # ssl_verify_client optional;           # Optionnel
    ssl_verify_depth 2;
    
    location / {
        # Variables disponibles:
        # $ssl_client_s_dn - DN du certificat client
        # $ssl_client_serial - Numéro série
        # $ssl_client_verify - Résultat vérification
        
        proxy_set_header X-SSL-Client-DN $ssl_client_s_dn;
        proxy_pass http://backend;
    }
}


[OK] GESTION DES LOGS - SURVEILLER ET ANALYSER

# === COMPRENDRE LES LOGS NGINX ===

# Nginx génère 2 types de logs principaux:

# 1. ACCESS LOG (access.log)
#    Enregistre TOUTES les requêtes HTTP
#    Qui visite ? Quand ? Quelle page ? Quel code statut ?
#
# 2. ERROR LOG (error.log)
#    Enregistre les ERREURS et problèmes
#    Erreurs 404, 500, problèmes configuration, etc.

# Emplacement par défaut:
# /var/log/nginx/access.log
# /var/log/nginx/error.log


# === FORMAT DES LOGS ACCESS ===

# Format par défaut (combined)
log_format combined '$remote_addr - $remote_user [$time_local] '
                    '"$request" $status $body_bytes_sent '
                    '"$http_referer" "$http_user_agent"';

# Exemple ligne de log:
# 203.0.113.45 - - [13/Nov/2024:10:30:45 +0000] "GET /page.html HTTP/1.1" 200 2534 "https://google.com" "Mozilla/5.0 ..."

# Décortication:
# 203.0.113.45              -> IP du visiteur
# -                         -> Identifiant remote user (rarement utilisé)
# -                         -> Utilisateur authentifié (si auth_basic)
# [13/Nov/2024:10:30:45]    -> Date et heure
# "GET /page.html HTTP/1.1" -> Méthode + URI + Protocole
# 200                       -> Code statut HTTP (200 = OK)
# 2534                      -> Taille réponse en bytes
# "https://google.com"      -> Referer (d'où vient visiteur)
# "Mozilla/5.0 ..."         -> User agent (navigateur)


# === FORMATS DE LOG PERSONNALISÉS ===

http {
    # === FORMAT JSON (Pour parsing automatique) ===
    log_format json_combined escape=json
    '{'
        '"time":"$time_local",'
        '"remote_addr":"$remote_addr",'
        '"request":"$request",'
        '"status":"$status",'
        '"body_bytes_sent":"$body_bytes_sent",'
        '"request_time":"$request_time",'
        '"upstream_response_time":"$upstream_response_time",'
        '"http_referer":"$http_referer",'
        '"http_user_agent":"$http_user_agent"'
    '}';
    
    # Exemple sortie JSON:
    # {"time":"13/Nov/2024:10:30:45","remote_addr":"203.0.113.45","request":"GET /api HTTP/1.1","status":"200","body_bytes_sent":"1234","request_time":"0.052","upstream_response_time":"0.048","http_referer":"","http_user_agent":"curl/7.68.0"}
    
    
    # === FORMAT DÉTAILLÉ (Avec temps de réponse) ===
    log_format detailed '$remote_addr - $remote_user [$time_local] '
                       '"$request" $status $body_bytes_sent '
                       '"$http_referer" "$http_user_agent" '
                       'rt=$request_time uct="$upstream_connect_time" '
                       'uht="$upstream_header_time" urt="$upstream_response_time"';
    
    # Variables importantes:
    # $request_time              -> Temps total traitement (secondes)
    # $upstream_connect_time     -> Temps connexion backend
    # $upstream_header_time      -> Temps recevoir headers backend
    # $upstream_response_time    -> Temps réponse complète backend
    
    
    # === FORMAT MINIMAL (Performance) ===
    log_format minimal '$remote_addr $status $request_time';
    # Seulement essentiel: IP, statut, temps
    
    
    # === Utiliser format personnalisé ===
    server {
        listen 80;
        server_name example.com;
        
        # Utiliser format JSON
        access_log /var/log/nginx/example-access.log json_combined;
        
        # Ou format détaillé
        # access_log /var/log/nginx/example-access.log detailed;
        
        location / {
            root /var/www/example;
        }
    }
}


# === LOGS PAR SITE/LOCATION ===

server {
    listen 80;
    server_name example.com;
    
    # Logs globaux du site
    access_log /var/log/nginx/example-access.log;
    error_log /var/log/nginx/example-error.log;
    
    # API avec logs séparés
    location /api/ {
        access_log /var/log/nginx/api-access.log;
        error_log /var/log/nginx/api-error.log;
        proxy_pass http://localhost:3000;
    }
    
    # Admin avec logs séparés
    location /admin/ {
        access_log /var/log/nginx/admin-access.log;
        error_log /var/log/nginx/admin-error.log;
        root /var/www/admin;
    }
    
    # Images sans logs (économise espace)
    location ~* \.(jpg|jpeg|png|gif)$ {
        access_log off;  # Désactiver logs
        expires 1y;
    }
}


# === LOGS CONDITIONNELS ===

# Logger seulement certaines requêtes

http {
    # Map pour définir condition
    map $status $loggable {
        ~^[23]  0;      # Ne PAS logger codes 2xx et 3xx (succès)
        default 1;      # Logger tout le reste (erreurs)
    }
    
    server {
        listen 80;
        server_name example.com;
        
        # Logger seulement si $loggable = 1
        access_log /var/log/nginx/errors-only.log combined if=$loggable;
        
        location / {
            root /var/www/example;
        }
    }
}

# Autre exemple: Logger seulement requêtes lentes
map $request_time $slow_request {
    default 0;
    ~^[1-9] 1;  # Logger si temps > 1 seconde
}

access_log /var/log/nginx/slow-requests.log combined if=$slow_request;


# === BUFFER LOGS (Performance) ===

# Écrire logs par batch au lieu de chaque requête
server {
    listen 80;
    server_name example.com;
    
    # Buffer de 32KB, flush toutes les 5 secondes
    access_log /var/log/nginx/example-access.log combined buffer=32k flush=5s;
    
    # Réduit écritures disque = meilleure performance
    # Compromise: Logs peuvent être perdus si crash durant 5 secondes
}


# === ROTATION DES LOGS ===

# Problème: Logs grandissent infiniment -> Disque plein!
# Solution: Rotation = Archiver vieux logs, créer nouveaux

# Nginx utilise logrotate (installé par défaut sur Ubuntu/Debian)
# Configuration: /etc/logrotate.d/nginx

# Voir config actuelle:
cat /etc/logrotate.d/nginx

# Configuration type:
/var/log/nginx/*.log {
    daily                       # Rotation quotidienne
    missingok                   # Pas d'erreur si fichier absent
    rotate 14                   # Garder 14 jours d'historique
    compress                    # Compresser vieux logs (gzip)
    delaycompress               # Compresser au cycle suivant (pas immédiat)
    notifempty                  # Ne pas rotater fichier vide
    create 0640 www-data adm    # Permissions nouveaux fichiers
    sharedscripts
    postrotate
        # Dire à Nginx de rouvrir fichiers logs
        if [ -f /var/run/nginx.pid ]; then
            kill -USR1 `cat /var/run/nginx.pid`
        fi
    endscript
}

# Tester rotation manuellement:
sudo logrotate -f /etc/logrotate.d/nginx

# Vérifier logs après rotation:
ls -lh /var/log/nginx/
# Vous verrez:
# access.log              (actuel)
# access.log.1            (hier, non compressé)
# access.log.2.gz         (avant-hier, compressé)
# access.log.3.gz         (il y a 3 jours)
# etc.


# === ANALYSER LES LOGS ===

# === 1. Voir logs en temps réel ===
sudo tail -f /var/log/nginx/access.log
sudo tail -f /var/log/nginx/error.log

# Voir dernières 100 lignes:
sudo tail -n 100 /var/log/nginx/access.log

# Voir uniquement erreurs 404:
sudo tail -f /var/log/nginx/access.log | grep " 404 "

# Voir uniquement erreurs 5xx:
sudo tail -f /var/log/nginx/access.log | grep " 5[0-9][0-9] "


# === 2. Statistiques basiques ===

# Nombre total de requêtes:
wc -l /var/log/nginx/access.log
# Affiche: 125478 (125k requêtes)

# Top 10 IPs les plus actives:
awk '{print $1}' /var/log/nginx/access.log | sort | uniq -c | sort -rn | head -10
# Affiche:
#   5234 203.0.113.45
#   3421 198.51.100.78
#   2156 192.0.2.123
#   ...

# Top 10 pages les plus visitées:
awk '{print $7}' /var/log/nginx/access.log | sort | uniq -c | sort -rn | head -10
# $7 = URI demandée
# Affiche:
#   8945 /
#   3421 /about
#   2156 /contact
#   ...

# Codes de statut HTTP:
awk '{print $9}' /var/log/nginx/access.log | sort | uniq -c | sort -rn
# $9 = code statut
# Affiche:
#   98234 200  (succès)
#   4521 304   (not modified)
#   892 404    (not found)
#   45 500     (erreur serveur)

# Temps de réponse moyen (si dans logs):
awk '{sum+=$NF; count++} END {print sum/count}' /var/log/nginx/access.log
# $NF = dernier champ (request_time)

# Requêtes par heure:
awk '{print $4}' /var/log/nginx/access.log | cut -d: -f1-2 | sort | uniq -c
# Affiche:
#   1234 [13/Nov/2024:10
#   2345 [13/Nov/2024:11
#   3456 [13/Nov/2024:12

# User agents (navigateurs):
awk -F'"' '{print $6}' /var/log/nginx/access.log | sort | uniq -c | sort -rn | head
# Affiche navigateurs les plus courants

# Referers (d'où viennent visiteurs):
awk -F'"' '{print $4}' /var/log/nginx/access.log | sort | uniq -c | sort -rn | head


# === 3. GOACCESS (Analyseur graphique - RECOMMANDÉ) ===

# GoAccess = Outil génial pour analyser logs visuellement
# Installation:
sudo apt install goaccess

# Analyse en temps réel dans terminal:
sudo goaccess /var/log/nginx/access.log -c

# Options:
# - Flèches pour naviguer
# - TAB pour changer de panel
# - q pour quitter

# Générer rapport HTML:
sudo goaccess /var/log/nginx/access.log -o /var/www/html/report.html --log-format=COMBINED

# Visitez http://example.com/report.html
# Vous verrez:
# - Visiteurs par pays
# - Pages les plus visitées
# - Navigateurs utilisés
# - Codes statut
# - Graphiques temporels
# - Et bien plus!

# Mettre à jour rapport automatiquement:
# Crontab (toutes les heures):
0 * * * * sudo goaccess /var/log/nginx/access.log -o /var/www/html/report.html --log-format=COMBINED

# Rapport temps réel (WebSocket):
sudo goaccess /var/log/nginx/access.log -o /var/www/html/report.html --log-format=COMBINED --real-time-html --ws-url=wss://example.com


# === 4. JOURNALCTL (Pour logs systemd) ===

# Voir logs Nginx via systemd:
sudo journalctl -u nginx

# Logs en temps réel:
sudo journalctl -u nginx -f

# Logs depuis aujourd'hui:
sudo journalctl -u nginx --since today

# Logs depuis hier:
sudo journalctl -u nginx --since yesterday

# Logs dernière heure:
sudo journalctl -u nginx --since "1 hour ago"

# Logs avec priorité erreur uniquement:
sudo journalctl -u nginx -p err


# === CENTRALISER LES LOGS (Production) ===

# Pour plusieurs serveurs, centraliser logs dans un endroit

# Solution 1: ELK Stack (Elasticsearch, Logstash, Kibana)
# - Puissant mais complexe
# - Idéal pour grandes infrastructures

# Solution 2: Rsyslog (Plus simple)
# Configuration Nginx pour envoyer logs vers rsyslog:

http {
    access_log syslog:server=192.168.1.100:514,tag=nginx_access combined;
    error_log syslog:server=192.168.1.100:514,tag=nginx_error error;
}

# Solution 3: Loki + Grafana (Moderne)
# - Plus léger que ELK
# - Bonne intégration Grafana


# === NIVEAUX ERROR LOG ===

# error_log peut avoir différents niveaux de verbosité:

# Niveau debug (TRÈS bavard - développement seulement):
error_log /var/log/nginx/error.log debug;

# Niveau info:
error_log /var/log/nginx/error.log info;

# Niveau notice:
error_log /var/log/nginx/error.log notice;

# Niveau warn (warnings):
error_log /var/log/nginx/error.log warn;

# Niveau error (DÉFAUT - erreurs uniquement):
error_log /var/log/nginx/error.log error;

# Niveau crit (critique):
error_log /var/log/nginx/error.log crit;

# Niveau alert:
error_log /var/log/nginx/error.log alert;

# Niveau emerg (urgence):
error_log /var/log/nginx/error.log emerg;

# Recommandation production: warn ou error


# === RÉSUMÉ LOGS ===

# Voir logs en temps réel:
sudo tail -f /var/log/nginx/access.log
sudo tail -f /var/log/nginx/error.log

# Format personnalisé:
log_format detailed '$remote_addr [$time_local] "$request" $status $request_time';
access_log /var/log/nginx/access.log detailed;

# Logs par site:
server {
    access_log /var/log/nginx/monsite-access.log;
    error_log /var/log/nginx/monsite-error.log;
}

# Statistiques rapides:
# Top IPs:
awk '{print $1}' access.log | sort | uniq -c | sort -rn | head

# Top pages:
awk '{print $7}' access.log | sort | uniq -c | sort -rn | head

# Codes statut:
awk '{print $9}' access.log | sort | uniq -c | sort -rn

# Analyse graphique:
sudo goaccess /var/log/nginx/access.log -c

# Rapport HTML:
sudo goaccess /var/log/nginx/access.log -o report.html --log-format=COMBINED


[OK] CACHE HTTP


# === Cache de base ===

http {
    # Zone de cache
    proxy_cache_path /var/cache/nginx/proxy
                     levels=1:2
                     keys_zone=my_cache:10m
                     max_size=1g
                     inactive=60m
                     use_temp_path=off;
    
    server {
        listen 80;
        server_name example.com;
        
        location / {
            proxy_pass http://backend;
            
            # Activer cache
            proxy_cache my_cache;
            proxy_cache_valid 200 302 10m;
            proxy_cache_valid 404 1m;
            
            # Headers cache
            proxy_cache_use_stale error timeout http_500 http_502 http_503;
            proxy_cache_background_update on;
            proxy_cache_lock on;
            
            # Header pour debug
            add_header X-Cache-Status $upstream_cache_status;
        }
    }
}


# === Cache avancé ===

http {
    # Zone cache principale
    proxy_cache_path /var/cache/nginx/main
                     levels=1:2
                     keys_zone=main_cache:50m
                     max_size=10g
                     inactive=1h
                     use_temp_path=off;
    
    # Zone cache statique
    proxy_cache_path /var/cache/nginx/static
                     levels=1:2
                     keys_zone=static_cache:10m
                     max_size=5g
                     inactive=7d
                     use_temp_path=off;
    
    # Cache key personnalisée
    proxy_cache_key "$scheme$request_method$host$request_uri$cookie_user";
    
    # Conditions de bypass
    map $request_method $skip_cache {
        default 0;
        POST 1;
    }
    
    map $http_cookie $skip_cache_cookie {
        default 0;
        ~*logged_in 1;
    }
    
    server {
        listen 80;
        server_name example.com;
        
        location / {
            proxy_pass http://backend;
            
            # Cache
            proxy_cache main_cache;
            proxy_cache_valid 200 10m;
            proxy_cache_valid 404 1m;
            
            # Bypass cache
            proxy_cache_bypass $skip_cache $skip_cache_cookie;
            proxy_no_cache $skip_cache $skip_cache_cookie;
            
            # Purge cache (nécessite module ngx_cache_purge)
            # proxy_cache_purge PURGE from 127.0.0.1;
            
            # Headers
            add_header X-Cache-Status $upstream_cache_status;
            proxy_hide_header Set-Cookie;
        }
        
        # Cache pour fichiers statiques
        location ~* \.(jpg|jpeg|png|gif|ico|css|js|svg|woff|woff2|ttf|eot)$ {
            proxy_pass http://backend;
            proxy_cache static_cache;
            proxy_cache_valid 200 7d;
            expires 7d;
            add_header Cache-Control "public, immutable";
            add_header X-Cache-Status $upstream_cache_status;
        }
    }
}

# Créer répertoire cache
sudo mkdir -p /var/cache/nginx/main
sudo mkdir -p /var/cache/nginx/static
sudo chown -R www-data:www-data /var/cache/nginx


# === FastCGI Cache (pour PHP) ===

http {
    # Zone cache FastCGI
    fastcgi_cache_path /var/cache/nginx/fastcgi
                       levels=1:2
                       keys_zone=php_cache:100m
                       max_size=10g
                       inactive=60m
                       use_temp_path=off;
    
    fastcgi_cache_key "$scheme$request_method$host$request_uri";
    
    server {
        listen 80;
        server_name example.com;
        root /var/www/example;
        
        # Conditions skip cache
        set $skip_cache 0;
        
        # POST requests
        if ($request_method = POST) {
            set $skip_cache 1;
        }
        
        # URLs avec query string
        if ($query_string != "") {
            set $skip_cache 1;
        }
        
        # URLs admin/login
        if ($request_uri ~* "/(admin|login|wp-admin)") {
            set $skip_cache 1;
        }
        
        # Cookies logged in
        if ($http_cookie ~* "logged_in|wordpress_logged_in") {
            set $skip_cache 1;
        }
        
        location ~ \.php$ {
            include fastcgi_params;
            fastcgi_pass unix:/var/run/php/php8.1-fpm.sock;
            fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
            
            # Cache
            fastcgi_cache php_cache;
            fastcgi_cache_valid 200 60m;
            fastcgi_cache_bypass $skip_cache;
            fastcgi_no_cache $skip_cache;
            
            # Headers
            add_header X-Cache-Status $upstream_cache_status;
        }
    }
}


# === Microcaching (cache très court) ===

http {
    proxy_cache_path /var/cache/nginx/micro
                     levels=1:2
                     keys_zone=micro:10m
                     max_size=1g
                     inactive=10s;
    
    server {
        listen 80;
        server_name api.example.com;
        
        location / {
            proxy_pass http://backend;
            
            # Cache 1 seconde
            proxy_cache micro;
            proxy_cache_valid 200 1s;
            proxy_cache_lock on;
            proxy_cache_use_stale updating;
            
            add_header X-Cache-Status $upstream_cache_status;
        }
    }
}


[OK] SÉCURITÉ


# === Headers de sécurité ===

server {
    listen 443 ssl http2;
    server_name example.com;
    
    # Security headers
    add_header Strict-Transport-Security "max-age=31536000; includeSubDomains; preload" always;
    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 Content-Security-Policy "default-src 'self'; script-src 'self' 'unsafe-inline'; style-src 'self' 'unsafe-inline';" always;
    add_header Permissions-Policy "geolocation=(), microphone=(), camera=()" always;
    
    # Masquer version Nginx
    server_tokens off;
    more_clear_headers Server;  # Nécessite module headers-more
}


# === Bloquer requêtes malveillantes ===

server {
    listen 80;
    server_name example.com;
    
    # Bloquer requêtes sans Host
    if ($host !~* ^(example\.com|www\.example\.com)$) {
        return 444;
    }
    
    # Bloquer user agents malveillants
    if ($http_user_agent ~* (bot|crawler|spider|scraper|curl|wget)) {
        return 403;
    }
    
    # Bloquer méthodes HTTP dangereuses
    if ($request_method !~ ^(GET|HEAD|POST)$) {
        return 405;
    }
    
    # Bloquer accès fichiers sensibles
    location ~ /\.(git|svn|env|htaccess) {
        deny all;
        return 404;
    }
    
    # Bloquer scripts PHP dans uploads
    location ~* /uploads/.*\.php$ {
        deny all;
        return 404;
    }
}


# === Authentification basique ===

# Créer fichier mot de passe
sudo apt install apache2-utils
sudo htpasswd -c /etc/nginx/.htpasswd admin
sudo htpasswd /etc/nginx/.htpasswd user2

server {
    listen 80;
    server_name admin.example.com;
    
    # Auth pour tout le site
    auth_basic "Zone Restreinte";
    auth_basic_user_file /etc/nginx/.htpasswd;
    
    location / {
        root /var/www/admin;
    }
    
    # Location sans auth
    location /public/ {
        auth_basic off;
    }
}


# === Rate limiting ===

http {
    # Zone de rate limiting
    limit_req_zone $binary_remote_addr zone=one:10m rate=1r/s;
    limit_req_zone $binary_remote_addr zone=api:10m rate=10r/s;
    limit_req_zone $binary_remote_addr zone=login:10m rate=5r/m;
    
    # Limite connexions
    limit_conn_zone $binary_remote_addr zone=addr:10m;
    
    server {
        listen 80;
        server_name example.com;
        
        # Limite générale
        location / {
            limit_req zone=one burst=5 nodelay;
            limit_conn addr 10;
            proxy_pass http://backend;
        }
        
        # Limite API
        location /api/ {
            limit_req zone=api burst=20 nodelay;
            proxy_pass http://backend;
        }
        
        # Limite login
        location /login {
            limit_req zone=login burst=3 nodelay;
            proxy_pass http://backend;
        }
    }
}


# === Restriction par IP ===

server {
    listen 80;
    server_name admin.example.com;
    
    # Autoriser IPs spécifiques
    allow 192.168.1.0/24;
    allow 10.0.0.100;
    deny all;
    
    location / {
        root /var/www/admin;
    }
    
    # Location avec règles différentes
    location /public/ {
        allow all;
    }
}

# Avec geo module
http {
    geo $admin_access {
        default 0;
        192.168.1.0/24 1;
        10.0.0.100 1;
    }
    
    server {
        listen 80;
        server_name admin.example.com;
        
        if ($admin_access = 0) {
            return 403;
        }
        
        location / {
            root /var/www/admin;
        }
    }
}


# === Protection DDoS ===

http {
    # Rate limits agressifs
    limit_req_zone $binary_remote_addr zone=ddos:10m rate=100r/s;
    limit_conn_zone $binary_remote_addr zone=conn:10m;
    
    # Timeout courts
    client_body_timeout 10s;
    client_header_timeout 10s;
    keepalive_timeout 5s 5s;
    send_timeout 10s;
    
    # Limites taille
    client_body_buffer_size 128k;
    client_max_body_size 10m;
    client_header_buffer_size 1k;
    large_client_header_buffers 4 8k;
    
    server {
        listen 80;
        server_name example.com;
        
        location / {
            limit_req zone=ddos burst=200 nodelay;
            limit_conn conn 20;
            proxy_pass http://backend;
        }
    }
}


# === ModSecurity (WAF) ===

# Installation
sudo apt install libnginx-mod-security

# Configuration de base
# /etc/nginx/modsec/main.conf
SecRuleEngine On
SecRequestBodyAccess On
SecResponseBodyAccess Off
SecAuditEngine RelevantOnly
SecAuditLog /var/log/nginx/modsec_audit.log

# Dans nginx.conf
http {
    modsecurity on;
    modsecurity_rules_file /etc/nginx/modsec/main.conf;
}


[OK] OPTIMISATION PERFORMANCE - RENDRE NGINX ULTRA-RAPIDE

# === WORKER PROCESSES ET CONNEXIONS ===

# nginx.conf
user www-data;

# Nombre de workers = nombre de CPU cores
worker_processes auto;          # Détecte automatiquement (RECOMMANDÉ)
# Ou manuellement:
# worker_processes 4;           # Si 4 CPU cores

# Affinité CPU (lie worker à CPU spécifique)
worker_cpu_affinity auto;       # Automatique (RECOMMANDÉ)

# Limite fichiers ouverts par worker
worker_rlimit_nofile 65535;     # 65k fichiers (pour haute charge)

events {
    # Connexions simultanées par worker
    worker_connections 4096;    # 4096 connexions/worker
                                # Total: 4 workers × 4096 = 16384 connexions
    
    # Méthode événementielle (Linux)
    use epoll;                  # Très efficace sur Linux
    
    # Accepter plusieurs connexions à la fois
    multi_accept on;            # Active (meilleure performance)
}

# Calcul connexions max:
# worker_processes × worker_connections = connexions simultanées max
# 4 × 4096 = 16384 connexions simultanées


# === BUFFERS ET TIMEOUTS ===

http {
    # === BUFFERS CLIENT ===
    client_body_buffer_size 128k;       # Buffer body requête
    client_max_body_size 20m;           # Taille max upload
    client_header_buffer_size 1k;       # Buffer headers
    large_client_header_buffers 4 8k;   # 4 buffers de 8k pour gros headers
    
    # === BUFFERS PROXY ===
    proxy_buffer_size 4k;               # Buffer headers réponse backend
    proxy_buffers 8 4k;                 # 8 buffers de 4k
    proxy_busy_buffers_size 8k;         # Buffers occupés
    
    # === BUFFERS FASTCGI (PHP) ===
    fastcgi_buffers 8 16k;              # 8 buffers de 16k
    fastcgi_buffer_size 32k;            # Buffer headers
    
    # === TIMEOUTS ===
    client_body_timeout 12s;            # Timeout envoi body
    client_header_timeout 12s;          # Timeout envoi headers
    keepalive_timeout 15s;              # Durée keep-alive
    send_timeout 10s;                   # Timeout envoi réponse
    
    # === OPTIMISATIONS TCP ===
    sendfile on;                        # Envoi fichier optimisé (IMPORTANT!)
    tcp_nopush on;                      # Envoie headers + début fichier ensemble
    tcp_nodelay on;                     # Désactive algorithme Nagle
    
    # === HASH TABLES ===
    types_hash_max_size 2048;           # Table hash types MIME
    server_names_hash_bucket_size 64;   # Taille hash noms serveurs
}


# === COMPRESSION GZIP ===

http {
    # === GZIP BASIQUE ===
    gzip on;                    # Activer compression (ESSENTIEL!)
    gzip_vary on;               # Ajoute header Vary: Accept-Encoding
    gzip_proxied any;           # Compresser réponses proxy
    gzip_comp_level 6;          # Niveau compression 1-9 (6 = optimal)
                                # 1 = rapide, faible compression
                                # 9 = lent, forte compression
                                # 6 = bon compromis
    
    gzip_min_length 256;        # Compresser seulement si > 256 bytes
                                # Pas worth pour petits fichiers
    
    gzip_disable "msie6";       # Désactiver pour IE6 (bugué)
    
    # === TYPES MIME À COMPRESSER ===
    gzip_types
        text/plain
        text/css
        text/xml
        text/javascript
        application/json
        application/javascript
        application/xml+rss
        application/rss+xml
        application/atom+xml
        image/svg+xml
        text/x-component
        text/x-cross-domain-policy;
    
    # Note: text/html est TOUJOURS compressé (pas besoin de lister)
}

# Test compression:
curl -H "Accept-Encoding: gzip" -I https://example.com/style.css
# Devrait voir: Content-Encoding: gzip

# Gains typiques:
# HTML: 70-80% réduction
# CSS: 75-85% réduction
# JS: 70-80% réduction
# JSON: 80-90% réduction


# === COMPRESSION BROTLI (Meilleure que Gzip) ===

# Brotli = Algorithme moderne, 20% meilleur que Gzip
# Supporté par tous navigateurs modernes

# Installation module:
sudo apt install nginx-module-brotli

# Charger module (début nginx.conf):
load_module modules/ngx_http_brotli_filter_module.so;
load_module modules/ngx_http_brotli_static_module.so;

http {
    # === BROTLI DYNAMIQUE ===
    brotli on;                  # Activer Brotli
    brotli_comp_level 6;        # Niveau 1-11 (6 = bon compromis)
    brotli_types
        text/plain
        text/css
        text/xml
        text/javascript
        application/json
        application/javascript
        application/xml+rss
        image/svg+xml;
    
    # === BROTLI STATIQUE ===
    brotli_static on;           # Servir fichiers .br précompressés
    
    # Précompresser fichiers (script déploiement):
    # find /var/www -type f \( -name '*.css' -o -name '*.js' \) -exec brotli {} \;
}

# Priorité navigateur moderne:
# 1. Fichier .br (Brotli statique) - Le plus rapide
# 2. Brotli dynamique - Très bon
# 3. Gzip - Bon fallback


# === OPEN FILE CACHE ===

# Cache métadonnées fichiers (évite open() à chaque requête)
http {
    open_file_cache max=10000 inactive=30s;
    # max=10000 = Cache 10k fichiers
    # inactive=30s = Supprimer si pas accédé 30 secondes
    
    open_file_cache_valid 60s;  # Revérifier fichier toutes les 60s
    open_file_cache_min_uses 2; # Cacher seulement si utilisé 2+ fois
    open_file_cache_errors on;  # Cacher aussi erreurs (fichier absent)
}

# Gains: 20-30% performance pour sites avec beaucoup de fichiers


# === HTTP/2 ===

# HTTP/2 = Protocole moderne, BEAUCOUP plus rapide que HTTP/1.1
# Multiplexage, compression headers, server push

server {
    # Activer HTTP/2 (nécessite HTTPS)
    listen 443 ssl http2;       # Ajouter "http2"
    listen [::]:443 ssl http2;
    
    server_name example.com;
    
    ssl_certificate /path/to/cert.pem;
    ssl_certificate_key /path/to/key.pem;
    
    # === HTTP/2 PUSH (Précharger ressources) ===
    location = /index.html {
        # Pousser CSS/JS avant que navigateur les demande
        http2_push /css/style.css;
        http2_push /js/app.js;
        http2_push /images/logo.png;
    }
    
    location / {
        root /var/www/example;
    }
}

# Vérifier HTTP/2 actif:
curl -I --http2 https://example.com
# Devrait voir: HTTP/2 200


# === CONFIGURATION HAUTE PERFORMANCE COMPLÈTE ===

# nginx.conf optimisé pour production

user www-data;
worker_processes auto;
worker_cpu_affinity auto;
worker_rlimit_nofile 100000;    # 100k fichiers
pcre_jit on;                    # JIT pour regex (plus rapide)

events {
    worker_connections 10000;   # 10k connexions/worker
    use epoll;
    multi_accept on;
}

http {
    # === CACHE FICHIERS ===
    open_file_cache max=200000 inactive=20s;
    open_file_cache_valid 30s;
    open_file_cache_min_uses 2;
    open_file_cache_errors on;
    
    # === BUFFERS ===
    client_body_buffer_size 128k;
    client_max_body_size 10m;
    client_header_buffer_size 1k;
    large_client_header_buffers 4 8k;
    output_buffers 1 32k;
    postpone_output 1460;
    
    # === TIMEOUTS ===
    client_header_timeout 3m;
    client_body_timeout 3m;
    send_timeout 3m;
    keepalive_timeout 30;
    keepalive_requests 100;
    
    # === TCP ===
    sendfile on;
    tcp_nopush on;
    tcp_nodelay on;
    
    # === COMPRESSION ===
    gzip on;
    gzip_min_length 1000;
    gzip_comp_level 6;
    gzip_vary on;
    gzip_proxied any;
    gzip_types text/plain text/css application/json application/javascript text/xml application/xml image/svg+xml;
    
    # === SÉCURITÉ ===
    server_tokens off;
    
    # === HASH TABLES ===
    types_hash_max_size 2048;
    server_names_hash_bucket_size 128;
    
    # === MIME TYPES ===
    include mime.types;
    default_type application/octet-stream;
    
    # === LOGS (avec buffer) ===
    access_log /var/log/nginx/access.log combined buffer=32k flush=5s;
    error_log /var/log/nginx/error.log warn;
    
    # === SITES ===
    include /etc/nginx/sites-enabled/*;
}

# Cette config supporte:
# - 40k connexions simultanées (4 workers × 10k)
# - Optimisations TCP/cache
# - Compression Gzip
# - Sécurité basique


# === BENCHMARKING (Tester performance) ===

# Outil 1: Apache Bench (ab)
ab -n 10000 -c 100 http://example.com/
# -n 10000 = 10k requêtes total
# -c 100 = 100 requêtes simultanées

# Résultat:
# Requests per second: 5234.12 [#/sec]
# Time per request: 19.106 [ms]
# Transfer rate: 12456.78 [Kbytes/sec]


# Outil 2: wrk (Plus moderne)
wrk -t4 -c100 -d30s http://example.com/
# -t4 = 4 threads
# -c100 = 100 connexions
# -d30s = durée 30 secondes

# Résultat:
# Requests/sec: 6543.21
# Latency avg: 15.23ms


# Outil 3: siege
siege -c 100 -t 60s http://example.com/
# -c 100 = 100 users simultanés
# -t 60s = durée 60 secondes


# === MONITORING PERFORMANCE ===

# Module stub_status (statistiques Nginx)
server {
    listen 127.0.0.1:8080;      # Accessible seulement localement
    
    location /nginx_status {
        stub_status on;
        access_log off;
        allow 127.0.0.1;
        deny all;
    }
}

# Accéder:
curl http://localhost:8080/nginx_status

# Sortie:
# Active connections: 291
# server accepts handled requests
#  16630948 16630948 31070465
# Reading: 6 Writing: 179 Waiting: 106

# Explication:
# Active connections: Connexions actives actuellement
# accepts: Connexions acceptées total
# handled: Connexions traitées total
# requests: Requêtes traitées total
# Reading: Nginx lit requête
# Writing: Nginx écrit réponse
# Waiting: Keep-alive (en attente)


# === RÉSUMÉ OPTIMISATION ===

# Worker processes:
worker_processes auto;
worker_connections 4096;

# Compression:
gzip on;
gzip_comp_level 6;
gzip_types text/plain text/css application/json;

# Cache fichiers:
open_file_cache max=10000 inactive=30s;

# HTTP/2:
listen 443 ssl http2;

# TCP optimisations:
sendfile on;
tcp_nopush on;
tcp_nodelay on;

# Benchmark:
ab -n 10000 -c 100 http://example.com/

# Gains typiques après optimisation:
# - 2-5x plus de requêtes/seconde
# - 50-70% réduction temps réponse
# - 70-80% réduction bande passante (gzip)


[OK] PHP-FPM


# === Configuration PHP-FPM ===

server {
    listen 80;
    server_name example.com;
    root /var/www/example;
    index index.php index.html;
    
    location / {
        try_files $uri $uri/ /index.php?$query_string;
    }
    
    # PHP-FPM
    location ~ \.php$ {
        try_files $uri =404;
        
        include fastcgi_params;
        fastcgi_pass unix:/var/run/php/php8.1-fpm.sock;
        fastcgi_index index.php;
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
        
        # Buffers
        fastcgi_buffers 16 16k;
        fastcgi_buffer_size 32k;
        
        # Timeouts
        fastcgi_connect_timeout 60;
        fastcgi_send_timeout 180;
        fastcgi_read_timeout 180;
    }
    
    # Sécurité - bloquer accès fichiers PHP dans uploads
    location ~* /uploads/.*\.php$ {
        deny all;
    }
    
    # Bloquer fichiers cachés
    location ~ /\. {
        deny all;
        access_log off;
        log_not_found off;
    }
}


# === PHP-FPM avec pool séparé ===

# /etc/php/8.1/fpm/pool.d/example.conf
[example]
user = www-data
group = www-data
listen = /var/run/php/php8.1-fpm-example.sock
listen.owner = www-data
listen.group = www-data
pm = dynamic
pm.max_children = 50
pm.start_servers = 5
pm.min_spare_servers = 5
pm.max_spare_servers = 35

# Nginx
location ~ \.php$ {
    fastcgi_pass unix:/var/run/php/php8.1-fpm-example.sock;
    # ... reste de la config
}


# === WordPress optimisé ===

server {
    listen 80;
    server_name wordpress.com www.wordpress.com;
    root /var/www/wordpress;
    index index.php;
    
    # Logs
    access_log /var/log/nginx/wordpress-access.log;
    error_log /var/log/nginx/wordpress-error.log;
    
    # Uploads
    client_max_body_size 64M;
    
    # Cache statique
    location ~* \.(js|css|png|jpg|jpeg|gif|ico|svg|woff|woff2|ttf|eot)$ {
        expires 1y;
        add_header Cache-Control "public, immutable";
        access_log off;
    }
    
    # WordPress règles
    location / {
        try_files $uri $uri/ /index.php?$args;
    }
    
    # PHP
    location ~ \.php$ {
        try_files $uri =404;
        include fastcgi_params;
        fastcgi_pass unix:/var/run/php/php8.1-fpm.sock;
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
        fastcgi_index index.php;
        
        # Cache FastCGI (voir section cache)
        fastcgi_cache_bypass $skip_cache;
        fastcgi_no_cache $skip_cache;
        fastcgi_cache wp_cache;
        fastcgi_cache_valid 200 60m;
    }
    
    # Sécurité WordPress
    location ~ /\.(ht|git|svn) {
        deny all;
    }
    
    location ~* /(?:uploads|files)/.*\.php$ {
        deny all;
    }
    
    location ~* /wp-config.php {
        deny all;
    }
    
    location = /xmlrpc.php {
        deny all;
        access_log off;
        log_not_found off;
    }
}


[OK] REDIRECTIONS


# === Redirection simple ===

server {
    listen 80;
    server_name old-domain.com;
    return 301 https://new-domain.com$request_uri;
}


# === Redirection www vers non-www ===

server {
    listen 80;
    listen 443 ssl http2;
    server_name www.example.com;
    
    ssl_certificate /path/to/cert.pem;
    ssl_certificate_key /path/to/key.pem;
    
    return 301 $scheme://example.com$request_uri;
}


# === Redirection non-www vers www ===

server {
    listen 80;
    listen 443 ssl http2;
    server_name example.com;
    
    ssl_certificate /path/to/cert.pem;
    ssl_certificate_key /path/to/key.pem;
    
    return 301 $scheme://www.example.com$request_uri;
}


# === Redirection HTTP vers HTTPS ===

server {
    listen 80;
    server_name example.com www.example.com;
    return 301 https://$host$request_uri;
}


# === Redirections multiples ===

server {
    listen 80;
    server_name example.com;
    
    # Redirection chemin spécifique
    location = /old-page {
        return 301 /new-page;
    }
    
    # Redirection avec regex
    location ~ ^/blog/(.*)$ {
        return 301 /articles/$1;
    }
    
    # Redirection conditionnelle
    if ($request_uri ~ ^/old-section/(.*)$) {
        return 301 /new-section/$1;
    }
}


# === Redirection avec map ===

http {
    map $request_uri $new_uri {
        /old-page-1  /new-page-1;
        /old-page-2  /new-page-2;
        /old-page-3  /new-page-3;
        default      "";
    }
    
    server {
        listen 80;
        server_name example.com;
        
        if ($new_uri != "") {
            return 301 $new_uri;
        }
        
        location / {
            root /var/www/example;
        }
    }
}


# === Redirection pour maintenance ===

server {
    listen 80;
    server_name example.com;
    root /var/www/example;
    
    # Variable maintenance
    set $maintenance 0;
    
    # Activer maintenance (créer fichier)
    if (-f /var/www/maintenance.flag) {
        set $maintenance 1;
    }
    
    # Exceptions (IPs admin)
    if ($remote_addr ~ ^(192\.168\.1\.100|10\.0\.0\.50)$) {
        set $maintenance 0;
    }
    
    # Redirection vers page maintenance
    if ($maintenance = 1) {
        return 503;
    }
    
    error_page 503 @maintenance;
    
    location @maintenance {
        rewrite ^(.*)$ /maintenance.html break;
    }
    
    location / {
        try_files $uri $uri/ /index.php?$args;
    }
}


[OK] VARIABLES NGINX


# === Variables intégrées courantes ===

# $arg_name                     # Paramètre GET
# $args                         # Query string complète
# $binary_remote_addr           # IP client (binaire)
# $body_bytes_sent              # Bytes envoyés (sans headers)
# $bytes_sent                   # Bytes envoyés total
# $connection                   # Numéro connexion
# $connection_requests          # Requêtes sur connexion
# $content_length               # Header Content-Length
# $content_type                 # Header Content-Type
# $cookie_name                  # Cookie spécifique
# $document_root                # Racine documents
# $document_uri                 # URI normalisée
# $host                         # Host (priorité: ligne, header, server_name)
# $hostname                     # Hostname système
# $http_name                    # Header HTTP arbitraire
# $https                        # "on" si HTTPS
# $is_args                      # "?" si query string
# $limit_rate                   # Limite rate response
# $msec                         # Timestamp milliseconde
# $nginx_version                # Version Nginx
# $pid                          # PID worker
# $pipe                         # "p" si pipelined
# $proxy_protocol_addr          # IP via PROXY protocol
# $query_string                 # Identique à $args
# $realpath_root                # Chemin absolu root
# $remote_addr                  # IP client
# $remote_port                  # Port client
# $remote_user                  # User auth basic
# $request                      # Ligne requête complète
# $request_body                 # Corps requête
# $request_body_file            # Fichier corps requête
# $request_completion           # "OK" si requête complète
# $request_filename             # Chemin fichier actuel
# $request_id                   # ID requête unique
# $request_length               # Taille requête
# $request_method               # Méthode (GET, POST...)
# $request_time                 # Temps traitement requête
# $request_uri                  # URI originale avec args
# $scheme                       # "http" ou "https"
# $sent_http_name               # Header réponse arbitraire
# $server_addr                  # IP serveur
# $server_name                  # server_name correspondant
# $server_port                  # Port serveur
# $server_protocol              # Protocole (HTTP/1.1...)
# $ssl_cipher                   # Cipher SSL
# $ssl_client_cert              # Certificat client
# $ssl_protocol                 # Protocole SSL
# $status                       # Code statut réponse
# $tcpinfo_rtt                  # RTT TCP
# $time_iso8601                 # Timestamp ISO 8601
# $time_local                   # Timestamp local
# $uri                          # URI actuelle normalisée
# $upstream_addr                # IP upstream
# $upstream_cache_status        # Statut cache (HIT/MISS/BYPASS...)
# $upstream_connect_time        # Temps connexion upstream
# $upstream_header_time         # Temps headers upstream
# $upstream_response_length     # Taille réponse upstream
# $upstream_response_time       # Temps réponse upstream
# $upstream_status              # Code statut upstream


# === Exemples d'utilisation ===

server {
    listen 80;
    server_name example.com;
    
    # Log personnalisé avec variables
    access_log /var/log/nginx/custom.log 
        '$remote_addr - $remote_user [$time_local] '
        '"$request" $status $body_bytes_sent '
        '"$http_referer" "$http_user_agent" '
        'rt=$request_time uct=$upstream_connect_time '
        'uht=$upstream_header_time urt=$upstream_response_time';
    
    # Headers avec variables
    location / {
        add_header X-Request-ID $request_id;
        add_header X-Served-By $hostname;
        proxy_pass http://backend;
    }
    
    # Redirection avec query string
    location /search {
        if ($arg_query) {
            return 301 /results?q=$arg_query;
        }
    }
    
    # Cookie personnalisé
    location / {
        add_header Set-Cookie "session_id=$request_id; Path=/; HttpOnly";
        root /var/www/example;
    }
}


# === Variables personnalisées ===

http {
    # Map pour créer variables
    map $request_method $loggable {
        default 1;
        GET 0;
    }
    
    map $status $loggable_status {
        ~^[23] 0;
        default 1;
    }
    
    map $http_user_agent $mobile {
        default 0;
        ~*mobile 1;
        ~*android 1;
        ~*iphone 1;
    }
    
    server {
        listen 80;
        server_name example.com;
        
        # Log conditionnel
        access_log /var/log/nginx/access.log combined if=$loggable;
        
        # Backend selon device
        location / {
            if ($mobile) {
                proxy_pass http://mobile-backend;
            }
            proxy_pass http://desktop-backend;
        }
    }
}


[OK] MODULES TIERS


# === PageSpeed (Google) ===

# Installation
wget https://github.com/apache/incubator-pagespeed-ngx/archive/latest-stable.zip
unzip latest-stable.zip
cd incubator-pagespeed-ngx-latest-stable/
# Suivre instructions compilation avec Nginx

# Configuration
http {
    pagespeed on;
    pagespeed FileCachePath /var/cache/ngx_pagespeed;
    
    server {
        listen 80;
        server_name example.com;
        
        # Optimisations PageSpeed
        pagespeed EnableFilters rewrite_images;
        pagespeed EnableFilters convert_jpeg_to_webp;
        pagespeed EnableFilters combine_css;
        pagespeed EnableFilters combine_javascript;
        pagespeed EnableFilters collapse_whitespace;
        
        location / {
            root /var/www/example;
        }
    }
}


# === Naxsi (WAF) ===

# Installation
sudo apt install nginx-module-naxsi

# Configuration
# /etc/nginx/naxsi_core.rules (règles fournies)

http {
    include /etc/nginx/naxsi_core.rules;
    
    server {
        listen 80;
        server_name example.com;
        
        location / {
            # Mode learning (pas de blocage)
            # LearningMode;
            
            # Mode enforcement (blocage actif)
            SecRulesEnabled;
            DeniedUrl "/error.html";
            
            # Règles à vérifier
            CheckRule "$SQL >= 8" BLOCK;
            CheckRule "$RFI >= 8" BLOCK;
            CheckRule "$TRAVERSAL >= 4" BLOCK;
            CheckRule "$EVADE >= 4" BLOCK;
            CheckRule "$XSS >= 8" BLOCK;
            
            root /var/www/example;
        }
    }
}


# === GeoIP2 ===

# Installation
sudo apt install nginx-module-geoip2

# Télécharger base GeoIP2
sudo mkdir -p /usr/share/GeoIP
cd /usr/share/GeoIP
sudo wget https://git.io/GeoLite2-Country.mmdb

# Configuration
load_module modules/ngx_http_geoip2_module.so;

http {
    geoip2 /usr/share/GeoIP/GeoLite2-Country.mmdb {
        auto_reload 5m;
        $geoip2_metadata_country_build metadata build_epoch;
        $geoip2_data_country_code country iso_code;
        $geoip2_data_country_name country names en;
    }
    
    server {
        listen 80;
        server_name example.com;
        
        # Bloquer certains pays
        if ($geoip2_data_country_code ~ ^(CN|RU)$) {
            return 403;
        }
        
        # Header avec pays
        add_header X-Country-Code $geoip2_data_country_code;
        
        location / {
            root /var/www/example;
        }
    }
}


# === Headers More ===

# Installation
# Compiler avec --add-module=../headers-more-nginx-module

http {
    server {
        listen 80;
        server_name example.com;
        
        # Supprimer headers
        more_clear_headers 'Server';
        more_clear_headers 'X-Powered-By';
        
        # Ajouter headers
        more_set_headers 'X-Custom-Header: Value';
        
        # Modifier headers
        more_set_headers 'Server: CustomServer/1.0';
        
        location / {
            root /var/www/example;
        }
    }
}


# === Lua (OpenResty) ===

# Installation OpenResty (Nginx + Lua)
wget https://openresty.org/download/openresty-1.21.4.1.tar.gz
tar -zxvf openresty-1.21.4.1.tar.gz
cd openresty-1.21.4.1
./configure
make
sudo make install

# Configuration
http {
    server {
        listen 80;
        server_name example.com;
        
        # Lua inline
        location /lua {
            default_type 'text/plain';
            content_by_lua_block {
                ngx.say("Hello from Lua!")
                ngx.say("Your IP: " .. ngx.var.remote_addr)
            }
        }
        
        # Lua depuis fichier
        location /api {
            content_by_lua_file /path/to/script.lua;
        }
        
        # Authentification custom
        location /protected {
            access_by_lua_block {
                local token = ngx.var.arg_token
                if token ~= "secret123" then
                    ngx.exit(ngx.HTTP_FORBIDDEN)
                end
            }
            root /var/www/protected;
        }
    }
}


[OK] MONITORING ET DEBUGGING


# === Status module ===

# Configuration
http {
    server {
        listen 127.0.0.1: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

# Sortie:
# Active connections: 42
# server accepts handled requests
#  1234 1234 5678
# Reading: 0 Writing: 2 Waiting: 40


# === Module VTS (Virtual Host Traffic Status) ===

# Compilation avec module
./configure --add-module=/path/to/nginx-module-vts

# Configuration
http {
    vhost_traffic_status_zone;
    
    server {
        listen 80;
        server_name monitor.example.com;
        
        location /status {
            vhost_traffic_status_display;
            vhost_traffic_status_display_format html;
        }
    }
}


# === Logs de debug ===

# Compiler avec debug
./configure --with-debug

# Activer debug
error_log /var/log/nginx/error.log debug;

# Debug spécifique
error_log /var/log/nginx/error.log debug_http;
error_log /var/log/nginx/error.log debug_core;


# === Analyser les connexions ===

# Connexions actives
netstat -an | grep :80 | wc -l

# Connexions par IP
netstat -an | grep :80 | awk '{print $5}' | cut -d: -f1 | sort | uniq -c | sort -rn

# Avec ss (plus rapide)
ss -tan | grep :80 | wc -l


# === Test de charge ===

# Apache Bench
ab -n 10000 -c 100 http://example.com/

# wrk
wrk -t12 -c400 -d30s http://example.com/

# siege
siege -c 100 -t 60s http://example.com/


# === Prometheus Exporter ===

# Installation nginx-prometheus-exporter
wget https://github.com/nginxinc/nginx-prometheus-exporter/releases/download/v0.11.0/nginx-prometheus-exporter_0.11.0_linux_amd64.tar.gz
tar -zxvf nginx-prometheus-exporter_0.11.0_linux_amd64.tar.gz
sudo mv nginx-prometheus-exporter /usr/local/bin/

# Lancer
nginx-prometheus-exporter -nginx.scrape-uri=http://localhost:8080/nginx_status

# Métriques disponibles sur :9113/metrics


[OK] DOCKER


# === Dockerfile Nginx de base ===

FROM nginx:alpine

# Copier fichiers
COPY nginx.conf /etc/nginx/nginx.conf
COPY default.conf /etc/nginx/conf.d/default.conf
COPY html/ /usr/share/nginx/html/

EXPOSE 80 443

CMD ["nginx", "-g", "daemon off;"]


# === docker-compose.yml ===

version: '3.8'

services:
  nginx:
    image: nginx:alpine
    container_name: nginx
    ports:
      - "80:80"
      - "443:443"
    volumes:
      - ./nginx.conf:/etc/nginx/nginx.conf:ro
      - ./conf.d:/etc/nginx/conf.d:ro
      - ./html:/usr/share/nginx/html:ro
      - ./ssl:/etc/nginx/ssl:ro
      - ./logs:/var/log/nginx
    restart: unless-stopped
    networks:
      - web

networks:
  web:
    driver: bridge


# === Nginx + PHP-FPM ===

version: '3.8'

services:
  nginx:
    image: nginx:alpine
    ports:
      - "80:80"
    volumes:
      - ./nginx.conf:/etc/nginx/nginx.conf
      - ./www:/var/www/html
    depends_on:
      - php
    networks:
      - web

  php:
    image: php:8.1-fpm-alpine
    volumes:
      - ./www:/var/www/html
    networks:
      - web

networks:
  web:


# === Nginx reverse proxy Docker ===

version: '3.8'

services:
  nginx:
    image: nginx:alpine
    ports:
      - "80:80"
      - "443:443"
    volumes:
      - ./nginx.conf:/etc/nginx/nginx.conf
    networks:
      - web

  app1:
    image: myapp:latest
    expose:
      - "3000"
    networks:
      - web

  app2:
    image: myapp2:latest
    expose:
      - "4000"
    networks:
      - web

networks:
  web:

# nginx.conf pour Docker
upstream app1 {
    server app1:3000;
}

upstream app2 {
    server app2:4000;
}

server {
    listen 80;
    server_name app1.example.com;
    
    location / {
        proxy_pass http://app1;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
    }
}

server {
    listen 80;
    server_name app2.example.com;
    
    location / {
        proxy_pass http://app2;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
    }
}


[OK] KUBERNETES


# === Nginx Ingress Controller ===

# Installation avec Helm
helm repo add ingress-nginx https://kubernetes.github.io/ingress-nginx
helm repo update
helm install nginx-ingress ingress-nginx/ingress-nginx

# Ou avec kubectl
kubectl apply -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/controller-v1.8.1/deploy/static/provider/cloud/deploy.yaml


# === Ingress Resource ===

# ingress.yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: my-ingress
  annotations:
    nginx.ingress.kubernetes.io/rewrite-target: /
    nginx.ingress.kubernetes.io/ssl-redirect: "true"
spec:
  ingressClassName: nginx
  rules:
  - host: example.com
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: web-service
            port:
              number: 80
  - host: api.example.com
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: api-service
            port:
              number: 8080


# === Ingress avec TLS ===

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: tls-ingress
spec:
  ingressClassName: nginx
  tls:
  - hosts:
    - example.com
    - www.example.com
    secretName: tls-secret
  rules:
  - host: example.com
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: web-service
            port:
              number: 80


# === Annotations avancées ===

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: advanced-ingress
  annotations:
    # Rate limiting
    nginx.ingress.kubernetes.io/limit-rps: "10"
    nginx.ingress.kubernetes.io/limit-connections: "5"
    
    # Authentification basique
    nginx.ingress.kubernetes.io/auth-type: basic
    nginx.ingress.kubernetes.io/auth-secret: basic-auth
    nginx.ingress.kubernetes.io/auth-realm: "Authentication Required"
    
    # CORS
    nginx.ingress.kubernetes.io/enable-cors: "true"
    nginx.ingress.kubernetes.io/cors-allow-origin: "*"
    
    # WebSocket
    nginx.ingress.kubernetes.io/proxy-read-timeout: "3600"
    nginx.ingress.kubernetes.io/proxy-send-timeout: "3600"
    
    # Taille upload
    nginx.ingress.kubernetes.io/proxy-body-size: "100m"
    
    # Cache
    nginx.ingress.kubernetes.io/cache-control: "public, max-age=3600"
spec:
  ingressClassName: nginx
  rules:
  - host: example.com
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: web-service
            port:
              number: 80


[OK] TROUBLESHOOTING - RÉSOUDRE LES PROBLÈMES COURANTS

# === PROBLÈME: "Address already in use" ===

# Erreur complète:
# nginx: [emerg] bind() to 0.0.0.0:80 failed (98: Address already in use)

# Cause: Un autre service utilise déjà le port 80 (souvent Apache)

# Solution 1: Trouver quel processus utilise le port
sudo lsof -i :80
# Ou:
sudo netstat -tulpn | grep :80
# Ou:
sudo ss -tulpn | grep :80

# Affiche quelque chose comme:
# apache2   1234   root   4u  IPv6  12345      0t0  TCP *:80 (LISTEN)

# Solution 2: Arrêter l'autre service
sudo systemctl stop apache2

# Solution 3: Ou changer port Nginx (temporaire)
# Dans nginx.conf:
listen 8080;  # Au lieu de 80


# === PROBLÈME: "Permission denied" ===

# Erreur: nginx: [emerg] open() "/var/log/nginx/access.log" failed (13: Permission denied)

# Cause: Nginx n'a pas permissions sur fichiers/dossiers

# Solution 1: Vérifier permissions dossiers
ls -la /var/www/monsite/
ls -la /var/log/nginx/

# Solution 2: Fixer propriétaire
sudo chown -R www-data:www-data /var/www/monsite/
sudo chown -R www-data:www-data /var/log/nginx/

# Solution 3: Fixer permissions
sudo chmod -R 755 /var/www/monsite/

# Solution 4: SELinux (CentOS/RHEL)
# Vérifier si SELinux bloque:
getenforce
# Si "Enforcing", temporairement désactiver:
sudo setenforce 0

# Autoriser Nginx dans SELinux:
sudo setsebool -P httpd_can_network_connect 1
sudo chcon -R -t httpd_sys_content_t /var/www/


# === PROBLÈME: 502 Bad Gateway ===

# Signification: Nginx ne peut pas contacter le backend

# Cause 1: Backend pas démarré
# Vérifier:
ps aux | grep node    # ou python, php-fpm, etc.
# Si absent, démarrer:
node server.js        # ou votre commande

# Cause 2: Mauvais port dans proxy_pass
# Vérifier dans nginx.conf:
proxy_pass http://localhost:3000;  # Port correct ?
# Tester backend directement:
curl http://localhost:3000

# Cause 3: PHP-FPM ne tourne pas
sudo systemctl status php8.1-fpm
sudo systemctl start php8.1-fpm

# Cause 4: Socket PHP-FPM incorrect
# Vérifier socket existe:
ls -la /var/run/php/php8.1-fpm.sock
# Fixer permissions si besoin:
sudo chmod 666 /var/run/php/php8.1-fpm.sock

# Cause 5: Firewall bloque connexion locale
# Désactiver temporairement:
sudo ufw disable


# === PROBLÈME: 504 Gateway Timeout ===

# Signification: Backend trop lent à répondre

# Solution: Augmenter timeouts dans Nginx
location / {
    proxy_pass http://backend;
    proxy_connect_timeout 600s;
    proxy_send_timeout 600s;
    proxy_read_timeout 600s;
}

# Pour PHP-FPM:
location ~ \.php$ {
    fastcgi_pass php;
    fastcgi_read_timeout 600s;
}


# === PROBLÈME: Configuration ne se charge pas ===

# Vous avez modifié config mais rien ne change

# Cause: Oublié de recharger Nginx!
sudo systemctl reload nginx

# Ou: Erreur de syntaxe bloque reload
# TOUJOURS tester avant:
sudo nginx -t
# Si erreur, Nginx affiche ligne et problème


# === PROBLÈME: 404 Not Found ===

# Page existe mais Nginx dit 404

# Cause 1: Mauvais chemin "root"
# Vérifier config:
sudo nginx -T | grep root
# Compare avec:
ls /var/www/monsite/

# Cause 2: Mauvais fichier index
# Vérifier:
ls /var/www/monsite/index.html
# Si nom différent, ajuster:
index index.htm;  # ou index.php

# Cause 3: Permissions
ls -la /var/www/monsite/
# Doit être lisible par www-data


# === PROBLÈME: Upload échoue ===

# Fichier trop gros refusé

# Solution: Augmenter limite
client_max_body_size 100M;

# Pour PHP aussi (php.ini):
upload_max_filesize = 100M
post_max_size = 100M

# Redémarrer PHP-FPM:
sudo systemctl restart php8.1-fpm


# === PROBLÈME: SSL ne fonctionne pas ===

# Cause 1: Certificat invalide
# Vérifier:
openssl x509 -in /etc/letsencrypt/live/example.com/fullchain.pem -text -noout
openssl rsa -in /etc/letsencrypt/live/example.com/privkey.pem -check

# Cause 2: Certificat expiré
# Renouveler:
sudo certbot renew

# Cause 3: Port 443 pas ouvert firewall
sudo ufw allow 443/tcp
sudo ufw allow 80/tcp


# === PROBLÈME: Site lent ===

# Diagnostic:
# 1. Tester temps réponse Nginx seul:
time curl http://localhost/static.html
# Si rapide (< 50ms), problème pas Nginx

# 2. Tester backend directement:
time curl http://localhost:3000
# Si lent, optimiser backend

# 3. Activer logs détaillés:
log_format timing '$remote_addr $request_time $upstream_response_time';
access_log /var/log/nginx/timing.log timing;

# 4. Activer cache si pas fait:
proxy_cache my_cache;

# 5. Activer gzip:
gzip on;


# === PROBLÈME: Cache ne fonctionne pas ===

# Vérifier: Header X-Cache-Status toujours MISS

# Cause 1: Cookies différents chaque fois
# Solution:
proxy_ignore_headers Set-Cookie;

# Cause 2: Cache pas configuré
# Vérifier zone existe:
proxy_cache_path /var/cache/nginx/proxy ...;
# Et dossier existe:
ls -la /var/cache/nginx/proxy/

# Cause 3: Toujours bypass
# Vérifier conditions:
set $skip_cache 0;
proxy_cache_bypass $skip_cache;


# === VÉRIFIER CONFIGURATION COMPLÈTE ===

# Afficher config complète après traitement:
sudo nginx -T

# Vérifier syntaxe:
sudo nginx -t

# Vérifier version et modules:
nginx -V

# Vérifier processus actifs:
ps aux | grep nginx

# Vérifier ports écoutés:
sudo netstat -tulpn | grep nginx


[OK] BONNES PRATIQUES


# === Organisation fichiers ===

# Structure recommandée
/etc/nginx/
├── nginx.conf                  # Configuration principale
├── mime.types
├── fastcgi_params
├── sites-available/           # Sites disponibles
│   ├── site1.conf
│   ├── site2.conf
│   └── site3.conf
├── sites-enabled/             # Sites actifs (symlinks)
│   ├── site1.conf -> ../sites-available/site1.conf
│   └── site2.conf -> ../sites-available/site2.conf
├── snippets/                  # Fragments réutilisables
│   ├── ssl-params.conf
│   ├── proxy-params.conf
│   └── security-headers.conf
├── conf.d/                    # Configs globales
│   ├── gzip.conf
│   ├── cache.conf
│   └── rate-limit.conf
└── ssl/                       # Certificats
    ├── certs/
    └── private/


# === Snippets réutilisables ===

# /etc/nginx/snippets/ssl-params.conf
ssl_protocols TLSv1.2 TLSv1.3;
ssl_prefer_server_ciphers off;
ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256;
ssl_session_cache shared:SSL:10m;
ssl_session_timeout 10m;
ssl_stapling on;
ssl_stapling_verify on;

# /etc/nginx/snippets/proxy-params.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;
proxy_http_version 1.1;
proxy_set_header Connection "";

# /etc/nginx/snippets/security-headers.conf
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;

# Utilisation
server {
    listen 443 ssl http2;
    include snippets/ssl-params.conf;
    include snippets/security-headers.conf;
    
    location / {
        include snippets/proxy-params.conf;
        proxy_pass http://backend;
    }
}


# === Versionner configuration ===

# Git pour /etc/nginx
cd /etc/nginx
sudo git init
sudo git add .
sudo git commit -m "Initial nginx config"

# Avant modification
sudo git diff nginx.conf
sudo git commit -am "Update nginx.conf"


# === Tests automatisés ===

# Script test avant reload
#!/bin/bash
# test-nginx.sh

echo "Testing Nginx configuration..."
sudo nginx -t

if [ $? -eq 0 ]; then
    echo "[OK] Configuration OK"
    echo "Reloading Nginx..."
    sudo systemctl reload nginx
    echo "[OK] Nginx reloaded"
else
    echo "[X] Configuration error"
    exit 1
fi


# === Documentation ===

# Commenter configurations complexes
server {
    listen 443 ssl http2;
    server_name example.com;
    
    # SSL configuration
    # Certificat renouvelé tous les 90 jours (Let's Encrypt)
    # Contact: admin@example.com
    ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;
    
    # Rate limiting pour éviter abus API
    # Limite: 100 requêtes/minute par IP
    location /api/ {
        limit_req zone=api burst=20 nodelay;
        proxy_pass http://api_backend;
    }
}


# === Backup configuration ===

#!/bin/bash
# backup-nginx.sh

DATE=$(date +%Y%m%d_%H%M%S)
BACKUP_DIR="/backup/nginx"

mkdir -p $BACKUP_DIR

# Backup config
tar -czf $BACKUP_DIR/nginx-config-$DATE.tar.gz /etc/nginx/

# Garder seulement 30 derniers jours
find $BACKUP_DIR -name "nginx-config-*.tar.gz" -mtime +30 -delete

echo "Backup created: nginx-config-$DATE.tar.gz"


# === Monitoring ===

# Script check Nginx
#!/bin/bash
# check-nginx.sh

if ! systemctl is-active --quiet nginx; then
    echo "Nginx is down! Restarting..."
    systemctl start nginx
    
    # Notification (exemple avec mail)
    echo "Nginx was down and has been restarted" | mail -s "Nginx Alert" admin@example.com
fi

# Cron job
# */5 * * * * /usr/local/bin/check-nginx.sh


# === Rotation logs personnalisée ===

# Script rotation manuelle
#!/bin/bash
# rotate-logs.sh

LOG_DIR="/var/log/nginx"
DATE=$(date +%Y%m%d)

# Copier logs actuels
cp $LOG_DIR/access.log $LOG_DIR/access.log.$DATE
cp $LOG_DIR/error.log $LOG_DIR/error.log.$DATE

# Vider logs actuels
> $LOG_DIR/access.log
> $LOG_DIR/error.log

# Recharger Nginx
systemctl reload nginx

# Compresser anciens logs
gzip $LOG_DIR/access.log.$DATE
gzip $LOG_DIR/error.log.$DATE

# Supprimer logs > 30 jours
find $LOG_DIR -name "*.gz" -mtime +30 -delete


[OK] EXEMPLES CONFIGURATIONS COMPLÈTES


# === Site statique haute performance ===

server {
    listen 80;
    listen [::]:80;
    server_name example.com www.example.com;
    return 301 https://$server_name$request_uri;
}

server {
    listen 443 ssl http2;
    listen [::]:443 ssl http2;
    
    server_name example.com www.example.com;
    root /var/www/example;
    index index.html;
    
    # SSL
    ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;
    include snippets/ssl-params.conf;
    
    # Security headers
    include snippets/security-headers.conf;
    
    # Logs
    access_log /var/log/nginx/example-access.log;
    error_log /var/log/nginx/example-error.log;
    
    # Gzip
    gzip on;
    gzip_vary on;
    gzip_types text/plain text/css application/json application/javascript text/xml application/xml image/svg+xml;
    
    # Cache browser
    location ~* \.(jpg|jpeg|png|gif|ico|svg)$ {
        expires 1y;
        add_header Cache-Control "public, immutable";
        access_log off;
    }
    
    location ~* \.(css|js)$ {
        expires 1M;
        add_header Cache-Control "public";
        access_log off;
    }
    
    location / {
        try_files $uri $uri/ =404;
    }
    
    # Sécurité
    location ~ /\. {
        deny all;
    }
}


# === Application Node.js ===

upstream nodejs_backend {
    least_conn;
    server 127.0.0.1:3000 max_fails=3 fail_timeout=30s;
    server 127.0.0.1:3001 max_fails=3 fail_timeout=30s;
    keepalive 32;
}

server {
    listen 80;
    server_name app.example.com;
    return 301 https://$server_name$request_uri;
}

server {
    listen 443 ssl http2;
    server_name app.example.com;
    
    ssl_certificate /etc/letsencrypt/live/app.example.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/app.example.com/privkey.pem;
    include snippets/ssl-params.conf;
    
    client_max_body_size 50M;
    
    # Proxy headers
    location / {
        proxy_pass http://nodejs_backend;
        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;
        
        proxy_connect_timeout 60s;
        proxy_send_timeout 60s;
        proxy_read_timeout 60s;
    }
    
    # Fichiers statiques
    location /static/ {
        alias /var/www/app/static/;
        expires 1y;
        add_header Cache-Control "public, immutable";
    }
}


# === API REST avec rate limiting ===

limit_req_zone $binary_remote_addr zone=api_limit:10m rate=100r/m;

server {
    listen 443 ssl http2;
    server_name api.example.com;
    
    ssl_certificate /etc/letsencrypt/live/api.example.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/api.example.com/privkey.pem;
    
    # CORS
    add_header 'Access-Control-Allow-Origin' '*' always;
    add_header 'Access-Control-Allow-Methods' 'GET, POST, PUT, DELETE, OPTIONS' always;
    add_header 'Access-Control-Allow-Headers' 'Authorization, Content-Type' always;
    
    if ($request_method = 'OPTIONS') {
        return 204;
    }
    
    location /api/ {
        limit_req zone=api_limit burst=20 nodelay;
        
        proxy_pass http://api_backend;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        
        # Cache API responses
        proxy_cache api_cache;
        proxy_cache_valid 200 1m;
        proxy_cache_key "$request_uri";
        add_header X-Cache-Status $upstream_cache_status;
    }
}


[OK] EXEMPLES PRATIQUES COMPLETS

# === EXEMPLE 1: SITE WORDPRESS OPTIMISÉ ===

# Configuration production WordPress avec cache, sécurité, performance

upstream php {
    server unix:/var/run/php/php8.1-fpm.sock;
}

# Zone cache FastCGI
fastcgi_cache_path /var/cache/nginx/wordpress
                   levels=1:2
                   keys_zone=wordpress:100m
                   max_size=10g
                   inactive=60m;

server {
    # HTTP -> HTTPS
    listen 80;
    listen [::]:80;
    server_name wordpress.com www.wordpress.com;
    return 301 https://wordpress.com$request_uri;
}

server {
    # HTTPS
    listen 443 ssl http2;
    listen [::]:443 ssl http2;
    server_name wordpress.com www.wordpress.com;
    
    root /var/www/wordpress;
    index index.php;
    
    # SSL
    ssl_certificate /etc/letsencrypt/live/wordpress.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/wordpress.com/privkey.pem;
    ssl_protocols TLSv1.2 TLSv1.3;
    
    # Headers sécurité
    add_header Strict-Transport-Security "max-age=31536000" always;
    add_header X-Frame-Options "SAMEORIGIN" always;
    add_header X-Content-Type-Options "nosniff" always;
    
    # Upload
    client_max_body_size 64M;
    
    # Logs
    access_log /var/log/nginx/wordpress-access.log;
    error_log /var/log/nginx/wordpress-error.log;
    
    # === CONDITIONS SKIP CACHE ===
    set $skip_cache 0;
    
    if ($request_method = POST) {
        set $skip_cache 1;
    }
    
    if ($query_string != "") {
        set $skip_cache 1;
    }
    
    if ($request_uri ~* "/(wp-admin|wp-login.php|cart|checkout|my-account)") {
        set $skip_cache 1;
    }
    
    if ($http_cookie ~* "wordpress_logged_in|comment_author|woocommerce") {
        set $skip_cache 1;
    }
    
    # === SÉCURITÉ ===
    # Bloquer fichiers sensibles
    location ~ /\.(git|env|htaccess) {
        deny all;
        return 404;
    }
    
    # Bloquer xmlrpc.php (brute force)
    location = /xmlrpc.php {
        deny all;
    }
    
    # Bloquer PHP dans uploads
    location ~* /uploads/.*\.php$ {
        deny all;
    }
    
    # === FICHIERS STATIQUES ===
    location ~* \.(jpg|jpeg|png|gif|ico|svg|webp)$ {
        expires 1y;
        add_header Cache-Control "public, immutable";
        access_log off;
    }
    
    location ~* \.(css|js)$ {
        expires 1M;
        add_header Cache-Control "public";
        access_log off;
    }
    
    location ~* \.(woff|woff2|ttf|otf|eot)$ {
        expires 1y;
        add_header Access-Control-Allow-Origin "*";
        access_log off;
    }
    
    # === WORDPRESS REWRITE ===
    location / {
        try_files $uri $uri/ /index.php?$args;
    }
    
    # === PHP-FPM AVEC CACHE ===
    location ~ \.php$ {
        try_files $uri =404;
        
        include fastcgi_params;
        fastcgi_pass php;
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
        fastcgi_index index.php;
        
        # Cache FastCGI
        fastcgi_cache wordpress;
        fastcgi_cache_valid 200 60m;
        fastcgi_cache_bypass $skip_cache;
        fastcgi_no_cache $skip_cache;
        
        # Headers debug
        add_header X-Cache-Status $upstream_cache_status;
    }
}


# === EXEMPLE 2: APPLICATION NODE.JS (Express/React) ===

# SPA React avec backend Node.js API

upstream nodejs_backend {
    least_conn;
    server localhost:3000;
    keepalive 32;
}

# Rate limiting
limit_req_zone $binary_remote_addr zone=api_limit:10m rate=100r/m;

server {
    # HTTP -> HTTPS
    listen 80;
    server_name app.example.com;
    return 301 https://$server_name$request_uri;
}

server {
    # HTTPS
    listen 443 ssl http2;
    server_name app.example.com;
    
    # SSL
    ssl_certificate /etc/letsencrypt/live/app.example.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/app.example.com/privkey.pem;
    ssl_protocols TLSv1.2 TLSv1.3;
    
    # Headers sécurité
    add_header Strict-Transport-Security "max-age=31536000" always;
    add_header X-Frame-Options "SAMEORIGIN" always;
    add_header X-Content-Type-Options "nosniff" always;
    
    # Logs
    access_log /var/log/nginx/app-access.log;
    error_log /var/log/nginx/app-error.log;
    
    # === FRONTEND REACT (Build statique) ===
    root /var/www/app/build;
    index index.html;
    
    # Fichiers statiques React (JS, CSS, images)
    location /static/ {
        expires 1y;
        add_header Cache-Control "public, immutable";
        access_log off;
    }
    
    # === API BACKEND ===
    location /api/ {
        # Rate limiting
        limit_req zone=api_limit burst=20 nodelay;
        
        # Proxy vers Node.js
        proxy_pass http://nodejs_backend/;
        proxy_http_version 1.1;
        proxy_set_header Connection "";
        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;
    }
    
    # === REACT ROUTER (SPA Routing) ===
    location / {
        try_files $uri $uri/ /index.html;
        # Toutes routes non trouvées -> index.html
        # React Router gère le routing côté client
    }
}


# === EXEMPLE 3: SITE MULTI-LANGUES ===

# Site avec versions FR, EN, ES

server {
    listen 443 ssl http2;
    server_name example.com;
    
    ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;
    
    # Détecter langue navigateur
    set $lang "en";  # Langue par défaut
    
    if ($http_accept_language ~* ^fr) {
        set $lang "fr";
    }
    if ($http_accept_language ~* ^es) {
        set $lang "es";
    }
    
    # Rediriger vers version langue
    location = / {
        return 302 /$lang/;
    }
    
    # Version française
    location /fr/ {
        alias /var/www/example/fr/;
        try_files $uri $uri/ /fr/index.html;
    }
    
    # Version anglaise
    location /en/ {
        alias /var/www/example/en/;
        try_files $uri $uri/ /en/index.html;
    }
    
    # Version espagnole
    location /es/ {
        alias /var/www/example/es/;
        try_files $uri $uri/ /es/index.html;
    }
    
    # Fichiers statiques communs
    location /assets/ {
        alias /var/www/example/assets/;
        expires 1y;
    }
}


# === EXEMPLE 4: MICROSERVICES ===

# Plusieurs services backend derrière Nginx

upstream auth_service {
    server localhost:3001;
}

upstream users_service {
    server localhost:3002;
}

upstream orders_service {
    server localhost:3003;
}

upstream products_service {
    server localhost:3004;
}

server {
    listen 443 ssl http2;
    server_name api.example.com;
    
    ssl_certificate /etc/letsencrypt/live/api.example.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/api.example.com/privkey.pem;
    
    # Headers communs
    add_header X-Content-Type-Options "nosniff" always;
    
    # === AUTHENTIFICATION ===
    location /api/auth/ {
        proxy_pass http://auth_service/;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
    }
    
    # === UTILISATEURS ===
    location /api/users/ {
        proxy_pass http://users_service/;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
    }
    
    # === COMMANDES ===
    location /api/orders/ {
        proxy_pass http://orders_service/;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
    }
    
    # === PRODUITS ===
    location /api/products/ {
        proxy_pass http://products_service/;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
    }
    
    # Health check
    location /health {
        return 200 "OK\n";
        add_header Content-Type text/plain;
    }
}


# === EXEMPLE 5: CDN / ASSET SERVER ===

# Serveur dédié fichiers statiques (images, vidéos, etc.)

server {
    listen 443 ssl http2;
    server_name cdn.example.com;
    
    ssl_certificate /etc/letsencrypt/live/cdn.example.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/cdn.example.com/privkey.pem;
    
    root /var/www/cdn;
    
    # Headers CORS (autoriser tous domaines)
    add_header Access-Control-Allow-Origin "*" always;
    add_header Access-Control-Allow-Methods "GET, OPTIONS" always;
    
    # Pas de logs pour fichiers statiques
    access_log off;
    
    # === IMAGES ===
    location /images/ {
        expires 1y;
        add_header Cache-Control "public, immutable";
        
        # Optimisation: Servir WebP si supporté
        location ~ \.(jpe?g|png)$ {
            add_header Vary Accept;
            try_files $uri$webp_suffix $uri =404;
        }
    }
    
    # === VIDÉOS ===
    location /videos/ {
        expires 1M;
        add_header Cache-Control "public";
        
        # Streaming vidéo
        mp4;
        mp4_buffer_size 1m;
        mp4_max_buffer_size 5m;
    }
    
    # === TÉLÉCHARGEMENTS ===
    location /downloads/ {
        # Liste fichiers
        autoindex on;
        autoindex_exact_size off;
        autoindex_localtime on;
        
        # Limite vitesse téléchargement (anti-abus)
        limit_rate 1m;  # 1 MB/s max par connexion
    }
}


# === EXEMPLE 6: SITE E-COMMERCE (WooCommerce) ===

upstream php_fpm {
    server unix:/var/run/php/php8.1-fpm.sock;
}

# Cache
fastcgi_cache_path /var/cache/nginx/shop
                   levels=1:2
                   keys_zone=shop:100m
                   max_size=5g
                   inactive=30m;

# Rate limiting checkout
limit_req_zone $binary_remote_addr zone=checkout:10m rate=10r/m;

server {
    listen 443 ssl http2;
    server_name shop.example.com;
    
    root /var/www/shop;
    index index.php;
    
    ssl_certificate /etc/letsencrypt/live/shop.example.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/shop.example.com/privkey.pem;
    
    # Upload produits
    client_max_body_size 128M;
    
    # === CONDITIONS SKIP CACHE ===
    set $skip_cache 0;
    
    # Jamais cacher panier, checkout, compte
    if ($request_uri ~* "/(cart|checkout|my-account|addons)") {
        set $skip_cache 1;
    }
    
    # Jamais cacher si cookies WooCommerce
    if ($http_cookie ~* "woocommerce_items_in_cart|woocommerce_cart_hash|wordpress_logged_in") {
        set $skip_cache 1;
    }
    
    # POST requests
    if ($request_method = POST) {
        set $skip_cache 1;
    }
    
    # === SÉCURITÉ ===
    location ~ /\.(git|env) {
        deny all;
    }
    
    location = /xmlrpc.php {
        deny all;
    }
    
    # === FICHIERS STATIQUES ===
    location ~* \.(jpg|jpeg|png|gif|ico|svg|webp)$ {
        expires 1M;
        add_header Cache-Control "public";
        access_log off;
    }
    
    location ~* \.(css|js)$ {
        expires 7d;
        add_header Cache-Control "public";
        access_log off;
    }
    
    # === CHECKOUT (Rate limited) ===
    location ~* /(checkout|cart) {
        limit_req zone=checkout burst=5 nodelay;
        try_files $uri $uri/ /index.php?$args;
    }
    
    # === WORDPRESS/WOOCOMMERCE ===
    location / {
        try_files $uri $uri/ /index.php?$args;
    }
    
    # === PHP ===
    location ~ \.php$ {
        try_files $uri =404;
        
        include fastcgi_params;
        fastcgi_pass php_fpm;
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
        
        # Cache
        fastcgi_cache shop;
        fastcgi_cache_valid 200 30m;
        fastcgi_cache_bypass $skip_cache;
        fastcgi_no_cache $skip_cache;
        
        add_header X-Cache-Status $upstream_cache_status;
    }
}


[OK] CHECKLIST MISE EN PRODUCTION


# === Avant déploiement ===

[ ] Tester configuration: sudo nginx -t
[ ] Vérifier logs: sudo nginx -T
[ ] Backup config actuelle
[ ] Certificats SSL valides et à jour
[ ] Firewall configuré (ports 80, 443)
[ ] DNS configurés correctement
[ ] Rate limiting configuré
[ ] Security headers activés
[ ] Gzip/Brotli activé
[ ] Logs configurés et rotation active
[ ] Monitoring en place
[ ] Backup automatique configuré


# === Sécurité ===

[ ] SSL/TLS avec protocoles modernes uniquement
[ ] HSTS activé
[ ] server_tokens off
[ ] Headers de sécurité (X-Frame-Options, CSP, etc.)
[ ] Bloquer fichiers sensibles (.git, .env, etc.)
[ ] Rate limiting sur endpoints sensibles
[ ] Authentification sur zones admin
[ ] Firewall (UFW/iptables) configuré
[ ] Fail2ban installé et configuré
[ ] Logs sécurisés (permissions correctes)


# === Performance ===

[ ] Worker processes = nombre de CPU
[ ] Worker connections optimisé
[ ] Buffers configurés
[ ] Keepalive activé
[ ] Compression activée
[ ] Cache navigateur configuré
[ ] Cache proxy si nécessaire
[ ] Open file cache activé
[ ] HTTP/2 activé
[ ] CDN configuré si nécessaire


# === Monitoring ===

[ ] Status endpoint configuré
[ ] Logs centralisés
[ ] Alertes configurées
[ ] Métriques collectées
[ ] Tests de charge effectués
[ ] Plan de rollback préparé


[OK] RESSOURCES


# Documentation officielle
https://nginx.org/en/docs/

# Guide du débutant
https://nginx.org/en/docs/beginners_guide.html

# Wiki communautaire
https://www.nginx.com/resources/wiki/

# Configuration examples
https://github.com/nginx/nginx/tree/master/conf

# Test configuration SSL
https://www.ssllabs.com/ssltest/

# Test sécurité headers
https://securityheaders.com/

# Test performance
https://www.webpagetest.org/

# Outils
- Nginx Amplify (monitoring officiel)
- GoAccess (analyse logs)
- nginx-prometheus-exporter
- Grafana + Prometheus
- ELK Stack (logs)

# Livres recommandés
- "Nginx HTTP Server" - Clément Nedelcu
- "Nginx Cookbook" - Derek DeJonghe
- "Mastering Nginx" - Dimitri Aivaliotis

# Communautés
- Forum officiel: https://forum.nginx.org/
- Reddit: r/nginx
- Stack Overflow: [nginx]

# === FIN DU CHEATSHEET ===