# Fichier: python_cheats/cheatsheets/apache.txt
# Cheatsheet Apache HTTP Server - Guide Complet Pour Débutants


═══════════════════════════════════════════════════════════════
[DOCS] QU'EST-CE QU'APACHE ?
═══════════════════════════════════════════════════════════════

Apache HTTP Server (souvent appelé simplement "Apache") est un logiciel serveur web.
C'est le programme qui permet à votre ordinateur de servir des sites web sur Internet.

[OBJECTIF] ANALOGIE SIMPLE :
Imaginez un restaurant :
- Votre site web = les plats du menu
- Apache = le serveur qui apporte les plats aux clients
- Les visiteurs = les clients qui commandent
- HTTP = le langage utilisé pour communiquer les commandes

[OUTIL] CE QU'APACHE FAIT :
[OK] Écoute les demandes des navigateurs web (Chrome, Firefox, etc.)
[OK] Trouve les fichiers demandés (HTML, CSS, images, etc.)
[OK] Envoie ces fichiers au navigateur
[OK] Gère plusieurs sites sur une même machine
[OK] Sécurise les connexions avec HTTPS
[OK] Redirige les URLs
[OK] Compresse les fichiers pour accélérer le chargement

[GRAPHIQUE] STATISTIQUES :
- Créé en 1995 (plus de 25 ans d'existence)
- Utilisé par environ 30% des sites web dans le monde
- Gratuit et open source
- Fonctionne sur Linux, Windows, macOS

🆚 ALTERNATIVES :
- Nginx : Plus moderne, très performant
- LiteSpeed : Très rapide, compatible Apache
- IIS : Serveur Microsoft pour Windows
- Caddy : Moderne, SSL automatique


═══════════════════════════════════════════════════════════════
[GUIDE] CONCEPTS FONDAMENTAUX À COMPRENDRE
═══════════════════════════════════════════════════════════════

[WEB] 1. SERVEUR WEB
   Un programme qui attend des requêtes HTTP et renvoie des pages web
   Port par défaut : 80 (HTTP) et 443 (HTTPS)

[DOSSIER] 2. DOCUMENTROOT
   Le dossier racine où Apache cherche vos fichiers web
   Par défaut : /var/www/html/
   Exemple : Si DocumentRoot = /var/www/html/
            URL : http://example.com/page.html
            Fichier : /var/www/html/page.html

[ACCUEIL] 3. VIRTUAL HOST (VHOST)
   Permet d'héberger plusieurs sites sur un seul serveur
   Exemple : blog.com et shop.com sur la même machine
   Chaque site a sa propre configuration

[PLUGIN] 4. PORT
   Numéro identifiant un service réseau
   - 80 : HTTP (web normal)
   - 443 : HTTPS (web sécurisé)
   - 8080 : Port alternatif souvent utilisé pour tests

[SECURISE] 5. SSL/TLS (HTTPS)
   Protocole qui chiffre la communication
   Nécessite un certificat SSL
   Indispensable pour sites modernes (Google le favorise)

[DOC] 6. .htaccess
   Fichier de configuration au niveau répertoire
   Permet de modifier le comportement d'Apache
   Utile pour redirections, protection, cache

[SYNC] 7. MODULES
   Extensions qui ajoutent des fonctionnalités
   Exemples : mod_rewrite (redirections), mod_ssl (HTTPS)
   Se chargent/déchargent selon les besoins

[SYNC] 8. REVERSE PROXY
   Apache fait intermédiaire entre visiteur et application
   Utile pour Node.js, Python, Ruby applications
   Le visiteur ne communique jamais directement avec l'app


═══════════════════════════════════════════════════════════════
[COURS] WORKFLOW TYPIQUE D'UNE REQUÊTE
═══════════════════════════════════════════════════════════════

1. Visiteur tape "http://example.com/page.html" dans son navigateur
2. Navigateur envoie requête HTTP au serveur (port 80)
3. Apache reçoit la requête
4. Apache vérifie quel Virtual Host correspond à "example.com"
5. Apache regarde le DocumentRoot de ce Virtual Host
6. Apache trouve le fichier /var/www/html/page.html
7. Apache lit le fichier
8. Apache envoie le contenu au navigateur
9. Navigateur affiche la page

[ATTENTION] PROBLÈMES POSSIBLES :
- Port 80 bloqué -> Erreur "connexion impossible"
- Fichier introuvable -> Erreur 404
- Pas de permissions -> Erreur 403
- Erreur dans fichier PHP -> Erreur 500


[OK] INSTALLATION - PREMIERS PAS

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

# Installation simple et rapide
# Avantage: Apache démarre automatiquement après installation
# Version stable testée pour votre distribution

sudo apt update                    # Met à jour la liste des paquets
sudo apt install apache2          # Installe Apache

# Après installation, Apache démarre automatiquement !
# Testez en ouvrant votre navigateur sur http://localhost
# Vous devriez voir "Apache2 Ubuntu Default Page"

# Installer modules utiles (recommandé)
sudo apt install apache2-utils    # Outils supplémentaires (htpasswd, ab, etc.)

# Explication:
# - apache2: Le serveur web lui-même
# - apache2-utils: Outils en ligne de commande utiles
#   * htpasswd: créer mots de passe pour authentification
#   * ab: tester performance (Apache Benchmark)
#   * htdigest: authentification digest


# === RHEL / CENTOS / FEDORA ===

# Sur ces systèmes, Apache s'appelle "httpd" (HTTP Daemon)
# C'est le MÊME logiciel, juste un nom différent !

# RHEL/CentOS 7
sudo yum install httpd           # Installe Apache (appelé httpd)

# RHEL/CentOS 8+ / Fedora
sudo dnf install httpd           # dnf est le successeur de yum

# Note: Sur ces systèmes, Apache ne démarre PAS automatiquement
# Vous devez le démarrer manuellement:
sudo systemctl start httpd
sudo systemctl enable httpd      # Démarrage automatique au boot


# === MAC OS ===

# Apache est PRÉ-INSTALLÉ sur macOS !
# Mais version souvent ancienne, on recommande Homebrew

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

# Configuration dans: /usr/local/etc/httpd/
# Fichiers web dans: /usr/local/var/www/

# Démarrer Apache avec Homebrew:
brew services start httpd

# Si vous voulez utiliser l'Apache système (déjà installé):
sudo apachectl start


# === WINDOWS ===

# Apache sur Windows n'est PAS recommandé pour production
# Mais OK pour développement local

# Méthode 1: Apache Lounge (RECOMMANDÉ)
# 1. Aller sur https://www.apachelounge.com/download/
# 2. Télécharger "Apache 2.4.x Win64" (version VS17)
# 3. Télécharger aussi "Visual C++ Redistributable" si demandé
#
# 4. Extraire dans C:\Apache24
#
# 5. Ouvrir Command Prompt EN TANT QU'ADMINISTRATEUR
#
# 6. Installer comme service Windows:
cd C:\Apache24\bin
httpd.exe -k install
#
# 7. Démarrer Apache:
httpd.exe -k start

# Méthode 2: XAMPP (Plus facile, tout-en-un)
# Télécharger depuis: https://www.apachefriends.org/
# Inclut Apache + MySQL + PHP
# Interface graphique simple
# Parfait pour débutants

# Note importante Windows:
# - Apache est moins performant sur Windows
# - Recommandation: Utilisez WSL2 (Windows Subsystem for Linux)
#   puis installez Apache dans Ubuntu sous WSL2


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

# Vérifier la version d'Apache
apache2 -v                       # Ubuntu/Debian
httpd -v                         # RHEL/CentOS/Fedora

# Sortie attendue:
# Server version: Apache/2.4.52 (Ubuntu)
# Server built:   2024-01-09T22:03:56

# Version détaillée avec tous les modules compilés
apache2 -V                       # Ubuntu/Debian
httpd -V                         # RHEL/CentOS

# Affiche:
# - Version exacte
# - Options de compilation
# - Modules intégrés
# - Chemins importants (ServerRoot, etc.)


# Vérifier qu'Apache fonctionne
sudo systemctl status apache2    # Ubuntu/Debian
sudo systemctl status httpd      # RHEL/CentOS

# Sortie si Apache fonctionne:
# [BLACK_CIRCLE] apache2.service - The Apache HTTP Server
#    Loaded: loaded (/lib/systemd/system/apache2.service; enabled)
#    Active: active (running) since ...
# Si vous voyez "active (running)" = Tout va bien ! [OK]


# Tester dans le navigateur
# Ouvrir: http://localhost
# Ou: http://127.0.0.1
# Ou: http://votre-ip-serveur

# Vous devriez voir:
# - Ubuntu/Debian: "Apache2 Ubuntu Default Page"
# - RHEL/CentOS: "Testing 123..." page de test


# === PREMIERS TESTS ===

# Où est la page par défaut ?
# Ubuntu/Debian: /var/www/html/index.html
# RHEL/CentOS: /usr/share/httpd/noindex/index.html
# macOS (Homebrew): /usr/local/var/www/index.html

# Créons notre première page personnalisée:

# Ubuntu/Debian:
echo "<h1>Mon premier site avec Apache !</h1>" | sudo tee /var/www/html/index.html

# RHEL/CentOS:
echo "<h1>Mon premier site avec Apache !</h1>" | sudo tee /var/www/html/index.html

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


# Créer une page avec plus de contenu:
sudo tee /var/www/html/index.html > /dev/null << 'EOF'
<!DOCTYPE html>
<html lang="fr">
<head>
    <meta charset="UTF-8">
    <title>Mon premier site Apache</title>
    <style>
        body {
            font-family: Arial, sans-serif;
            max-width: 800px;
            margin: 50px auto;
            padding: 20px;
            background: #f5f5f5;
        }
        h1 {
            color: #D22128; /* Rouge Apache */
            text-align: center;
        }
        .info {
            background: white;
            padding: 20px;
            border-radius: 5px;
            box-shadow: 0 2px 5px rgba(0,0,0,0.1);
        }
    </style>
</head>
<body>
    <h1>[RAPIDE] Mon premier site avec Apache !</h1>
    <div class="info">
        <p>Félicitations ! Apache fonctionne correctement.</p>
        <p>Date: <?php echo date('d/m/Y H:i:s'); ?></p>
    </div>
</body>
</html>
EOF

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


# === DIFFÉRENCES UBUNTU vs CENTOS ===

# UBUNTU/DEBIAN          |  RHEL/CENTOS/FEDORA
# ---------------------- | ---------------------
# apache2                | httpd
# apache2.conf           | httpd.conf
# /etc/apache2/          | /etc/httpd/
# sites-available/       | conf.d/
# sites-enabled/         | conf.d/
# a2ensite               | pas d'équivalent
# a2dissite              | pas d'équivalent
# a2enmod                | pas d'équivalent
# a2dismod               | pas d'équivalent

# Sur Ubuntu: Structure modulaire avec outils dédiés (a2ensite, a2enmod)
# Sur CentOS: Structure plus simple, tout dans conf.d/


[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 Apache
# C'est le "chef d'orchestre" qui contrôle tous les services système

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

# IMPORTANT: Utilisez "apache2" sur Ubuntu/Debian
#            Utilisez "httpd" sur RHEL/CentOS/Fedora


# Démarrer Apache
sudo systemctl start apache2     # Ubuntu/Debian
sudo systemctl start httpd       # RHEL/CentOS

# Explication: Lance le serveur Apache
# Utilisez quand: Apache est arrêté et vous voulez le démarrer
# Les visiteurs peuvent maintenant accéder à votre site


# Arrêter Apache
sudo systemctl stop apache2      # Ubuntu/Debian
sudo systemctl stop httpd        # RHEL/CentOS

# Explication: Arrête complètement Apache
# Attention: Votre site devient INACCESSIBLE !
# Les connexions actives sont fermées immédiatement
# Utilisez quand: Maintenance majeure, mise à jour système


# Redémarrer Apache (arrêt puis démarrage)
sudo systemctl restart apache2   # Ubuntu/Debian
sudo systemctl restart httpd     # RHEL/CentOS

# Explication: Arrête puis redémarre complètement Apache
# Attention: Brève interruption de service (1-3 secondes)
# Les connexions actives sont coupées
# Utilisez quand: Vous avez modifié la config principale
#                 ou installé de nouveaux modules


# Recharger la configuration (SANS interruption) *
sudo systemctl reload apache2    # Ubuntu/Debian
sudo systemctl reload httpd      # RHEL/CentOS

# Explication: Recharge la config SANS couper les connexions
# C'est MAGIQUE: Les visiteurs actuels ne sont PAS déconnectés !
# Apache lit la nouvelle config et l'applique progressivement
# Utilisez quand: Vous avez modifié un VirtualHost, .htaccess, etc.
# C'est la commande que vous utiliserez 90% du temps !


# Activer le démarrage automatique au boot
sudo systemctl enable apache2    # Ubuntu/Debian
sudo systemctl enable httpd      # RHEL/CentOS

# Explication: Apache démarre automatiquement quand le serveur boot
# TRÈS IMPORTANT en production !
# À faire UNE FOIS après l'installation
# Sinon après un redémarrage serveur, votre site sera down


# Désactiver le démarrage automatique
sudo systemctl disable apache2   # Ubuntu/Debian
sudo systemctl disable httpd     # RHEL/CentOS

# Explication: Apache ne démarre plus automatiquement au boot
# Utilisez quand: Serveur de développement local
#                 ou si vous voulez contrôler manuellement


# Vérifier le statut d'Apache
sudo systemctl status apache2    # Ubuntu/Debian
sudo systemctl status httpd      # RHEL/CentOS

# Affiche plein d'informations utiles:
# [BLACK_CIRCLE] apache2.service - The Apache HTTP Server
#    Loaded: loaded (/lib/systemd/system/apache2.service; enabled)
#    Active: active (running) since Mon 2024-01-15 10:30:00 UTC
#    Main PID: 12345 (apache2)
#      Tasks: 55 (limit: 4915)
#    Memory: 15.2M
# 
# Signification:
# - Active: active (running) = Apache fonctionne [OK]
# - Active: inactive (dead) = Apache est arrêté [X]
# - Active: failed = Erreur au démarrage [X][X]
# - Main PID: le numéro du processus principal
# - Tasks: nombre de processus Apache actifs
# - Les dernières lignes montrent les logs récents


# Voir les logs en temps réel
sudo journalctl -u apache2 -f    # Ubuntu/Debian
sudo journalctl -u httpd -f      # RHEL/CentOS

# Explication:
# - journalctl: outil de consultation des logs systemd
# - -u apache2: filtre uniquement les logs Apache
# - -f: follow (mode continu, comme tail -f)
# Appuyez sur Ctrl+C pour quitter
# 
# Très utile pour:
# - Débugger les erreurs
# - Voir les accès en direct
# - Surveiller l'activité


# Voir les logs récents (sans mode continu)
sudo journalctl -u apache2 -n 50   # 50 dernières lignes
sudo journalctl -u httpd -n 50

# Voir les logs depuis un certain temps
sudo journalctl -u apache2 --since "1 hour ago"
sudo journalctl -u apache2 --since "2024-01-15 10:00:00"


# === COMMANDES APACHE DIRECTES (apachectl) ===

# apachectl est l'outil de contrôle "bas niveau" d'Apache
# Fonctionne même sans systemd (systèmes anciens, macOS)
# Sur Ubuntu/Debian, utilisez plutôt systemctl (plus moderne)


# Démarrer Apache
sudo apachectl start
# Simple et direct, mais systemctl est préférable


# Arrêter Apache proprement (graceful shutdown)
sudo apachectl stop
# Attend la fin des requêtes en cours
# Peut prendre quelques secondes


# Arrêt gracieux (encore plus doux)
sudo apachectl graceful-stop
# Attend que TOUTES les connexions se terminent
# Ne prend plus de nouvelles connexions
# Peut prendre plusieurs minutes si connexions longues


# Redémarrer Apache
sudo apachectl restart
# Équivalent à systemctl restart


# Rechargement gracieux de la configuration *
sudo apachectl graceful
# Recharge la config SANS couper les connexions
# Équivalent à systemctl reload
# Les connexions actives continuent avec l'ancienne config
# Les nouvelles connexions utilisent la nouvelle config
# MEILLEURE pratique pour changements de config


# Tester la configuration AVANT de recharger [ALERTE]
sudo apachectl configtest
sudo apachectl -t                # Version courte (équivalent)

# SUPER IMPORTANT ! TOUJOURS faire ça avant reload !
# Vérifie la syntaxe de TOUTE la configuration
# Si erreur, Apache vous dit EXACTEMENT où et quoi

# Exemple de sortie si OK:
# Syntax OK

# Exemple de sortie si ERREUR:
# AH00526: Syntax error on line 15 of /etc/apache2/sites-enabled/monsite.conf:
# Invalid command 'DocumentRot', perhaps misspelled or defined by a module not included

# Dans cet exemple:
# - Ligne 15 du fichier monsite.conf
# - "DocumentRot" au lieu de "DocumentRoot"
# Apache vous dit EXACTEMENT le problème !


# Afficher la configuration compilée complète
sudo apachectl -S
sudo apache2ctl -S               # Ubuntu/Debian

# Très utile ! Affiche:
# VirtualHost configuration:
# *:80                   monsite.com (/etc/apache2/sites-enabled/monsite.conf:1)
# *:443                  monsite.com (/etc/apache2/sites-enabled/monsite-ssl.conf:1)
# ServerRoot: "/etc/apache2"
# Main DocumentRoot: "/var/www/html"
# Main ErrorLog: "/var/log/apache2/error.log"
# Mutex: ...
#
# Permet de voir:
# - Tous vos VirtualHosts actifs
# - Sur quels ports ils écoutent
# - Quel fichier de config les définit
# - Détecter conflits ou doublons


# Afficher les modules chargés
apachectl -M
apache2ctl -M                    # Ubuntu/Debian

# Liste TOUS les modules actifs:
# Loaded Modules:
#  core_module (static)
#  so_module (static)
#  http_module (static)
#  mpm_prefork_module (static)
#  rewrite_module (shared)
#  ssl_module (shared)
#  ...
#
# (static) = compilé dans Apache
# (shared) = chargé dynamiquement (.so)


# Afficher uniquement modules compilés statiquement
apachectl -l

# Afficher la version
apache2 -v                       # Ubuntu/Debian
httpd -v                         # RHEL/CentOS

# Affiche:
# Server version: Apache/2.4.52 (Ubuntu)
# Server built:   2024-01-09T22:03:56


# Afficher version + détails compilation
apache2 -V                       # Ubuntu/Debian
httpd -V                         # RHEL/CentOS

# Très détaillé:
# Server version: Apache/2.4.52 (Ubuntu)
# Server built:   2024-01-09T22:03:56
# Server's Module Magic Number: 20120211:119
# Server loaded:  APR 1.7.0, APR-UTIL 1.6.1
# Compiled using: APR 1.7.0, APR-UTIL 1.6.1
# Architecture:   64-bit
# Server MPM:     prefork
#   threaded:     no
#    forked:      yes (variable process count)
# Server compiled with....
#  -D APR_HAS_SENDFILE
#  -D APR_HAS_MMAP
#  -D HTTPD_ROOT="/etc/apache2"
#  -D SUEXEC_BIN="/usr/lib/apache2/suexec"
#  -D DEFAULT_PIDLOG="/var/run/apache2.pid"
#  -D DEFAULT_SCOREBOARD="logs/apache_runtime_status"
#  -D DEFAULT_ERRORLOG="logs/error_log"
#  -D AP_TYPES_CONFIG_FILE="mime.types"
#  -D SERVER_CONFIG_FILE="apache2.conf"


# === COMMANDES UBUNTU/DEBIAN SPÉCIFIQUES ===

# Ubuntu/Debian ont des outils simplifiés avec a2* (apache2-*)

# Activer un site
sudo a2ensite monsite.conf       # Crée symlink dans sites-enabled/
# Équivaut à:
# sudo ln -s /etc/apache2/sites-available/monsite.conf /etc/apache2/sites-enabled/

# Désactiver un site
sudo a2dissite monsite.conf      # Supprime symlink
# Équivaut à:
# sudo rm /etc/apache2/sites-enabled/monsite.conf


# Activer un module
sudo a2enmod rewrite            # Active mod_rewrite
sudo a2enmod ssl                # Active mod_ssl
sudo a2enmod headers            # Active mod_headers

# Désactiver un module
sudo a2dismod rewrite
sudo a2dismod ssl


# Activer une config globale
sudo a2enconf security          # Active security.conf
sudo a2enconf charset           # Active charset.conf

# Désactiver une config globale
sudo a2disconf security


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

# Situation: Vous venez de modifier la configuration

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

# Étape 2: TOUJOURS tester AVANT de recharger ! [ALERTE]
sudo apachectl configtest
# ou
sudo apache2ctl -t

# Si vous voyez "Syntax OK":

# Étape 3: Recharger la configuration
sudo systemctl reload apache2    # Ubuntu/Debian
sudo systemctl reload httpd      # RHEL/CentOS
# ou
sudo apachectl graceful

# Étape 4: Vérifier que tout fonctionne
sudo systemctl status apache2
# Et tester dans le navigateur


# Si vous voyez une ERREUR:
# AH00526: Syntax error on line 15 of /etc/apache2/sites-enabled/monsite.conf:
# Invalid command 'DocumentRot'

# NE PAS recharger ! Corrigez d'abord l'erreur:
# 1. Ouvrir le fichier mentionné
sudo nano /etc/apache2/sites-enabled/monsite.conf

# 2. Aller à la ligne mentionnée (ici ligne 15)

# 3. Corriger l'erreur (DocumentRot -> DocumentRoot)

# 4. Sauvegarder

# 5. Retester
sudo apachectl configtest

# 6. Quand "Syntax OK", alors recharger
sudo systemctl reload apache2


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

# Scénario complet: Vous créez un nouveau site

# 1. Créer le fichier de config
sudo nano /etc/apache2/sites-available/monsite.conf

# 2. Activer le site (Ubuntu/Debian uniquement)
sudo a2ensite monsite.conf

# 3. Tester la configuration
sudo apachectl configtest

# Si "Syntax OK":

# 4. Recharger Apache
sudo systemctl reload apache2

# 5. Vérifier le statut
sudo systemctl status apache2

# 6. Tester dans le navigateur
# http://monsite.com (ou http://localhost si pas de DNS)

# 7. Si problème, voir les logs
sudo tail -f /var/log/apache2/error.log


# === COMMANDES DE DIAGNOSTIC ===

# Voir les processus Apache
ps aux | grep apache2            # Ubuntu/Debian
ps aux | grep httpd              # RHEL/CentOS

# Vous verrez:
# - 1 processus parent (lancé par root)
# - Plusieurs processus enfants (lancés par www-data ou apache)
# Exemple:
# root      1234  0.0  0.5  apache2 -k start
# www-data  1235  0.0  0.3  apache2 -k start
# www-data  1236  0.0  0.3  apache2 -k start


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

netstat -an | grep :443 | wc -l
# Affiche le nombre de connexions sur le port 443 (HTTPS)


# Voir qui écoute sur le port 80
sudo lsof -i :80
# Ou
sudo ss -tlnp | grep :80

# Utile si vous avez l'erreur:
# "(98)Address already in use: AH00072: make_sock: could not bind to address"


# Voir l'utilisation mémoire Apache
ps aux | grep apache2 | awk '{sum+=$6} END {print sum/1024 " MB"}'


# Tester la performance (Apache Benchmark)
ab -n 1000 -c 10 http://localhost/
# -n 1000: 1000 requêtes au total
# -c 10: 10 requêtes en parallèle


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

# Erreur 1: "Address already in use"
# AH00072: make_sock: could not bind to address 0.0.0.0:80
# 
# Cause: Un autre service (souvent Nginx) utilise déjà le port 80
# 
# Solution:
sudo systemctl stop nginx       # Arrêter Nginx
sudo lsof -i :80                # Vérifier qui utilise le port
sudo systemctl start apache2    # Démarrer Apache


# Erreur 2: "Could not reliably determine the server's fully qualified domain name"
# AH00558: apache2: Could not reliably determine the server's fully qualified domain name
# 
# Cause: Apache ne connaît pas le nom de domaine du serveur
# Ce n'est qu'un WARNING, Apache fonctionne quand même
# 
# Solution (optionnelle):
echo "ServerName localhost" | sudo tee -a /etc/apache2/apache2.conf
sudo systemctl reload apache2


# Erreur 3: "Job for apache2.service failed"
# 
# Cause: Erreur de configuration
# 
# Solution:
sudo apachectl configtest       # Voir l'erreur exacte
# Corriger l'erreur mentionnée
# Réessayer


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


# Erreur 5: "Forbidden - You don't have permission to access / on this server"
# 
# Cause: Mauvaises permissions sur les fichiers web
# 
# Solution:
sudo chown -R www-data:www-data /var/www/html/
sudo chmod -R 755 /var/www/html/
sudo chmod 644 /var/www/html/*.html


# === ASTUCE PRO ===

# Créer un alias pour tester + recharger en une commande

# Ubuntu/Debian:
echo 'alias apache-reload="sudo apachectl configtest && sudo systemctl reload apache2"' >> ~/.bashrc
source ~/.bashrc

# RHEL/CentOS:
echo 'alias apache-reload="sudo apachectl configtest && sudo systemctl reload httpd"' >> ~/.bashrc
source ~/.bashrc

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


# Alias pour voir les logs d'erreur en temps réel:
echo 'alias apache-errors="sudo tail -f /var/log/apache2/error.log"' >> ~/.bashrc  # Ubuntu
echo 'alias apache-errors="sudo tail -f /var/log/httpd/error_log"' >> ~/.bashrc    # CentOS
source ~/.bashrc

# Utilisation:
apache-errors


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

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

# Après modification de config (à chaque fois):
sudo apachectl configtest       # Tester
sudo systemctl reload apache2   # Recharger si OK

# Pour débugger:
sudo systemctl status apache2   # Voir le statut
sudo tail -f /var/log/apache2/error.log   # Voir les erreurs

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

# Commandes les plus utilisées:
# 1. apachectl configtest (avant chaque modification)
# 2. systemctl reload apache2 (après chaque modification)
# 3. systemctl status apache2 (en cas de problème)


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

# === COMPRENDRE L'ARBORESCENCE ===

# Apache organise ses fichiers différemment selon la distribution
# Chaque distribution a sa philosophie d'organisation
# C'est important de comprendre VOTRE système !


# === UBUNTU/DEBIAN (Structure modulaire) ===

/etc/apache2/                   # [DOSSIER] RACINE - Tous les fichiers de config
│                               # C'est le "quartier général" d'Apache
│
├── apache2.conf                # [CONFIG] FICHIER PRINCIPAL - Config globale
│                               # C'est le "cerveau" d'Apache
│                               # Définit les paramètres généraux du serveur
│                               # Inclut tous les autres fichiers
│                               # NE MODIFIEZ PAS directement (sauf cas précis)
│
├── ports.conf                  # [PLUGIN] PORTS D'ÉCOUTE
│                               # Définit sur quels ports Apache écoute
│                               # Par défaut: 80 (HTTP) et 443 (HTTPS)
│                               # Modifiez ici pour changer de port
│
├── envvars                     # [MONDE] VARIABLES D'ENVIRONNEMENT
│                               # Définit USER, GROUP, PID path, etc.
│                               # Utilisateur www-data par défaut
│
├── magic                       # [TOP_HAT] DÉTECTION TYPE FICHIERS
│                               # Règles pour détecter type de fichier
│                               # Rarement modifié
│
├── sites-available/           # [DOCS] SITES DISPONIBLES
│   │                          # TOUS vos VirtualHosts sont ici
│   │                          # C'est ICI que vous créez vos sites !
│   ├── 000-default.conf       # Site HTTP par défaut (port 80)
│   ├── default-ssl.conf       # Site HTTPS par défaut (port 443)
│   ├── monsite.com.conf       # <- Vous créerez vos sites ici
│   └── api.monsite.com.conf   # <- Un fichier par domaine/sous-domaine
│
├── sites-enabled/             # [LIEN] SITES ACTIFS
│   │                          # Contient des liens symboliques (symlinks)
│   │                          # vers sites-available/
│   │                          # Seuls les sites ICI sont actifs !
│   └── 000-default.conf -> ../sites-available/000-default.conf
│                               # ^ Ce lien "active" le site
│
├── mods-available/            # [MODULE] MODULES DISPONIBLES
│   │                          # TOUS les modules Apache disponibles
│   │                          # Chaque module a 2 fichiers:
│   ├── rewrite.load           # .load = charge le module (.so)
│   ├── rewrite.conf           # .conf = config du module (optionnel)
│   ├── ssl.load
│   ├── ssl.conf
│   ├── php8.2.load            # Module PHP
│   └── ...                    # + de 100 modules disponibles !
│
├── mods-enabled/              # [PLUGIN] MODULES ACTIFS
│   │                          # Symlinks vers mods-available/
│   │                          # Seuls les modules ICI sont chargés
│   ├── rewrite.load -> ../mods-available/rewrite.load
│   ├── ssl.load -> ../mods-available/ssl.load
│   ├── ssl.conf -> ../mods-available/ssl.conf
│   └── ...
│
├── conf-available/            # [CONFIG] CONFIGS GLOBALES DISPONIBLES
│   │                          # Configs qui s'appliquent à tout Apache
│   ├── charset.conf           # Encodage caractères
│   ├── security.conf          # Paramètres sécurité
│   ├── serve-cgi-bin.conf     # Scripts CGI
│   └── ...
│
├── conf-enabled/              # [OK] CONFIGS GLOBALES ACTIVES
│   │                          # Symlinks vers conf-available/
│   ├── charset.conf -> ../conf-available/charset.conf
│   ├── security.conf -> ../conf-available/security.conf
│   └── ...
│
└── modules/                   # [PACKAGE] MODULES COMPILÉS (.so)
    └── *.so                    # Fichiers binaires des modules


/var/www/                      # [WEB] RACINE WEB - Vos sites web ici
│
├── html/                      # [DOSSIER] Site par défaut
│   ├── index.html             # Page d'accueil par défaut
│   └── ...
│
├── monsite.com/               # [DOSSIER] Organisation recommandée
│   ├── public_html/           # Fichiers publics (DocumentRoot)
│   │   ├── index.html
│   │   ├── css/
│   │   ├── js/
│   │   └── images/
│   └── logs/                  # Logs spécifiques (optionnel)
│       ├── access.log
│       └── error.log
│
└── api.monsite.com/
    └── public_html/


/var/log/apache2/              # [GRAPHIQUE] LOGS - Fichiers journaux
├── access.log                 # [NOTE] LOG D'ACCÈS - Toutes les requêtes
│                              # Format: IP - - [date] "GET /page" 200 1234
│                              # Qui visite ? Quand ? Quelle page ? Quel résultat ?
├── error.log                  # [X] LOG D'ERREURS - Problèmes rencontrés
│                              # Erreurs 404, 500, PHP errors, etc.
├── other_vhosts_access.log    # [NOTE] Accès autres VirtualHosts
└── ssl_request.log            # [VERROUILLE] Requêtes SSL (si configuré)


/usr/lib/apache2/modules/      # [PACKAGE] BIBLIOTHÈQUE DES MODULES
└── *.so                        # Tous les fichiers .so (modules compilés)


/var/run/apache2/              # [RUNNER] FICHIERS D'EXÉCUTION
├── apache2.pid                # PID du processus principal
└── ...


# === COMPRENDRE LA PHILOSOPHIE UBUNTU/DEBIAN ===

# Structure modulaire avec système a2ensite/a2dissite
# 
# CONCEPT CLÉS:
# 1. *-available/ = Bibliothèque (tout ce qui existe)
# 2. *-enabled/ = Ce qui est actif (symlinks)
# 3. Commandes a2* pour activer/désactiver facilement
#
# AVANTAGES:
# - Organisation claire
# - Activer/désactiver sans supprimer fichiers
# - Facile de tester différentes configs
# - Rollback simple en cas d'erreur
#
# ANALOGIE: Bibliothèque de livres
# - sites-available = Tous vos livres sur l'étagère
# - sites-enabled = Les livres que vous lisez actuellement
# - a2ensite = Prendre un livre de l'étagère
# - a2dissite = Remettre un livre sur l'étagère


# === RHEL/CENTOS/FEDORA (Structure simple) ===

/etc/httpd/                    # [DOSSIER] RACINE - Tous les fichiers de config
│
├── conf/                      # [CONFIG] CONFIGURATION PRINCIPALE
│   ├── httpd.conf             # [LOGIQUE] FICHIER PRINCIPAL (tout est ici !)
│   │                          # Config globale + VirtualHosts
│   │                          # Sur CentOS, tout est dans ce fichier
│   └── magic                  # Détection type fichiers
│
├── conf.d/                    # [DOSSIER] CONFIGS ADDITIONNELLES
│   │                          # Vos VirtualHosts vont ICI
│   │                          # Tous les .conf sont chargés automatiquement
│   ├── welcome.conf           # Page de bienvenue par défaut
│   ├── ssl.conf               # Configuration SSL/HTTPS
│   ├── monsite.com.conf       # <- Créez vos sites ici
│   └── api.monsite.com.conf   # <- Un fichier par site
│
├── conf.modules.d/            # [PLUGIN] MODULES
│   │                          # Fichiers de chargement des modules
│   ├── 00-base.conf           # Modules de base
│   ├── 00-mpm.conf            # Multi-Processing Module
│   ├── 00-ssl.conf            # Module SSL
│   ├── 10-php.conf            # Module PHP (si installé)
│   └── ...
│
└── modules/                   # [PACKAGE] BIBLIOTHÈQUE MODULES
    └── *.so                    # Fichiers binaires modules


/var/www/                      # [WEB] RACINE WEB
├── html/                      # Site par défaut
│   └── index.html
└── monsite.com/               # Vos sites
    └── public_html/


/var/log/httpd/                # [GRAPHIQUE] LOGS
├── access_log                 # Accès (pas .log mais _log !)
├── error_log                  # Erreurs
└── ssl_access_log             # Accès SSL


/usr/lib64/httpd/modules/      # [PACKAGE] BIBLIOTHÈQUE MODULES (64-bit)
└── *.so


/var/run/httpd/                # [RUNNER] FICHIERS D'EXÉCUTION
└── httpd.pid


# === COMPRENDRE LA PHILOSOPHIE RHEL/CENTOS ===

# Structure simple et directe
# 
# CONCEPT CLÉS:
# 1. httpd.conf = Configuration principale monolithique
# 2. conf.d/ = Ajouts modulaires (include automatique)
# 3. Pas d'outils a2* (activation manuelle)
#
# AVANTAGES:
# - Plus simple à comprendre pour débutants
# - Moins de fichiers à gérer
# - Config centralisée
#
# INCONVÉNIENTS:
# - Pas de système enable/disable élégant
# - Faut renommer fichiers pour désactiver (.conf -> .conf.disabled)
#
# Pour désactiver un site sur CentOS:
sudo mv /etc/httpd/conf.d/monsite.conf /etc/httpd/conf.d/monsite.conf.disabled
sudo systemctl reload httpd

# Pour réactiver:
sudo mv /etc/httpd/conf.d/monsite.conf.disabled /etc/httpd/conf.d/monsite.conf
sudo systemctl reload httpd


# === MACOS (Homebrew) ===

/usr/local/etc/httpd/          # Configuration
├── httpd.conf                 # Config principale
└── extra/                     # Configs supplémentaires
    ├── httpd-vhosts.conf      # VirtualHosts
    ├── httpd-ssl.conf         # SSL
    └── ...

/usr/local/var/www/            # Racine web

/usr/local/var/log/httpd/      # Logs


# === WINDOWS ===

C:\Apache24\                   # (ou chemin d'installation choisi)
├── conf\
│   ├── httpd.conf            # Config principale
│   └── extra\
│       └── httpd-vhosts.conf # VirtualHosts
├── htdocs\                   # Racine web (DocumentRoot)
│   └── index.html
├── logs\                     # Logs
│   ├── access.log
│   └── error.log
└── modules\                  # Modules (.dll au lieu de .so)
    └── *.dll


# === FICHIER apache2.conf EXPLIQUÉ (Ubuntu/Debian) ===

# /etc/apache2/apache2.conf

# === SECTION GLOBALE ===

# Timeout: Temps max pour une requête
Timeout 300
# 300 secondes = 5 minutes
# Augmentez pour uploads de gros fichiers
# Diminuez pour éviter connexions qui traînent

# KeepAlive: Connexions persistantes
KeepAlive On
# On = Réutilise même connexion TCP pour plusieurs requêtes
# Beaucoup plus rapide ! (évite handshake TCP à chaque fois)
# Off = Nouvelle connexion pour chaque requête (lent)

MaxKeepAliveRequests 100
# Max 100 requêtes par connexion persistante
# Après 100 requêtes, connexion fermée et rouverte
# 100 est une bonne valeur par défaut

KeepAliveTimeout 5
# Garde connexion ouverte 5 secondes
# Si pas de nouvelle requête après 5s, connexion fermée
# Balance: trop court = reconnexions fréquentes
#         trop long = gaspille ressources

# === UTILISATEUR ET GROUPE ===

# Sur Ubuntu, défini dans /etc/apache2/envvars:
# export APACHE_RUN_USER=www-data
# export APACHE_RUN_GROUP=www-data

# Apache démarre en root (pour pouvoir écouter port 80)
# Puis les processus workers tournent en www-data (sécurité!)
# Si Apache est compromis, l'attaquant n'a que les droits de www-data


# === SERVEUR ET CHEMINS ===

# Dossier racine d'Apache
ServerRoot "/etc/apache2"
# Tous les chemins relatifs partent d'ici

# Fichier PID
PidFile ${APACHE_PID_FILE}
# Contient le numéro du processus principal
# Utilisé par systemctl pour contrôler Apache


# === GESTION DES PROCESSUS (MPM - Multi-Processing Module) ===

# Apache peut utiliser différents MPM:
# - prefork: 1 processus par requête (stable, compatible PHP non thread-safe)
# - worker: Processus + threads (plus performant, moins RAM)
# - event: Comme worker mais optimisé (recommandé Apache 2.4+)

# Configuration dans /etc/apache2/mods-available/mpm_prefork.conf:

<IfModule mpm_prefork_module>
    StartServers             5
    # Nombre processus au démarrage
    # 5 est bon pour petit serveur
    
    MinSpareServers          5
    MaxSpareServers         10
    # Garde entre 5 et 10 processus "de réserve"
    # Prêts à traiter requêtes immédiatement
    
    MaxRequestWorkers      150
    # Max 150 connexions simultanées
    # Au-delà, requêtes mises en attente
    # Calculez: RAM disponible / RAM par processus
    # Ex: 4GB RAM / 30MB par processus = ~130 workers
    
    MaxConnectionsPerChild   0
    # 0 = processus jamais recyclés
    # Nombre > 0 = recycle après X requêtes (évite fuites mémoire)
</IfModule>


# === DIRECTIVES PAR DÉFAUT ===

# Interdire accès à tout le système de fichiers
<Directory />
    Options None
    Require all denied
</Directory>
# Sécurité: Par défaut, TOUT est interdit
# Vous devez explicitement autoriser /var/www/

# Autoriser /var/www/
<Directory /var/www/>
    Options Indexes FollowSymLinks
    # Indexes: Affiche liste fichiers si pas d'index.html
    # FollowSymLinks: Autorise liens symboliques
    
    AllowOverride None
    # None: .htaccess ignorés (meilleure performance)
    # All: .htaccess autorisés (plus flexible)
    
    Require all granted
    # Tout le monde peut accéder
</Directory>

# DocumentRoot par défaut
DocumentRoot "/var/www/html"
# Racine du site web par défaut


# === LOGS ===

# Format des logs
LogFormat "%v:%p %h %l %u %t \"%r\" %>s %O \"%{Referer}i\" \"%{User-Agent}i\"" vhost_combined
LogFormat "%h %l %u %t \"%r\" %>s %O \"%{Referer}i\" \"%{User-Agent}i\"" combined
LogFormat "%h %l %u %t \"%r\" %>s %O" common

# Explication du format "combined":
# %h = IP du client
# %l = identd (toujours - en pratique)
# %u = utilisateur authentifié (si authentification)
# %t = date/heure [10/Jan/2024:14:30:00 +0000]
# %r = requête "GET /index.html HTTP/1.1"
# %>s = status code (200, 404, 500, etc.)
# %O = taille réponse en octets
# Referer = page d'où vient le visiteur
# User-Agent = navigateur du visiteur

# Exemple de ligne de log:
# 192.168.1.100 - - [10/Jan/2024:14:30:00 +0000] "GET /index.html HTTP/1.1" 200 1234 "https://google.com" "Mozilla/5.0..."

ErrorLog ${APACHE_LOG_DIR}/error.log
# Fichier log des erreurs
# APACHE_LOG_DIR défini dans envvars = /var/log/apache2

CustomLog ${APACHE_LOG_DIR}/access.log combined
# Fichier log des accès avec format "combined"


# === INCLUSIONS ===

# Charger ports
IncludeOptional ports.conf

# Charger modules actifs
IncludeOptional mods-enabled/*.load
IncludeOptional mods-enabled/*.conf

# Charger configs globales actives
IncludeOptional conf-enabled/*.conf

# Charger sites actifs
IncludeOptional sites-enabled/*.conf

# "IncludeOptional" = Inclut si fichier existe
# Pas d'erreur si fichier manquant
# "Include" = Erreur si fichier manquant


# FIN de apache2.conf


# === FICHIER httpd.conf EXPLIQUÉ (RHEL/CentOS) ===

# /etc/httpd/conf/httpd.conf

# Sur CentOS, TOUT est dans httpd.conf
# Beaucoup plus long que apache2.conf d'Ubuntu
# Mais même logique

ServerRoot "/etc/httpd"
# Racine Apache

Listen 80
# Écoute sur port 80
# Peut ajouter: Listen 8080 pour port additionnel

Include conf.modules.d/*.conf
# Charge tous les modules

User apache
Group apache
# Utilisateur/groupe pour processus workers
# "apache" sur CentOS (vs "www-data" sur Ubuntu)

ServerAdmin root@localhost
# Email admin (affiché sur pages d'erreur)

ServerName www.example.com:80
# Nom du serveur (optionnel mais recommandé)

DocumentRoot "/var/www/html"
# Racine site par défaut

<Directory "/var/www">
    AllowOverride None
    Require all granted
</Directory>

<Directory "/var/www/html">
    Options Indexes FollowSymLinks
    AllowOverride None
    Require all granted
</Directory>

ErrorLog "logs/error_log"
# Relatif à ServerRoot = /etc/httpd/logs/error_log
# En fait un symlink vers /var/log/httpd/error_log

CustomLog "logs/access_log" combined

# Inclure configs additionnelles
IncludeOptional conf.d/*.conf
# C'est ici que vos sites sont chargés !


# === COMMANDES UTILES POUR EXPLORER ===

# Voir la structure complète (Ubuntu)
tree /etc/apache2/
ls -lR /etc/apache2/

# Voir la structure (CentOS)
tree /etc/httpd/
ls -lR /etc/httpd/

# Lister les sites disponibles (Ubuntu)
ls -l /etc/apache2/sites-available/

# Lister les sites actifs (Ubuntu)
ls -l /etc/apache2/sites-enabled/

# Lister les sites (CentOS)
ls -l /etc/httpd/conf.d/

# Lister les modules actifs (Ubuntu)
ls -l /etc/apache2/mods-enabled/
# Ou mieux:
apachectl -M

# Lister les modules (CentOS)
ls -l /etc/httpd/conf.modules.d/
httpd -M

# Voir la configuration complète compilée
apachectl -S
# Très utile ! Montre tous les VirtualHosts et leur config

# Voir le fichier principal
cat /etc/apache2/apache2.conf    # Ubuntu
cat /etc/httpd/conf/httpd.conf   # CentOS

# Éditer le fichier principal (ATTENTION!)
sudo nano /etc/apache2/apache2.conf
sudo nano /etc/httpd/conf/httpd.conf

# Voir les logs en temps réel
sudo tail -f /var/log/apache2/access.log    # Ubuntu
sudo tail -f /var/log/httpd/access_log      # CentOS

sudo tail -f /var/log/apache2/error.log     # Ubuntu
sudo tail -f /var/log/httpd/error_log       # CentOS

# Chercher une erreur spécifique dans les logs
sudo grep "error" /var/log/apache2/error.log
sudo grep "404" /var/log/apache2/access.log


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

# Convention standard:
/var/www/                       # Racine de tous les sites
├── html/                       # Site par défaut
│   └── index.html
├── monsite.com/                # Un dossier par site
│   ├── public_html/            # Fichiers publics (DocumentRoot)
│   │   ├── index.html
│   │   ├── about.html
│   │   ├── css/
│   │   │   └── style.css
│   │   ├── js/
│   │   │   └── script.js
│   │   └── images/
│   │       └── logo.png
│   ├── logs/                   # Logs spécifiques (optionnel)
│   │   ├── access.log
│   │   └── error.log
│   └── private/                # Fichiers privés (hors DocumentRoot)
│       └── config.php
├── api.monsite.com/
│   └── public_html/
└── blog.monsite.com/
    └── public_html/

# Créer structure pour nouveau site:
sudo mkdir -p /var/www/monsite.com/{public_html,logs,private}
sudo chown -R $USER:www-data /var/www/monsite.com    # Ubuntu
sudo chown -R $USER:apache /var/www/monsite.com      # CentOS

# Créer page de test:
cat > /var/www/monsite.com/public_html/index.html << 'EOF'
<!DOCTYPE html>
<html lang="fr">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Mon Site</title>
    <style>
        body {
            font-family: Arial, sans-serif;
            max-width: 800px;
            margin: 50px auto;
            padding: 20px;
            background: #f0f0f0;
        }
        h1 {
            color: #D22128;
            text-align: center;
        }
        .card {
            background: white;
            padding: 30px;
            border-radius: 10px;
            box-shadow: 0 2px 10px rgba(0,0,0,0.1);
        }
    </style>
</head>
<body>
    <h1>[RAPIDE] Bienvenue sur monsite.com</h1>
    <div class="card">
        <h2>Site propulsé par Apache</h2>
        <p>Votre site fonctionne correctement !</p>
        <p><strong>Date:</strong> <script>document.write(new Date().toLocaleString('fr-FR'));</script></p>
    </div>
</body>
</html>
EOF


# === PERMISSIONS - TRÈS IMPORTANT ! ===

# Apache doit pouvoir LIRE vos fichiers
# Mais PAS les modifier (sécurité)
# Vous devez pouvoir modifier vos fichiers

# Règle d'or:
# - Propriétaire: VOUS (votre user)
# - Groupe: www-data (Ubuntu) ou apache (CentOS)
# - Permissions dossiers: 755 (rwxr-xr-x)
# - Permissions fichiers: 644 (rw-r--r--)

# Ubuntu:
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 {} \;

# CentOS:
sudo chown -R $USER:apache /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 des permissions:
# 755 = rwxr-xr-x
#       ├─┬─┼─┬─┼─┬─┤
#       │ │ │ │ │ │ └─ Autres: execute
#       │ │ │ │ │ └─── Autres: read
#       │ │ │ │ └───── Autres: NO write
#       │ │ │ └─────── Groupe: execute
#       │ │ └───────── Groupe: read
#       │ └─────────── Groupe: NO write
#       └───────────── Owner: read+write+execute
#
# 644 = rw-r--r--
#       Owner peut lire et écrire
#       Groupe et Autres peuvent juste lire


# Cas spécial: Dossier d'upload
# Si votre site permet uploads, ce dossier doit être écrivable par Apache

sudo mkdir /var/www/monsite.com/public_html/uploads
sudo chown www-data:www-data /var/www/monsite.com/public_html/uploads
sudo chmod 755 /var/www/monsite.com/public_html/uploads


# Vérifier les permissions
ls -la /var/www/monsite.com/
# Vous devriez voir:
# drwxr-xr-x  5 votre_user www-data  4096 Jan 10 14:30 .
# drwxr-xr-x  5 root       root      4096 Jan 10 14:25 ..
# drwxr-xr-x  4 votre_user www-data  4096 Jan 10 14:30 public_html
# -rw-r--r--  1 votre_user www-data  1234 Jan 10 14:30 index.html


# === EXEMPLE: CRÉER sites-available vs conf.d ===

# UBUNTU/DEBIAN (sites-available):

# 1. Créer le fichier de config
sudo nano /etc/apache2/sites-available/monsite.com.conf

# 2. Écrire la config (voir section VirtualHosts)

# 3. Activer le site
sudo a2ensite monsite.com.conf
# Cela crée: /etc/apache2/sites-enabled/monsite.com.conf -> ../sites-available/monsite.com.conf

# 4. Tester
sudo apachectl configtest

# 5. Recharger
sudo systemctl reload apache2

# Pour désactiver:
sudo a2dissite monsite.com.conf
sudo systemctl reload apache2


# RHEL/CENTOS (conf.d):

# 1. Créer directement dans conf.d/
sudo nano /etc/httpd/conf.d/monsite.com.conf

# 2. Écrire la config

# 3. Tester
sudo apachectl configtest

# 4. Recharger
sudo systemctl reload httpd

# Pour désactiver (renommer):
sudo mv /etc/httpd/conf.d/monsite.com.conf /etc/httpd/conf.d/monsite.com.conf.disabled
sudo systemctl reload httpd

# Pour réactiver:
sudo mv /etc/httpd/conf.d/monsite.com.conf.disabled /etc/httpd/conf.d/monsite.com.conf
sudo systemctl reload httpd


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

# Fichiers à connaître:

# UBUNTU:
# /etc/apache2/apache2.conf          -> Config globale (rarement modifié)
# /etc/apache2/sites-available/      -> Créer vos sites ICI
# /etc/apache2/sites-enabled/        -> Sites actifs (symlinks)
# /etc/apache2/mods-enabled/         -> Modules actifs
# /var/www/                          -> Vos fichiers HTML/CSS/JS ICI
# /var/log/apache2/                  -> Logs pour débugger

# CENTOS:
# /etc/httpd/conf/httpd.conf         -> Config globale
# /etc/httpd/conf.d/                 -> Créer vos sites ICI
# /etc/httpd/conf.modules.d/         -> Modules
# /var/www/                          -> Vos fichiers web ICI
# /var/log/httpd/                    -> Logs

# Workflow typique Ubuntu:
# 1. Créer site dans sites-available/
# 2. Activer avec a2ensite
# 3. Mettre fichiers dans /var/www/
# 4. Tester avec apachectl configtest
# 5. Recharger avec systemctl reload apache2

# Workflow typique CentOS:
# 1. Créer site dans conf.d/
# 2. Mettre fichiers dans /var/www/
# 3. Tester avec apachectl configtest
# 4. Recharger avec systemctl reload httpd

[OK] GESTION DES SITES - CRÉER ET GÉRER VOS SITES WEB

# === COMPRENDRE LES SITES VIRTUELS (VirtualHosts) ===

# Un VirtualHost = Un site web
# Apache peut héberger PLUSIEURS sites sur un même serveur
# Chaque site a sa propre configuration

# ANALOGIE: Immeuble d'appartements
# - Le serveur Apache = L'immeuble
# - Chaque VirtualHost = Un appartement
# - Chaque appartement a sa propre adresse (domaine)
# - Chaque appartement a sa propre décoration (config)

# Exemples de ce qu'on peut faire:
# - site1.com et site2.com sur le même serveur
# - example.com et blog.example.com (sous-domaine)
# - Site sur port 80 et application sur port 8080
# - Sites avec différents noms de domaine


# === UBUNTU/DEBIAN - GESTION AVEC a2ensite ===

# Sur Ubuntu, on utilise des commandes "a2*" (apache2-*)
# C'est simple et élégant !

# Activer un site (le rendre accessible)
sudo a2ensite nom-du-site.conf
sudo a2ensite 000-default.conf        # Site par défaut
sudo a2ensite monsite.com.conf        # Votre site

# Qu'est-ce que ça fait ?
# 1. Crée un lien symbolique (symlink) dans sites-enabled/
# 2. Pointe vers le fichier dans sites-available/
# 3. Le site devient actif !

# Exemple concret:
sudo a2ensite monsite.com.conf
# Sortie:
# Enabling site monsite.com.
# To activate the new configuration, you need to run:
#   systemctl reload apache2

# IMPORTANT: a2ensite ne recharge PAS Apache automatiquement
# Vous devez le faire manuellement:
sudo systemctl reload apache2
# Maintenant le site est en ligne !


# Désactiver un site (le rendre inaccessible)
sudo a2dissite nom-du-site.conf
sudo a2dissite 000-default.conf
sudo a2dissite monsite.com.conf

# Qu'est-ce que ça fait ?
# 1. Supprime le lien symbolique dans sites-enabled/
# 2. Le fichier dans sites-available/ reste intact
# 3. Le site n'est plus accessible
# 4. Vous pouvez le réactiver plus tard avec a2ensite

# Exemple:
sudo a2dissite 000-default.conf
# Sortie:
# Site 000-default disabled.
# To activate the new configuration, you need to run:
#   systemctl reload apache2

sudo systemctl reload apache2
# Le site n'est plus accessible


# Lister tous les sites disponibles
ls /etc/apache2/sites-available/
# Affiche tous vos fichiers de configuration
# Exemple de sortie:
# 000-default.conf  monsite.com.conf  blog.monsite.com.conf

ls -lh /etc/apache2/sites-available/
# Version détaillée avec permissions et tailles


# Lister les sites actifs (activés)
ls /etc/apache2/sites-enabled/
# Affiche uniquement les sites en ligne (symlinks)
# Exemple:
# 000-default.conf -> ../sites-available/000-default.conf
# monsite.com.conf -> ../sites-available/monsite.com.conf

ls -l /etc/apache2/sites-enabled/
# Montre clairement les liens symboliques avec ->


# Créer un nouveau site (workflow complet)

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

# Étape 2: Écrire la configuration (voir section VirtualHosts ci-dessous)

# Étape 3: Sauvegarder et quitter nano
# Ctrl+O (écrire), Entrée, Ctrl+X (quitter)

# Étape 4: TOUJOURS tester la configuration avant activation !
sudo apachectl configtest
# Ou version courte:
sudo apache2ctl -t

# Si vous voyez "Syntax OK" -> Tout va bien !
# Si erreur, corrigez avant de continuer

# Étape 5: Activer le site
sudo a2ensite monsite.com.conf

# Étape 6: Recharger Apache
sudo systemctl reload apache2

# Étape 7: Tester dans le navigateur
# http://monsite.com (ou http://localhost si pas de DNS)


# Vérifier la configuration avant de recharger (CRUCIAL!)
sudo apachectl configtest
sudo apache2ctl -t               # Version courte

# Pourquoi c'est CRUCIAL ?
# Si vous rechargez Apache avec une config invalide:
# - Apache peut refuser de redémarrer
# - Tous vos sites deviennent inaccessibles !
# - Panique et stress garantis [!]
#
# Avec configtest, vous vérifiez AVANT:
# - Erreur de syntaxe ? On corrige tranquillement
# - Syntax OK ? On peut recharger en toute sécurité

# Exemple d'erreur détectée:
# AH00526: Syntax error on line 5 of /etc/apache2/sites-available/monsite.com.conf:
# Invalid command 'DocumentRot', perhaps misspelled
#
# Apache vous dit EXACTEMENT:
# - Quel fichier: monsite.com.conf
# - Quelle ligne: ligne 5
# - Quel problème: DocumentRot au lieu de DocumentRoot


# === RHEL/CENTOS - GESTION MANUELLE ===

# Sur CentOS, pas de commandes a2ensite/a2dissite
# On gère les sites manuellement dans conf.d/

# Créer un nouveau site
sudo nano /etc/httpd/conf.d/monsite.com.conf

# Écrire la config

# Tester
sudo apachectl configtest

# Recharger
sudo systemctl reload httpd

# Le site est actif !


# Désactiver un site (renommer le fichier)
sudo mv /etc/httpd/conf.d/monsite.com.conf /etc/httpd/conf.d/monsite.com.conf.disabled
sudo systemctl reload httpd

# Pourquoi .disabled ?
# Apache charge tous les fichiers .conf dans conf.d/
# En renommant en .disabled, Apache l'ignore
# Le fichier existe toujours, juste pas chargé

# Réactiver le site
sudo mv /etc/httpd/conf.d/monsite.com.conf.disabled /etc/httpd/conf.d/monsite.com.conf
sudo systemctl reload httpd


# Lister les sites (CentOS)
ls -lh /etc/httpd/conf.d/
# Tous les fichiers .conf sont actifs


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

# Scénario: Créer site "boutique.com"

# 1. Créer dossier pour les fichiers web
sudo mkdir -p /var/www/boutique.com/public_html
sudo chown -R $USER:www-data /var/www/boutique.com

# 2. Créer page de test
cat > /var/www/boutique.com/public_html/index.html << 'EOF'
<!DOCTYPE html>
<html lang="fr">
<head>
    <meta charset="UTF-8">
    <title>Ma Boutique</title>
    <style>
        body {
            font-family: Arial, sans-serif;
            max-width: 800px;
            margin: 50px auto;
            text-align: center;
        }
        h1 { color: #D22128; }
    </style>
</head>
<body>
    <h1>Bienvenue sur Ma Boutique !</h1>
    <p>Le site fonctionne correctement.</p>
</body>
</html>
EOF

# 3. Créer fichier de configuration
sudo nano /etc/apache2/sites-available/boutique.com.conf

# 4. Copier cette configuration:
<VirtualHost *:80>
    ServerName boutique.com
    ServerAlias www.boutique.com
    DocumentRoot /var/www/boutique.com/public_html
    
    <Directory /var/www/boutique.com/public_html>
        Options Indexes FollowSymLinks
        AllowOverride All
        Require all granted
    </Directory>
    
    ErrorLog ${APACHE_LOG_DIR}/boutique-error.log
    CustomLog ${APACHE_LOG_DIR}/boutique-access.log combined
</VirtualHost>

# 5. Sauvegarder (Ctrl+O, Entrée, Ctrl+X)

# 6. Tester la config
sudo apachectl configtest

# 7. Si "Syntax OK", activer le site
sudo a2ensite boutique.com.conf

# 8. Recharger Apache
sudo systemctl reload apache2

# 9. Ajouter dans /etc/hosts pour test local (si pas de DNS)
echo "127.0.0.1  boutique.com www.boutique.com" | sudo tee -a /etc/hosts

# 10. Tester dans navigateur
# http://boutique.com

# Félicitations ! Votre site est en ligne ! [BRAVO]

[OK] GESTION DES MODULES - ACTIVER/DÉSACTIVER FONCTIONNALITÉS

# === COMPRENDRE LES MODULES ===

# Les modules = Extensions pour Apache
# Ajoutent des fonctionnalités supplémentaires
# Comme des plugins ou add-ons

# ANALOGIE: Smartphone
# - Apache de base = Téléphone avec fonctions de base
# - Modules = Applications que vous installez
# - mod_rewrite = App GPS (redirection URL)
# - mod_ssl = App sécurité (HTTPS)
# - mod_php = App pour exécuter code PHP

# Pourquoi activer/désactiver modules ?
# [OK] Performance: Moins de modules = Apache plus rapide
# [OK] Sécurité: Désactiver modules inutiles = moins de failles
# [OK] Fonctionnalités: Activer selon besoins


# === UBUNTU/DEBIAN - COMMANDES a2enmod ===

# Activer un module
sudo a2enmod nom_du_module

# Exemples courants:
sudo a2enmod rewrite           # URL rewriting (très utilisé!)
sudo a2enmod ssl               # HTTPS/SSL (obligatoire pour HTTPS)
sudo a2enmod headers           # Manipuler headers HTTP

# Sortie typique:
# Enabling module rewrite.
# To activate the new configuration, you need to run:
#   systemctl restart apache2

# IMPORTANT: Certains modules nécessitent RESTART (pas reload)
sudo systemctl restart apache2


# Désactiver un module
sudo a2dismod nom_du_module

# Exemples:
sudo a2dismod autoindex        # Désactive listage répertoires
sudo a2dismod status           # Désactive page status Apache

sudo systemctl restart apache2


# Lister tous les modules disponibles
ls /etc/apache2/mods-available/
# Affiche TOUS les modules installés
# Exemple de sortie:
# access_compat.load  deflate.load     rewrite.load
# alias.conf          dir.conf         ssl.conf
# alias.load          dir.load         ssl.load

# Chaque module peut avoir:
# - .load: Fichier de chargement (LoadModule ...)
# - .conf: Configuration optionnelle du module


# Lister les modules actifs (chargés)
sudo apachectl -M
sudo apache2ctl -M

# Sortie détaillée:
# Loaded Modules:
#  core_module (static)
#  so_module (static)
#  http_module (static)
#  mpm_prefork_module (static)
#  rewrite_module (shared)
#  ssl_module (shared)
#  php7_module (shared)
#  ...
#
# (static) = Compilé dans Apache (toujours présent)
# (shared) = Chargé dynamiquement (.so file)

# Ou voir les symlinks:
ls -l /etc/apache2/mods-enabled/


# === MODULES ESSENTIELS POUR DÉBUTANT ===

# mod_rewrite - Réécriture d'URL (URLs propres)
sudo a2enmod rewrite
sudo systemctl restart apache2

# Permet de transformer:
# monsite.com/index.php?page=contact
# En:
# monsite.com/contact
#
# Indispensable pour:
# - WordPress
# - URLs SEO-friendly
# - Redirection HTTP -> HTTPS


# mod_ssl - Support HTTPS/SSL
sudo a2enmod ssl
sudo a2enmod socache_shmcb     # Cache SSL (requis pour ssl)
sudo systemctl restart apache2

# Permet de:
# - Activer HTTPS
# - Sécuriser connexions
# - Utiliser certificats SSL


# mod_headers - Manipulation headers HTTP
sudo a2enmod headers
sudo systemctl restart apache2

# Permet de:
# - Ajouter headers de sécurité
# - Contrôler cache navigateur
# - CORS (Cross-Origin Resource Sharing)


# mod_expires - Contrôle d'expiration cache
sudo a2enmod expires
sudo systemctl restart apache2

# Permet de:
# - Définir durée cache navigateur
# - Accélérer site (moins de requêtes)
# - Réduire bande passante


# mod_deflate - Compression GZIP
sudo a2enmod deflate
sudo systemctl restart apache2

# Permet de:
# - Compresser fichiers envoyés (HTML, CSS, JS)
# - Réduire taille de 60-80%
# - Site plus rapide !


# mod_proxy et mod_proxy_http - Reverse proxy
sudo a2enmod proxy
sudo a2enmod proxy_http
sudo systemctl restart apache2

# Permet de:
# - Apache devant autre serveur (Node.js, Python)
# - Load balancing
# - Architecture microservices


# mod_proxy_fcgi - FastCGI (pour PHP-FPM)
sudo a2enmod proxy_fcgi
sudo systemctl restart apache2

# Permet de:
# - Utiliser PHP-FPM (plus performant que mod_php)
# - Meilleure gestion mémoire PHP


# mod_http2 - Support HTTP/2
sudo a2enmod http2
sudo systemctl restart apache2

# Permet de:
# - Activer HTTP/2 (plus rapide que HTTP/1.1)
# - Multiplexage requêtes
# - Compression headers


# mod_security2 - Web Application Firewall (WAF)
sudo apt install libapache2-mod-security2
sudo a2enmod security2
sudo systemctl restart apache2

# Permet de:
# - Protection contre attaques web
# - Filtrage requêtes malveillantes
# - Règles de sécurité OWASP


# === PACK DE MODULES POUR SITE MODERNE ===

# Configuration recommandée pour site moderne:

# Activer tous les modules essentiels:
sudo a2enmod rewrite          # URLs propres
sudo a2enmod ssl              # HTTPS
sudo a2enmod socache_shmcb    # Cache SSL
sudo a2enmod headers          # Headers sécurité
sudo a2enmod expires          # Cache navigateur
sudo a2enmod deflate          # Compression
sudo a2enmod http2            # HTTP/2

# Redémarrer Apache
sudo systemctl restart apache2

# Vérifier que tout est chargé
sudo apachectl -M | grep -E 'rewrite|ssl|headers|expires|deflate|http2'


# === RHEL/CENTOS - GESTION MANUELLE MODULES ===

# Sur CentOS, les modules sont dans conf.modules.d/

# Voir modules disponibles
ls /etc/httpd/conf.modules.d/
# Sortie:
# 00-base.conf  00-mpm.conf  00-ssl.conf  10-php.conf

# Activer un module
sudo nano /etc/httpd/conf.modules.d/00-base.conf

# Ajouter ligne:
LoadModule rewrite_module modules/mod_rewrite.so

# Sauvegarder

# Redémarrer Apache
sudo systemctl restart httpd


# Désactiver un module (commenter la ligne)
sudo nano /etc/httpd/conf.modules.d/00-base.conf

# Mettre # devant:
#LoadModule autoindex_module modules/mod_autoindex.so

# Sauvegarder et redémarrer
sudo systemctl restart httpd


# Lister modules chargés (CentOS)
httpd -M


# === MODULES À DÉSACTIVER POUR SÉCURITÉ ===

# Ces modules sont souvent inutiles et peuvent être une faille

# autoindex - Liste fichiers d'un répertoire
sudo a2dismod autoindex
# Problème: Si pas d'index.html, affiche tous vos fichiers !
# Risque: Révèle structure de votre site

# status - Page de statut Apache
sudo a2dismod status
# Problème: Affiche infos sur serveur Apache
# Risque: Donne infos à attaquant potentiel

# userdir - Répertoires utilisateurs ~/public_html
sudo a2dismod userdir
# Problème: Permet accès répertoires utilisateurs système
# Risque: Exposition informations

sudo systemctl restart apache2


# === DÉPANNAGE MODULES ===

# Erreur: "Invalid command 'RewriteEngine'"
# Cause: mod_rewrite pas activé
# Solution:
sudo a2enmod rewrite
sudo systemctl restart apache2


# Erreur: "Invalid command 'SSLEngine'"
# Cause: mod_ssl pas activé
# Solution:
sudo a2enmod ssl
sudo systemctl restart apache2


# Erreur: "Cannot load modules/mod_xxx.so"
# Cause: Module pas installé
# Solution Ubuntu:
sudo apt install libapache2-mod-xxx

# Solution CentOS:
sudo yum install mod_xxx


# Voir dépendances d'un module
# Certains modules dépendent d'autres
# Exemple: ssl dépend de socache_shmcb

# Si vous activez ssl sans socache_shmcb:
sudo a2enmod ssl
# Sortie:
# Considering dependency socache_shmcb for ssl:
# Module socache_shmcb already enabled
# 
# Apache active automatiquement les dépendances !


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

# Modules essentiels à activer:
sudo a2enmod rewrite ssl headers expires deflate
sudo systemctl restart apache2

# Modules à désactiver (sécurité):
sudo a2dismod autoindex status userdir
sudo systemctl restart apache2

# Vérifier modules actifs:
sudo apachectl -M

# En cas d'erreur "Invalid command":
# -> Le module correspondant n'est pas activé
# -> Utilisez a2enmod pour l'activer


[OK] CONFIGURATION VIRTUALHOST - CRÉER VOS SITES WEB

# === COMPRENDRE LES VIRTUALHOSTS ===

# VirtualHost = Configuration d'un site web
# Un fichier = Un site

# STRUCTURE DE BASE:
# <VirtualHost *:80>
#     Configuration du site ici
# </VirtualHost>

# *:80 signifie:
# * = Toutes les adresses IP du serveur
# 80 = Port HTTP standard


# === VIRTUALHOST BASIQUE (HTTP) - LE MINIMUM ===

# Créer le fichier:
sudo nano /etc/apache2/sites-available/monsite.conf

# Copier cette configuration:

<VirtualHost *:80>
    # === IDENTIFICATION DU SITE ===
    
    ServerName example.com
    # Le nom de domaine principal
    # C'est l'adresse que les gens taperont dans le navigateur
    # Exemple: monsite.com, boutique.fr, blog.example.com
    
    ServerAlias www.example.com
    # Alias = noms alternatifs pour le même site
    # Permet d'accéder au site avec ou sans www
    # Vous pouvez avoir plusieurs ServerAlias:
    # ServerAlias www.example.com example.fr www.example.fr
    
    ServerAdmin admin@example.com
    # Email de l'administrateur
    # Affiché sur les pages d'erreur Apache
    # Les utilisateurs peuvent vous contacter si problème
    
    
    # === LOCALISATION DES FICHIERS ===
    
    DocumentRoot /var/www/monsite
    # DocumentRoot = Racine du site
    # C'est le dossier contenant index.html, CSS, JS, images
    # /var/www/monsite/index.html devient http://example.com/index.html
    # /var/www/monsite/images/logo.png devient http://example.com/images/logo.png
    
    
    # === PERMISSIONS DU RÉPERTOIRE ===
    
    <Directory /var/www/monsite>
        # Configuration spécifique à ce dossier
        
        Options Indexes FollowSymLinks
        # Options = Fonctionnalités autorisées
        #
        # Indexes: Si pas d'index.html, affiche liste fichiers
        #          [ATTENTION] Désactivez en production (sécurité)
        #          Pour désactiver: Options -Indexes
        #
        # FollowSymLinks: Autorise liens symboliques
        #                 Permet d'utiliser ln -s
        #
        # Autres options possibles:
        # - ExecCGI: Exécuter scripts CGI
        # - Includes: Server Side Includes (SSI)
        # - MultiViews: Négociation contenu
        # - None: Désactive toutes options
        
        AllowOverride All
        # AllowOverride = Autorisation .htaccess
        #
        # All: .htaccess peut tout modifier
        #      Flexible mais moins performant
        #      Bien pour développement
        #
        # None: .htaccess ignorés
        #       Meilleure performance
        #       Bien pour production (si pas besoin .htaccess)
        #
        # Valeurs spécifiques:
        # - AuthConfig: Seulement authentification
        # - Indexes: Seulement listage répertoires
        # - Limit: Seulement contrôle accès
        
        Require all granted
        # Require = Contrôle d'accès
        #
        # all granted: Tout le monde peut accéder
        #              Site public
        #
        # all denied: Personne ne peut accéder
        #             Site fermé
        #
        # ip 192.168.1.0/24: Seulement ce réseau
        #
        # valid-user: Seulement utilisateurs authentifiés
    </Directory>
    
    
    # === LOGS ===
    
    ErrorLog ${APACHE_LOG_DIR}/monsite-error.log
    # Fichier des erreurs (404, 500, PHP errors, etc.)
    # ${APACHE_LOG_DIR} = /var/log/apache2/ (Ubuntu)
    #                   = /var/log/httpd/ (CentOS)
    #
    # Résultat final: /var/log/apache2/monsite-error.log
    #
    # Utile pour débugger !
    # Voir en temps réel: sudo tail -f /var/log/apache2/monsite-error.log
    
    CustomLog ${APACHE_LOG_DIR}/monsite-access.log combined
    # Fichier des accès (toutes les requêtes)
    # Format "combined" = Format détaillé standard
    # Contient: IP, date, page, navigateur, etc.
    #
    # Exemple de ligne:
    # 192.168.1.100 - - [15/Jan/2024:10:30:00 +0000] "GET /index.html HTTP/1.1" 200 1234
    #
    # Formats disponibles:
    # - combined: Très détaillé (recommandé)
    # - common: Basique
    # - vhost_combined: Avec nom VirtualHost
</VirtualHost>

# Sauvegarder le fichier (Ctrl+O, Entrée, Ctrl+X)

# Activer le site
sudo a2ensite monsite.conf

# Tester la configuration
sudo apachectl configtest

# Recharger Apache
sudo systemctl reload apache2


# === VIRTUALHOST SSL (HTTPS) - SITE SÉCURISÉ ===

# HTTPS = HTTP + SSL/TLS
# Chiffre les données entre navigateur et serveur
# Obligatoire pour sites modernes (Google pénalise sites HTTP)

# Prérequis:
# 1. Avoir un certificat SSL (Let's Encrypt, commercial, auto-signé)
# 2. Activer mod_ssl

sudo a2enmod ssl
sudo a2enmod socache_shmcb
sudo systemctl restart apache2

# Créer le fichier:
sudo nano /etc/apache2/sites-available/monsite-ssl.conf

<VirtualHost *:443>
    # Port 443 = Port HTTPS standard
    
    ServerName example.com
    ServerAlias www.example.com
    ServerAdmin admin@example.com
    
    DocumentRoot /var/www/monsite
    
    
    # === CONFIGURATION SSL ===
    
    SSLEngine on
    # Active le chiffrement SSL pour ce VirtualHost
    
    SSLCertificateFile /etc/ssl/certs/example.com.crt
    # Certificat SSL (fichier .crt ou .pem)
    # Contient la clé publique
    # C'est ce que le navigateur vérifie
    
    SSLCertificateKeyFile /etc/ssl/private/example.com.key
    # Clé privée (fichier .key)
    # [ATTENTION] TRÈS IMPORTANT: Ce fichier doit rester SECRET !
    # Permissions: chmod 600
    # Ne JAMAIS partager ou commiter dans Git !
    
    SSLCertificateChainFile /etc/ssl/certs/example.com.ca-bundle
    # Chaîne de certificats (optionnel mais recommandé)
    # Certificats intermédiaires de l'autorité (CA)
    # Améliore compatibilité navigateurs
    # Let's Encrypt fournit ce fichier automatiquement
    
    
    # === CONFIGURATION SSL MODERNE (Sécurité renforcée) ===
    
    SSLProtocol all -SSLv3 -TLSv1 -TLSv1.1
    # Protocoles SSL/TLS autorisés
    #
    # all: Tous les protocoles
    # -SSLv3: DÉSACTIVE SSLv3 (obsolète, vulnérable)
    # -TLSv1: DÉSACTIVE TLS 1.0 (obsolète)
    # -TLSv1.1: DÉSACTIVE TLS 1.1 (obsolète)
    #
    # Résultat: Seulement TLS 1.2 et TLS 1.3
    # C'est ce qu'il faut en 2024 !
    
    SSLCipherSuite HIGH:!aNULL:!MD5
    # Suites de chiffrement autorisées
    #
    # HIGH: Chiffrement fort uniquement
    # !aNULL: Interdit chiffrement nul (pas de chiffrement)
    # !MD5: Interdit MD5 (obsolète, vulnérable)
    #
    # Plus sécurisé (recommandé 2024):
    # SSLCipherSuite ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256
    
    SSLHonorCipherOrder on
    # Le serveur choisit l'algorithme de chiffrement
    # Pas le client
    # Empêche client de forcer algorithme faible
    
    
    # === OPTIMISATIONS SSL (optionnel mais recommandé) ===
    
    SSLSessionCache shmcb:${APACHE_RUN_DIR}/ssl_scache(512000)
    # Cache les sessions SSL
    # Évite de refaire handshake complet à chaque requête
    # 512000 = 512 KB de cache
    # Site beaucoup plus rapide avec HTTPS !
    
    SSLSessionCacheTimeout 300
    # Durée cache session: 300 secondes = 5 minutes
    
    SSLOptions +StdEnvVars
    # Exporte variables SSL dans environnement
    # Permet à PHP/scripts d'accéder infos SSL
    
    
    # === HEADERS DE SÉCURITÉ (Très recommandé!) ===
    
    Header always set Strict-Transport-Security "max-age=31536000; includeSubDomains"
    # HSTS: Force HTTPS pour 1 an
    # Le navigateur se souviendra d'utiliser HTTPS
    # includeSubDomains: Applique aussi aux sous-domaines
    # [ATTENTION] N'activez que si HTTPS fonctionne parfaitement !
    
    
    <Directory /var/www/monsite>
        Options -Indexes +FollowSymLinks
        # -Indexes: Désactive listage (sécurité)
        # +FollowSymLinks: Active liens symboliques
        
        AllowOverride All
        Require all granted
    </Directory>
    
    ErrorLog ${APACHE_LOG_DIR}/monsite-ssl-error.log
    CustomLog ${APACHE_LOG_DIR}/monsite-ssl-access.log combined
</VirtualHost>

# Activer le site SSL
sudo a2ensite monsite-ssl.conf
sudo apachectl configtest
sudo systemctl reload apache2


# === REDIRECTION HTTP vers HTTPS ===

# Scénario: Vous voulez que TOUT passe en HTTPS
# Si quelqu'un va sur http://example.com
# -> Redirection automatique vers https://example.com

# Modifier le VirtualHost HTTP (*:80):
sudo nano /etc/apache2/sites-available/monsite.conf

<VirtualHost *:80>
    ServerName example.com
    ServerAlias www.example.com
    
    # MÉTHODE 1: Redirect (Simple)
    Redirect permanent / https://example.com/
    # permanent = Code 301 (redirection permanente)
    # / = Toutes les pages
    # Les navigateurs et Google comprennent que le site a déménagé en HTTPS
    
    # Exemples de redirections:
    # http://example.com/ -> https://example.com/
    # http://example.com/contact -> https://example.com/contact
    # http://example.com/blog/article -> https://example.com/blog/article
</VirtualHost>

# OU

<VirtualHost *:80>
    ServerName example.com
    ServerAlias www.example.com
    
    # MÉTHODE 2: RewriteEngine (Plus flexible)
    RewriteEngine On
    # Active le moteur de réécriture d'URL
    
    RewriteCond %{HTTPS} off
    # Condition: Si HTTPS est désactivé (donc HTTP)
    # %{HTTPS} = Variable Apache
    # off = Pas en HTTPS
    
    RewriteRule ^(.*)$ https://%{HTTP_HOST}$1 [R=301,L]
    # Règle de réécriture:
    # ^(.*)$ = Toute URL (regex)
    # https:// = Passer en HTTPS
    # %{HTTP_HOST} = Nom de domaine (example.com)
    # $1 = Le chemin capturé dans (.*)
    # [R=301,L] = Redirection 301, Last (arrêter traitement)
    #
    # Exemple:
    # http://example.com/contact
    # -> https://example.com/contact
</VirtualHost>

# Quelle méthode choisir ?
# - Redirect: Plus simple, suffisant 90% cas
# - RewriteEngine: Plus flexible, pour cas complexes


# === VIRTUALHOST AVEC SOUS-DOMAINES ===

# Scénario: Plusieurs sous-domaines pour différents services
# - example.com -> Site principal
# - blog.example.com -> Blog
# - api.example.com -> API
# - admin.example.com -> Administration

# Site principal
<VirtualHost *:80>
    ServerName example.com
    ServerAlias www.example.com
    DocumentRoot /var/www/main
    
    <Directory /var/www/main>
        Options -Indexes +FollowSymLinks
        AllowOverride All
        Require all granted
    </Directory>
    
    ErrorLog ${APACHE_LOG_DIR}/main-error.log
    CustomLog ${APACHE_LOG_DIR}/main-access.log combined
</VirtualHost>

# Blog (sous-domaine)
<VirtualHost *:80>
    ServerName blog.example.com
    # Pas de ServerAlias (sous-domaine unique)
    
    DocumentRoot /var/www/blog
    
    <Directory /var/www/blog>
        Options -Indexes +FollowSymLinks
        AllowOverride All
        Require all granted
    </Directory>
    
    ErrorLog ${APACHE_LOG_DIR}/blog-error.log
    CustomLog ${APACHE_LOG_DIR}/blog-access.log combined
</VirtualHost>

# API (sous-domaine)
<VirtualHost *:80>
    ServerName api.example.com
    DocumentRoot /var/www/api
    
    <Directory /var/www/api>
        # API: pas besoin d'index, désactiver navigation
        Options -Indexes +FollowSymLinks
        AllowOverride All
        Require all granted
        
        # Headers CORS pour API
        Header always set Access-Control-Allow-Origin "*"
        Header always set Access-Control-Allow-Methods "GET, POST, PUT, DELETE, OPTIONS"
        Header always set Access-Control-Allow-Headers "Content-Type, Authorization"
    </Directory>
    
    ErrorLog ${APACHE_LOG_DIR}/api-error.log
    CustomLog ${APACHE_LOG_DIR}/api-access.log combined
</VirtualHost>

# Administration (sous-domaine protégé)
<VirtualHost *:80>
    ServerName admin.example.com
    DocumentRoot /var/www/admin
    
    <Directory /var/www/admin>
        Options -Indexes +FollowSymLinks
        AllowOverride All
        
        # Restriction par IP (sécurité!)
        Require ip 192.168.1.0/24
        # Seulement accessible depuis réseau local
        # Ou ajouter votre IP publique
        
        # OU authentification par mot de passe
        # AuthType Basic
        # AuthName "Administration"
        # AuthUserFile /etc/apache2/.htpasswd
        # Require valid-user
    </Directory>
    
    ErrorLog ${APACHE_LOG_DIR}/admin-error.log
    CustomLog ${APACHE_LOG_DIR}/admin-access.log combined
</VirtualHost>

# Note DNS: N'oubliez pas de créer les enregistrements DNS !
# blog.example.com -> A -> Votre_IP_Serveur
# api.example.com -> A -> Votre_IP_Serveur
# admin.example.com -> A -> Votre_IP_Serveur


# === VIRTUALHOST BASÉ SUR IP (Rare) ===

# Scénario: Plusieurs adresses IP sur le serveur
# Chaque IP héberge un site différent

# Vérifier vos IPs:
ip addr show

# Site 1 sur première IP
<VirtualHost 192.168.1.10:80>
    ServerName site1.com
    DocumentRoot /var/www/site1
    
    <Directory /var/www/site1>
        Options -Indexes +FollowSymLinks
        AllowOverride All
        Require all granted
    </Directory>
</VirtualHost>

# Site 2 sur deuxième IP
<VirtualHost 192.168.1.11:80>
    ServerName site2.com
    DocumentRoot /var/www/site2
    
    <Directory /var/www/site2>
        Options -Indexes +FollowSymLinks
        AllowOverride All
        Require all granted
    </Directory>
</VirtualHost>

# Cas d'usage:
# - SSL avec certificat par IP (ancien, obsolète maintenant)
# - Isolation stricte entre sites
# - Contraintes réseau spécifiques


# === VIRTUALHOST AVEC PLUSIEURS PORTS ===

# Scénario: Application sur port non-standard
# Exemple: App Node.js derrière Apache sur port 8080

# Étape 1: Dire à Apache d'écouter sur le port
# Éditer /etc/apache2/ports.conf
sudo nano /etc/apache2/ports.conf

# Ajouter:
Listen 80
Listen 443
Listen 8080      # <- Nouveau port
Listen 8081      # <- Autre port si besoin

# Sauvegarder

# Étape 2: Créer VirtualHost pour ce port
<VirtualHost *:8080>
    ServerName example.com:8080
    # Important: Inclure :8080 dans ServerName
    
    DocumentRoot /var/www/app1
    
    <Directory /var/www/app1>
        Options -Indexes +FollowSymLinks
        AllowOverride All
        Require all granted
    </Directory>
    
    ErrorLog ${APACHE_LOG_DIR}/app1-error.log
    CustomLog ${APACHE_LOG_DIR}/app1-access.log combined
</VirtualHost>

# Application sur port 8081
<VirtualHost *:8081>
    ServerName example.com:8081
    DocumentRoot /var/www/app2
    
    <Directory /var/www/app2>
        Options -Indexes +FollowSymLinks
        AllowOverride All
        Require all granted
    </Directory>
    
    ErrorLog ${APACHE_LOG_DIR}/app2-error.log
    CustomLog ${APACHE_LOG_DIR}/app2-access.log combined
</VirtualHost>

# Accès:
# http://example.com:8080 -> app1
# http://example.com:8081 -> app2

# Note pare-feu: Ouvrir les ports
sudo ufw allow 8080/tcp
sudo ufw allow 8081/tcp


# === REVERSE PROXY (Apache devant autre application) ===

# Scénario courant: Application Node.js/Python/Java
# L'app tourne sur localhost:3000
# Apache fait interface avec le monde extérieur

# Activer modules nécessaires
sudo a2enmod proxy
sudo a2enmod proxy_http
sudo systemctl restart apache2

<VirtualHost *:80>
    ServerName app.example.com
    
    # Pas de DocumentRoot !
    # Apache redirige tout vers l'application
    
    ProxyPreserveHost On
    # Garde le nom d'hôte original dans les requêtes
    
    ProxyPass / http://localhost:3000/
    # Redirige TOUTES les requêtes vers localhost:3000
    # / = Toutes les URLs
    # http://localhost:3000/ = Application backend
    
    ProxyPassReverse / http://localhost:3000/
    # Ajuste les headers de réponse
    # Nécessaire pour redirections correctes
    
    # Logs
    ErrorLog ${APACHE_LOG_DIR}/app-error.log
    CustomLog ${APACHE_LOG_DIR}/app-access.log combined
</VirtualHost>

# Exemple concret:
# Utilisateur va sur: http://app.example.com/api/users
# Apache redirige vers: http://localhost:3000/api/users
# L'application Node.js répond
# Apache renvoie la réponse à l'utilisateur

# Avantages:
# - Application n'a pas besoin de gérer SSL
# - Apache gère sécurité, logs, cache
# - Peut avoir plusieurs apps derrière un Apache


# === RÉSUMÉ DÉBUTANT - CRÉER UN SITE ===

# 1. Créer dossier web
sudo mkdir -p /var/www/monsite.com/public_html

# 2. Mettre fichiers dedans
echo "<h1>Mon Site</h1>" > /var/www/monsite.com/public_html/index.html

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

# 4. Créer config VirtualHost
sudo nano /etc/apache2/sites-available/monsite.com.conf

# 5. Copier config de base (voir ci-dessus)

# 6. Activer site
sudo a2ensite monsite.com.conf

# 7. Tester config
sudo apachectl configtest

# 8. Recharger Apache
sudo systemctl reload apache2

# 9. Tester dans navigateur
# http://monsite.com


[OK] FICHIER .HTACCESS - CONFIGURATION PAR RÉPERTOIRE

# === COMPRENDRE .HTACCESS ===

# .htaccess = "Hypertext Access"
# Fichier de configuration Apache par répertoire
# Placé dans DocumentRoot (ou sous-dossiers)
# Permet de modifier config sans toucher VirtualHost

# ANALOGIE: Règlement d'immeuble
# - VirtualHost = Règlement général de l'immeuble
# - .htaccess = Règlement spécifique d'un appartement
# - Chaque dossier peut avoir son .htaccess

# Points importants:
# [OK] Nom commence par . (fichier caché)
# [OK] Pas d'extension (.htaccess, pas .htaccess.txt)
# [OK] Un .htaccess par dossier
# [OK] S'applique au dossier + sous-dossiers
# [OK] Nécessite AllowOverride All dans VirtualHost

# Avantages:
# + Pas besoin de recharger Apache
# + Modifications immédiates
# + Pas besoin accès root
# + Parfait pour hébergement partagé

# Inconvénients:
# - Moins performant (Apache lit à chaque requête)
# - Moins sécurisé (modifiable par utilisateur web)
# - Peut causer conflits si mal configuré


# === CRÉER UN .HTACCESS ===

# Se placer dans DocumentRoot
cd /var/www/monsite.com/public_html

# Créer le fichier
nano .htaccess

# Ou avec sudo si nécessaire
sudo nano .htaccess


# === VÉRIFIER QUE .HTACCESS FONCTIONNE ===

# Dans votre VirtualHost, vérifier:
<Directory /var/www/monsite>
    AllowOverride All    # <- Doit être "All" ou valeur spécifique
    # Si "None", .htaccess est ignoré !
</Directory>

# Tester si .htaccess est lu:
# 1. Créer .htaccess avec erreur volontaire
echo "TEST_INVALIDE" > /var/www/monsite.com/public_html/.htaccess

# 2. Aller sur votre site
# Si erreur 500 -> .htaccess est lu [OK]
# Si site fonctionne -> .htaccess ignoré [X]

# 3. Supprimer le test
rm /var/www/monsite.com/public_html/.htaccess


# === REDIRECTIONS URL ===

# Créer/éditer .htaccess
nano /var/www/monsite.com/public_html/.htaccess

# --- Redirection simple ---
Redirect 301 /old-page.html /new-page.html
# 301 = Redirection permanente
# /old-page.html = Ancienne URL
# /new-page.html = Nouvelle URL
#
# Effet:
# http://monsite.com/old-page.html -> http://monsite.com/new-page.html

# Codes de redirection:
# 301 = Permanent (Google suit, recommandé SEO)
# 302 = Temporaire (Google ne suit pas)
# 303 = See Other (après POST)
# 307 = Temporaire (garde méthode HTTP)

# Exemples pratiques:
Redirect 301 /about-us.html /about.html
Redirect 301 /products /shop
Redirect 301 /blog/old-article /blog/new-article


# --- Redirection vers autre domaine ---
Redirect 301 / https://nouveau-site.com/
# Redirige TOUT le site vers nouveau domaine
# / = Toutes les pages
#
# http://ancien-site.com/contact -> https://nouveau-site.com/contact
# http://ancien-site.com/blog -> https://nouveau-site.com/blog


# --- Redirection avec RewriteEngine (plus puissant) ---

# Activer le moteur de réécriture
RewriteEngine On
# TOUJOURS mettre en premier !

# Redirection simple avec RewriteRule
RewriteRule ^old-page\.html$ /new-page.html [R=301,L]
# ^old-page\.html$ = Pattern regex
# ^ = Début d'URL
# \. = Point littéral (échappé)
# $ = Fin d'URL
# [R=301,L] = Flags
#   R=301 = Redirect 301
#   L = Last (arrêter le traitement)

# Exemples de patterns regex:
# ^contact$ = Exactement "contact"
# ^blog/.+$ = blog/ suivi de n'importe quoi
# ^page-([0-9]+)$ = page-123, page-456, etc.
# \.php$ = Termine par .php


# --- Forcer HTTPS ---
RewriteEngine On
RewriteCond %{HTTPS} off
# Condition: Si pas en HTTPS
# %{HTTPS} = Variable Apache
# off = HTTP (pas sécurisé)

RewriteRule ^(.*)$ https://%{HTTP_HOST}/$1 [R=301,L]
# Redirige vers HTTPS en gardant même URL
# (.*) = Capture tout le chemin
# %{HTTP_HOST} = Nom de domaine
# $1 = Le chemin capturé
#
# Exemple:
# http://monsite.com/contact
# -> https://monsite.com/contact


# --- Forcer WWW ---
RewriteEngine On
RewriteCond %{HTTP_HOST} !^www\.
# Condition: Si nom ne commence PAS par www.
# !^ = NOT commence par
# \. = Point littéral

RewriteRule ^(.*)$ https://www.%{HTTP_HOST}/$1 [R=301,L]
# Ajoute www. au début
#
# Exemple:
# http://monsite.com -> https://www.monsite.com
# http://monsite.com/blog -> https://www.monsite.com/blog


# --- Retirer WWW ---
RewriteEngine On
RewriteCond %{HTTP_HOST} ^www\.(.+)$ [NC]
# Condition: Si commence par www.
# (.+) = Capture le reste du domaine
# [NC] = No Case (insensible casse)

RewriteRule ^(.*)$ https://%1/$1 [R=301,L]
# %1 = Premier groupe capturé dans RewriteCond
# $1 = Groupe capturé dans RewriteRule
#
# Exemple:
# http://www.monsite.com -> https://monsite.com


# --- Combiné: HTTPS + WWW ---
RewriteEngine On

# Force HTTPS
RewriteCond %{HTTPS} off
RewriteRule ^(.*)$ https://%{HTTP_HOST}/$1 [R=301,L]

# Force WWW
RewriteCond %{HTTP_HOST} !^www\.
RewriteRule ^(.*)$ https://www.%{HTTP_HOST}/$1 [R=301,L]


# === URL REWRITING (URLs propres) ===

# --- Masquer extension .php ---
RewriteEngine On

# Si fichier existe avec .php, le servir
RewriteCond %{REQUEST_FILENAME} !-d
# Condition: N'est PAS un répertoire
# !-d = NOT directory

RewriteCond %{REQUEST_FILENAME}.php -f
# Condition: Fichier .php existe
# -f = IS file

RewriteRule ^(.*)$ $1.php [L]
# Ajoute .php silencieusement
#
# Effet:
# http://monsite.com/contact
# -> Sert contact.php
# L'utilisateur ne voit pas .php dans l'URL !


# --- URLs façon WordPress/Laravel ---
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
# Pas un fichier existant
RewriteCond %{REQUEST_FILENAME} !-d
# Pas un répertoire existant

RewriteRule ^(.*)$ index.php?url=$1 [QSA,L]
# Envoie tout à index.php
# ?url=$1 = Passe l'URL en paramètre
# [QSA,L] = Query String Append, Last
#
# Exemples:
# /blog/article -> index.php?url=blog/article
# /contact -> index.php?url=contact
# /api/users/123 -> index.php?url=api/users/123
#
# index.php analyse $1 et affiche la bonne page


# --- URLs avec paramètres nommés ---
RewriteRule ^article/([0-9]+)$ article.php?id=$1 [L]
# Capture l'ID numérique
# ([0-9]+) = Un ou plusieurs chiffres
#
# Exemples:
# /article/123 -> article.php?id=123
# /article/456 -> article.php?id=456

RewriteRule ^user/([a-zA-Z0-9_]+)$ profile.php?username=$1 [L]
# Capture le username
# ([a-zA-Z0-9_]+) = Lettres, chiffres, underscore
#
# /user/john_doe -> profile.php?username=john_doe


# === PROTECTION PAR MOT DE PASSE ===

# Protéger tout le site
AuthType Basic
# Type d'authentification: Basic (simple, suffisant 90% cas)

AuthName "Zone protégée"
# Message affiché dans popup de connexion
# Peut être n'importe quoi

AuthUserFile /var/www/.htpasswd
# Chemin ABSOLU vers fichier contenant utilisateurs
# [ATTENTION] Doit être hors DocumentRoot (sécurité!)
# PAS /var/www/monsite/public_html/.htpasswd
# OUI /var/www/.htpasswd

Require valid-user
# Exige un utilisateur valide
# N'importe quel user du fichier peut accéder

# Créer le fichier .htpasswd (voir section suivante)


# --- Protéger un fichier spécifique ---
<Files "admin.php">
    AuthType Basic
    AuthName "Administration"
    AuthUserFile /var/www/.htpasswd
    Require valid-user
</Files>
# Seul admin.php est protégé
# Le reste du site est public


# --- Protéger un répertoire ---
<Directory /var/www/monsite/public_html/admin>
    AuthType Basic
    AuthName "Panel Admin"
    AuthUserFile /var/www/.htpasswd
    Require valid-user
</Directory>
# Tout dans /admin/ est protégé


# --- Restreindre à certains utilisateurs ---
AuthType Basic
AuthName "Zone VIP"
AuthUserFile /var/www/.htpasswd
Require user john marie
# Seuls john et marie peuvent accéder
# Les autres users du .htpasswd sont refusés


# === CONTRÔLE D'ACCÈS PAR IP ===

# --- Bloquer une IP spécifique ---
Require all granted
Require not ip 192.168.1.100
# Tout le monde peut accéder SAUF 192.168.1.100

Require not ip 10.0.0.0/8
# Bloquer tout le réseau 10.x.x.x


# --- Autoriser seulement certaines IPs ---
Require ip 192.168.1.0/24
# Seulement réseau local 192.168.1.x

Require ip 10.0.0.5
Require ip 192.168.1.100
# Seulement ces 2 IPs spécifiques


# --- Bloquer un pays (avec mod_geoip) ---
# Nécessite mod_geoip installé
<IfModule mod_geoip.c>
    GeoIPEnable On
    RewriteEngine On
    RewriteCond %{ENV:GEOIP_COUNTRY_CODE} ^(CN|RU)$
    # Bloquer Chine (CN) et Russie (RU)
    RewriteRule .* - [F]
    # [F] = Forbidden
</IfModule>


# === CONTRÔLE DU CACHE NAVIGATEUR ===

# Le cache permet au navigateur de garder fichiers localement
# Réduit requêtes serveur = Site plus rapide + Moins de bande passante

# --- Désactiver complètement le cache ---
<FilesMatch "\.(html|htm|js|css)$">
    Header set Cache-Control "no-cache, no-store, must-revalidate"
    # no-cache: Doit valider auprès serveur
    # no-store: Ne pas stocker localement
    # must-revalidate: Toujours vérifier fraîcheur
    
    Header set Pragma "no-cache"
    # Pour navigateurs HTTP/1.0 anciens
    
    Header set Expires 0
    # Date d'expiration immédiate
</FilesMatch>

# Cas d'usage:
# - Développement (voir changements immédiatement)
# - Pages très dynamiques
# - Contenu sensible (admin, compte)


# --- Cache optimal pour images ---
<FilesMatch "\.(jpg|jpeg|png|gif|ico|svg|webp)$">
    Header set Cache-Control "max-age=2592000, public"
    # max-age=2592000 = 30 jours (en secondes)
    # public = Peut être caché par tous (CDN, proxies)
</FilesMatch>

# Images changent rarement, on peut cacher longtemps
# 2592000 secondes = 30 jours
# Calcul: 30 jours × 24h × 60min × 60sec = 2592000


# --- Cache pour CSS et JavaScript ---
<FilesMatch "\.(js|css)$">
    Header set Cache-Control "max-age=604800, public"
    # max-age=604800 = 7 jours
    # 7 × 24 × 60 × 60 = 604800
</FilesMatch>

# CSS/JS changent plus souvent que images
# 7 jours = Bon compromis


# --- Cache avec versioning (technique pro) ---
<FilesMatch "\.(js|css)$">
    Header set Cache-Control "max-age=31536000, public, immutable"
    # max-age=31536000 = 1 an !
    # immutable = Ne jamais revalider
</FilesMatch>

# Comment ça marche ?
# 1. Versionner les fichiers: style.css?v=1.2.3
# 2. Changer version quand fichier change
# 3. Navigateur voit nouvelle URL, télécharge
# 4. Ancien fichier reste caché (pas de problème)
#
# Exemple HTML:
# <link rel="stylesheet" href="style.css?v=1.2.3">
# Après modification:
# <link rel="stylesheet" href="style.css?v=1.2.4">


# --- Expires headers (ancienne méthode, toujours valable) ---
<IfModule mod_expires.c>
    ExpiresActive On
    # Active la gestion des expirations
    
    # Images
    ExpiresByType image/jpg "access plus 1 year"
    ExpiresByType image/jpeg "access plus 1 year"
    ExpiresByType image/png "access plus 1 year"
    ExpiresByType image/gif "access plus 1 year"
    ExpiresByType image/webp "access plus 1 year"
    ExpiresByType image/svg+xml "access plus 1 year"
    ExpiresByType image/x-icon "access plus 1 year"
    
    # CSS et JavaScript
    ExpiresByType text/css "access plus 1 month"
    ExpiresByType application/javascript "access plus 1 month"
    ExpiresByType text/javascript "access plus 1 month"
    
    # HTML (court)
    ExpiresByType text/html "access plus 1 hour"
    
    # Polices
    ExpiresByType font/woff "access plus 1 year"
    ExpiresByType font/woff2 "access plus 1 year"
    ExpiresByType font/ttf "access plus 1 year"
    ExpiresByType font/otf "access plus 1 year"
    
    # Vidéos
    ExpiresByType video/mp4 "access plus 1 year"
    ExpiresByType video/webm "access plus 1 year"
</IfModule>

# "access plus 1 year" = À partir du moment où fichier est accédé + 1 an


# === COMPRESSION GZIP (Réduire taille fichiers) ===

# La compression réduit taille de 60-80% !
# Site beaucoup plus rapide
# Moins de bande passante

# Activer mod_deflate (si pas déjà fait)
# sudo a2enmod deflate
# sudo systemctl restart apache2

<IfModule mod_deflate.c>
    # Compresser HTML
    AddOutputFilterByType DEFLATE text/html
    # text/html = Pages HTML
    
    # Compresser CSS
    AddOutputFilterByType DEFLATE text/css
    
    # Compresser JavaScript
    AddOutputFilterByType DEFLATE text/javascript
    AddOutputFilterByType DEFLATE application/javascript
    AddOutputFilterByType DEFLATE application/x-javascript
    
    # Compresser JSON et XML
    AddOutputFilterByType DEFLATE application/json
    AddOutputFilterByType DEFLATE application/xml
    AddOutputFilterByType DEFLATE text/xml
    
    # Compresser polices
    AddOutputFilterByType DEFLATE font/ttf
    AddOutputFilterByType DEFLATE font/otf
    AddOutputFilterByType DEFLATE font/woff
    AddOutputFilterByType DEFLATE font/woff2
    
    # Compresser SVG
    AddOutputFilterByType DEFLATE image/svg+xml
    
    # NE PAS compresser les images déjà compressées
    # (jpg, png, gif sont déjà compressés)
    # Les recompresser gaspille CPU sans gain
</IfModule>

# Résultat typique:
# Fichier CSS 100 KB -> 20 KB compressé (80% gain!)
# Page HTML 50 KB -> 10 KB compressé (80% gain!)


# --- Configuration avancée compression ---
<IfModule mod_deflate.c>
    # Tout comprimer
    AddOutputFilterByType DEFLATE text/html text/plain text/xml text/css
    AddOutputFilterByType DEFLATE application/xml application/xhtml+xml
    AddOutputFilterByType DEFLATE application/rss+xml application/javascript
    AddOutputFilterByType DEFLATE application/x-javascript application/json
    
    # Navigateurs anciens (bugués avec compression)
    BrowserMatch ^Mozilla/4 gzip-only-text/html
    BrowserMatch ^Mozilla/4\.0[678] no-gzip
    BrowserMatch \bMSIE !no-gzip !gzip-only-text/html
    
    # Proxies
    Header append Vary User-Agent
</IfModule>


# === PAGES D'ERREUR PERSONNALISÉES ===

# Par défaut, Apache affiche pages d'erreur moches
# Personnalisez pour meilleure UX !

ErrorDocument 404 /404.html
# Si page pas trouvée (404) -> Affiche /404.html
# Créez un joli 404.html dans DocumentRoot

ErrorDocument 403 /403.html
# Accès interdit (403) -> Page personnalisée

ErrorDocument 500 /500.html
# Erreur serveur (500) -> Page personnalisée

ErrorDocument 503 /maintenance.html
# Service indisponible (503) -> Page maintenance

# Ou URL complète:
ErrorDocument 404 https://monsite.com/404
ErrorDocument 500 https://monsite.com/erreur

# Ou message direct:
ErrorDocument 404 "Oups ! Page introuvable."

# Codes d'erreur courants:
# 400 = Bad Request
# 401 = Unauthorized (pas authentifié)
# 403 = Forbidden (pas autorisé)
# 404 = Not Found (page introuvable)
# 500 = Internal Server Error
# 502 = Bad Gateway
# 503 = Service Unavailable


# === SÉCURITÉ ===

# --- Désactiver listage des répertoires ---
Options -Indexes
# Si pas d'index.html, affiche erreur 403
# Au lieu de lister tous les fichiers (faille sécurité!)

# Avant (DANGEREUX):
# http://monsite.com/images/
# -> Liste: logo.png, photo1.jpg, photo2.jpg, secret-doc.pdf
#
# Après (SÉCURISÉ):
# http://monsite.com/images/
# -> Erreur 403 Forbidden


# --- Bloquer accès fichiers sensibles ---

# Bloquer .htaccess lui-même
<Files ".htaccess">
    Require all denied
</Files>
# Empêche téléchargement de .htaccess

# Bloquer tous fichiers cachés (commençant par .)
<FilesMatch "^\.">
    Require all denied
</FilesMatch>
# Bloque: .htaccess, .env, .git, .htpasswd, etc.

# Bloquer fichiers de backup
<FilesMatch "\.(bak|old|backup|sql|log|txt)$">
    Require all denied
</FilesMatch>
# Bloque: config.php.bak, database.sql, debug.log, etc.

# Bloquer fichiers de configuration
<FilesMatch "(^#.*#|\.(conf|config|ini)|~)$">
    Require all denied
</FilesMatch>

# Bloquer dossier .git (très important!)
<DirectoryMatch "\.git">
    Require all denied
</DirectoryMatch>


# --- Headers de sécurité HTTP ---

# Protection XSS (Cross-Site Scripting)
Header set X-XSS-Protection "1; mode=block"
# 1 = Active la protection
# mode=block = Bloque la page si attaque détectée

# Prévention Clickjacking
Header always set X-Frame-Options "SAMEORIGIN"
# SAMEORIGIN = Page peut être dans iframe seulement si même domaine
# DENY = Jamais dans iframe
# ALLOW-FROM https://example.com = Seulement ce domaine

# Désactiver sniffing MIME
Header set X-Content-Type-Options "nosniff"
# Empêche navigateur de "deviner" type de fichier
# Force respect du Content-Type déclaré

# Content Security Policy (CSP)
Header set Content-Security-Policy "default-src 'self'"
# default-src 'self' = Charger ressources seulement depuis même domaine
# Empêche injection scripts malveillants
#
# Plus permissif:
# Header set Content-Security-Policy "default-src 'self' 'unsafe-inline' 'unsafe-eval' https:; img-src 'self' https: data:; font-src 'self' https: data:"

# HSTS - Force HTTPS (SEULEMENT si HTTPS fonctionne!)
Header always set Strict-Transport-Security "max-age=31536000; includeSubDomains; preload"
# max-age=31536000 = 1 an
# includeSubDomains = Applique aussi aux sous-domaines
# preload = Peut être ajouté à liste HSTS des navigateurs
#
# [ATTENTION] ATTENTION: Ne mettez ça QUE si:
# 1. HTTPS fonctionne parfaitement
# 2. Vous êtes sûr de garder HTTPS (pas de retour HTTP possible!)
# 3. Tous sous-domaines sont en HTTPS

# Referrer Policy
Header set Referrer-Policy "strict-origin-when-cross-origin"
# Contrôle quand envoyer header Referer
# strict-origin-when-cross-origin = Envoie origine seulement cross-origin

# Permissions Policy (anciennement Feature Policy)
Header set Permissions-Policy "geolocation=(), microphone=(), camera=()"
# Désactive accès géolocalisation, micro, caméra
# () = Personne ne peut utiliser


# --- Limiter taille upload ---
LimitRequestBody 10485760
# 10485760 bytes = 10 MB
# Empêche upload fichiers trop gros (DoS)
# 
# Calcul:
# 1 MB = 1024 KB = 1024 × 1024 bytes = 1048576 bytes
# 10 MB = 10 × 1048576 = 10485760 bytes

# Pour 100 MB:
# LimitRequestBody 104857600


# --- Protection Hotlinking (vol de bande passante) ---

# Hotlinking = Autre site utilise vos images
# Exemple: forum.example.com affiche vos images
# Résultat: Vous payez la bande passante !

RewriteEngine On
RewriteCond %{HTTP_REFERER} !^$
# Pas de referer vide (accès direct OK)

RewriteCond %{HTTP_REFERER} !^https?://(www\.)?monsite\.com [NC]
# Referer n'est PAS monsite.com
# [NC] = No Case (insensible casse)

RewriteRule \.(jpg|jpeg|png|gif|webp|svg)$ - [F,L]
# Si image et referer externe -> Forbidden
# [F,L] = Forbidden, Last

# Ou remplacer par image "voleur":
# RewriteRule \.(jpg|jpeg|png|gif)$ /images/hotlink.jpg [R,L]


# --- Désactiver signature Apache ---
# Par défaut Apache révèle sa version
# Exemple: "Apache/2.4.52 (Ubuntu)"
# Donnez moins d'infos aux attaquants !

# À mettre dans apache2.conf ou httpd.conf (pas .htaccess):
ServerTokens Prod
# Prod = Affiche seulement "Apache"
# Full = Affiche version + OS + modules (MAUVAIS)

ServerSignature Off
# Off = N'affiche pas signature sur pages erreur


# === EXEMPLE COMPLET .HTACCESS PRODUCTION ===

# Fichier .htaccess optimal pour site en production
# Copier/adapter selon vos besoins

# === REDIRECTIONS ===
RewriteEngine On

# Force HTTPS
RewriteCond %{HTTPS} off
RewriteRule ^(.*)$ https://%{HTTP_HOST}/$1 [R=301,L]

# Force WWW (ou sans WWW selon préférence)
RewriteCond %{HTTP_HOST} !^www\.
RewriteRule ^(.*)$ https://www.%{HTTP_HOST}/$1 [R=301,L]

# === SÉCURITÉ ===

# Désactiver listage
Options -Indexes

# Bloquer fichiers sensibles
<FilesMatch "^\.">
    Require all denied
</FilesMatch>
<FilesMatch "\.(bak|old|backup|sql|log)$">
    Require all denied
</FilesMatch>

# Headers de sécurité
Header set X-XSS-Protection "1; mode=block"
Header always set X-Frame-Options "SAMEORIGIN"
Header set X-Content-Type-Options "nosniff"
Header set Content-Security-Policy "default-src 'self' 'unsafe-inline' 'unsafe-eval' https:; img-src 'self' https: data:"
Header set Referrer-Policy "strict-origin-when-cross-origin"

# HSTS (si HTTPS)
Header always set Strict-Transport-Security "max-age=31536000; includeSubDomains"

# === PERFORMANCE ===

# Compression GZIP
<IfModule mod_deflate.c>
    AddOutputFilterByType DEFLATE text/html text/css text/javascript
    AddOutputFilterByType DEFLATE application/javascript application/json
    AddOutputFilterByType DEFLATE application/xml text/xml
</IfModule>

# Cache navigateur
<IfModule mod_expires.c>
    ExpiresActive On
    ExpiresByType image/jpg "access plus 1 year"
    ExpiresByType image/jpeg "access plus 1 year"
    ExpiresByType image/png "access plus 1 year"
    ExpiresByType image/gif "access plus 1 year"
    ExpiresByType image/webp "access plus 1 year"
    ExpiresByType image/svg+xml "access plus 1 year"
    ExpiresByType text/css "access plus 1 month"
    ExpiresByType application/javascript "access plus 1 month"
    ExpiresByType text/html "access plus 1 hour"
</IfModule>

# === PAGES D'ERREUR ===
ErrorDocument 404 /404.html
ErrorDocument 403 /403.html
ErrorDocument 500 /500.html

# FIN du .htaccess


[OK] CRÉATION UTILISATEURS - FICHIER .HTPASSWD

# === COMPRENDRE .HTPASSWD ===

# .htpasswd = Fichier contenant utilisateurs et mots de passe
# Format: username:mot_de_passe_chiffré
# Utilisé pour authentification HTTP Basic

# IMPORTANT:
# [OK] Placer HORS DocumentRoot (sécurité!)
# [OK] Mots de passe sont chiffrés (hash)
# [OK] Un utilisateur par ligne

# Bon emplacement:
# /var/www/.htpasswd [OK]
# /etc/apache2/.htpasswd [OK]
#
# Mauvais emplacement:
# /var/www/monsite/public_html/.htpasswd [X] (accessible web!)


# === CRÉER FICHIER ET PREMIER UTILISATEUR ===

# Commande htpasswd
# -c = Create (créer nouveau fichier)
# [ATTENTION] -c écrase fichier existant !

sudo htpasswd -c /var/www/.htpasswd john
# Prompt:
# New password: ****
# Re-type new password: ****
# Adding password for user john

# Fichier créé avec:
# john:$apr1$abc123$xyz...
# Le mot de passe est chiffré (hash)


# === AJOUTER UTILISATEUR SUPPLÉMENTAIRE ===

# SANS -c cette fois ! (sinon écrase fichier)
sudo htpasswd /var/www/.htpasswd marie
# Prompt pour mot de passe

sudo htpasswd /var/www/.htpasswd admin
sudo htpasswd /var/www/.htpasswd client1


# === SUPPRIMER UTILISATEUR ===

sudo htpasswd -D /var/www/.htpasswd john
# -D = Delete
# Supprime l'utilisateur john


# === VÉRIFIER CONTENU ===

cat /var/www/.htpasswd
# Affiche:
# john:$apr1$abc123$xyz...
# marie:$apr1$def456$uvw...
# admin:$apr1$ghi789$rst...

# Le hash change à chaque fois même pour même mot de passe
# C'est normal (salt aléatoire)


# === PERMISSIONS FICHIER ===

# Permissions correctes:
sudo chmod 644 /var/www/.htpasswd
# 644 = Propriétaire: read+write, Autres: read only

# Propriétaire correct:
sudo chown www-data:www-data /var/www/.htpasswd    # Ubuntu
sudo chown apache:apache /var/www/.htpasswd        # CentOS

# Ou garder root:
sudo chown root:www-data /var/www/.htpasswd
sudo chmod 640 /var/www/.htpasswd
# 640 = Owner: read+write, Group: read, Others: nothing


# === ALGORITHMES DE CHIFFREMENT ===

# MD5 (défaut, compatible partout)
htpasswd -c -m /var/www/.htpasswd user
# -m = MD5
# Compatible tous systèmes
# Sécurité moyenne

# bcrypt (recommandé, très sécurisé)
htpasswd -c -B /var/www/.htpasswd user
# -B = bcrypt
# Très sécurisé (lent = difficile à brute-force)
# Recommandé pour production

# SHA (ancien, moins sécurisé)
htpasswd -c -s /var/www/.htpasswd user
# -s = SHA
# Obsolète, éviter

# Plaintext (NON RECOMMANDÉ!)
htpasswd -c -p /var/www/.htpasswd user
# -p = Plaintext
# Mot de passe en clair !
# JAMAIS en production
# Seulement pour tests locaux


# === UTILISER DANS .HTACCESS ===

# Créer .htaccess dans répertoire à protéger
nano /var/www/monsite/public_html/.htaccess

# Ajouter:
AuthType Basic
AuthName "Zone protégée - Connexion requise"
AuthUserFile /var/www/.htpasswd
Require valid-user

# Tester:
# 1. Aller sur http://monsite.com
# 2. Popup de connexion apparaît
# 3. Entrer username et password
# 4. Si OK: Accès au site
# 5. Si KO: Erreur 401 Unauthorized


# === EXEMPLE COMPLET: PANEL ADMIN ===

# Scénario: Protéger /admin/ par mot de passe

# 1. Créer fichier .htpasswd
sudo htpasswd -c -B /var/www/.htpasswd admin
# Mot de passe: [votre_mot_de_passe_fort]

# 2. Créer .htaccess dans /admin/
sudo nano /var/www/monsite/public_html/admin/.htaccess

# 3. Contenu:
AuthType Basic
AuthName "Administration - Accès restreint"
AuthUserFile /var/www/.htpasswd
Require valid-user

# 4. Permissions
sudo chmod 644 /var/www/.htpasswd
sudo chown www-data:www-data /var/www/.htpasswd

# 5. Tester
# http://monsite.com/admin/
# -> Demande login/password


# === COMBINER AUTHENTIFICATION + IP ===

# Seulement certains IPs + Authentification
AuthType Basic
AuthName "Zone ultra-sécurisée"
AuthUserFile /var/www/.htpasswd
Require valid-user
Require ip 192.168.1.0/24

# Doit satisfaire LES DEUX conditions


# === DÉPANNAGE ===

# Erreur: "Internal Server Error"
# Cause possible: Chemin AuthUserFile incorrect
# Solution: Vérifier chemin absolu
# Bon: /var/www/.htpasswd
# Mauvais: .htpasswd ou ../.htpasswd

# Erreur: "Authentication failure"
# Cause: Mauvais username/password
# Solution: Recréer utilisateur
sudo htpasswd /var/www/.htpasswd username

# Erreur: "Configuration error: .htaccess not allowed"
# Cause: AllowOverride None dans VirtualHost
# Solution: Changer en AllowOverride All

# Popup ne s'affiche pas
# Cause: Mod auth pas activé
# Solution:
sudo a2enmod auth_basic
sudo a2enmod authz_user
sudo systemctl restart apache2


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

# Créer utilisateur (première fois):
sudo htpasswd -c -B /var/www/.htpasswd username

# Ajouter utilisateur (après):
sudo htpasswd -B /var/www/.htpasswd autre_user

# Dans .htaccess:
AuthType Basic
AuthName "Connexion requise"
AuthUserFile /var/www/.htpasswd
Require valid-user

# Tester dans navigateur !
# Popup doit apparaître demandant login/mot de passe

[OK] SSL/TLS CONFIGURATION - SÉCURISER VOTRE SITE EN HTTPS

# === COMPRENDRE SSL/TLS ===

# SSL/TLS = Chiffrement des communications web
# HTTP -> Texte en clair (tout le monde peut lire)
# HTTPS -> Chiffré (sécurisé)

# ANALOGIE: Envoyer une lettre
# HTTP = Carte postale (tout le monde peut lire)
# HTTPS = Lettre dans enveloppe scellée (seulement destinataire)

# Pourquoi HTTPS est OBLIGATOIRE maintenant ?
# [OK] Google pénalise sites HTTP (mauvais référencement)
# [OK] Navigateurs affichent "Non sécurisé" (perte confiance)
# [OK] Protection données utilisateurs (mots de passe, CB)
# [OK] Protection contre Man-in-the-Middle (MITM)
# [OK] HTTP/2 nécessite HTTPS (site plus rapide)

# Composants nécessaires:
# 1. Certificat SSL (.crt ou .pem) = Identité du site
# 2. Clé privée (.key) = Clé de chiffrement (SECRET!)
# 3. Chaîne de certificats (.ca-bundle) = Certificats intermédiaires

# Types de certificats:
# - Let's Encrypt: GRATUIT, automatisé, renouvelable (90 jours)
# - Commercial: Payant, support, garantie (Digicert, Comodo, etc.)
# - Auto-signé: Gratuit, SEULEMENT développement (navigateur alerte)


# === INSTALLATION MODULES SSL ===

# Activer mod_ssl
sudo a2enmod ssl
# Charge le module SSL principal
# Permet à Apache de gérer HTTPS

sudo a2enmod socache_shmcb
# Cache partagé pour sessions SSL
# Améliore ÉNORMÉMENT les performances HTTPS
# Sans ça, chaque requête refait handshake complet (lent!)

# Redémarrer Apache
sudo systemctl restart apache2    # Ubuntu/Debian
sudo systemctl restart httpd      # CentOS

# Vérifier que modules sont chargés
sudo apachectl -M | grep ssl
# Sortie attendue:
# socache_shmcb_module (shared)
# ssl_module (shared)


# === MÉTHODE 1: LET'S ENCRYPT (RECOMMANDÉ - GRATUIT) ===

# Let's Encrypt = Autorité de certification gratuite
# Certificats valides 90 jours (renouvellement automatique)
# Reconnus par TOUS les navigateurs
# PARFAIT pour production !

# Qu'est-ce que Certbot ?
# Certbot = Outil officiel Let's Encrypt
# Fait TOUT automatiquement:
# - Génère clé privée
# - Demande certificat à Let's Encrypt
# - Configure Apache
# - Programme renouvellement automatique


# --- INSTALLATION CERTBOT ---

# Ubuntu/Debian
sudo apt update
sudo apt install certbot python3-certbot-apache
# certbot: L'outil principal
# python3-certbot-apache: Plugin Apache (config automatique)

# CentOS/RHEL 8+
sudo dnf install epel-release
sudo dnf install certbot python3-certbot-apache

# Vérifier installation
certbot --version
# Sortie: certbot 2.x.x


# --- OBTENIR CERTIFICAT (Configuration automatique) ---

# Certbot configure TOUT automatiquement !
sudo certbot --apache -d example.com -d www.example.com

# Explications des options:
# --apache: Utilise plugin Apache (config auto)
# -d example.com: Domaine principal
# -d www.example.com: Domaine additionnel (www)
# Vous pouvez ajouter plusieurs -d pour sous-domaines

# Exemples avec sous-domaines:
sudo certbot --apache -d example.com -d www.example.com -d blog.example.com -d api.example.com

# Questions interactives posées:
# 1. Email address: votre@email.com
#    (Pour notifications expiration, sécurité)
#
# 2. Terms of Service: (A)gree
#    Accepter conditions
#
# 3. Share email with EFF: (Y)es or (N)o
#    Optionnel, à vous de choisir
#
# 4. Redirect HTTP to HTTPS?
#    1: No redirect (HTTP et HTTPS marchent)
#    2: Redirect (Force HTTPS) <- RECOMMANDÉ
#    Choisir 2 !

# Ce que Certbot fait automatiquement:
# [OK] Vérifie que domaines pointent vers votre serveur
# [OK] Crée challenge pour prouver propriété domaine
# [OK] Génère clé privée
# [OK] Obtient certificat de Let's Encrypt
# [OK] Installe certificat dans Apache
# [OK] Modifie VirtualHost pour HTTPS
# [OK] Configure redirection HTTP -> HTTPS
# [OK] Configure SSL moderne (TLS 1.2+)
# [OK] Active HSTS (optionnel)
# [OK] Programme renouvellement automatique

# Fichiers créés:
# /etc/letsencrypt/live/example.com/
# ├── fullchain.pem    -> Certificat complet (cert + chaîne)
# ├── privkey.pem      -> Clé privée (SECRET!)
# ├── cert.pem         -> Certificat seul
# └── chain.pem        -> Chaîne de certificats


# --- OBTENIR CERTIFICAT (Sans configuration automatique) ---

# Si vous voulez configurer manuellement Apache:
sudo certbot certonly --apache -d example.com -d www.example.com

# certonly: Obtient certificat SANS modifier Apache
# Vous configurez VirtualHost vous-même (voir section ci-dessous)

# Ou avec webroot (si Apache déjà configuré):
sudo certbot certonly --webroot -w /var/www/example.com/public_html -d example.com -d www.example.com
# --webroot: Méthode de vérification via fichier
# -w: Chemin DocumentRoot
# Let's Encrypt crée fichier dans .well-known/acme-challenge/


# --- RENOUVELER CERTIFICATS ---

# Les certificats Let's Encrypt expirent après 90 jours
# Certbot configure renouvellement AUTOMATIQUE

# Test de renouvellement (sans vraiment renouveler)
sudo certbot renew --dry-run
# --dry-run: Simulation, ne renouvelle pas vraiment
# Vérifie que processus fonctionne
# À faire APRÈS obtention certificat pour tester

# Sortie si OK:
# Congratulations, all simulated renewals succeeded:
#   /etc/letsencrypt/live/example.com/fullchain.pem (success)

# Renouveler manuellement (si besoin)
sudo certbot renew
# Renouvelle tous certificats qui expirent dans < 30 jours
# Apache est rechargé automatiquement

# Forcer renouvellement même si pas encore expiré
sudo certbot renew --force-renewal


# --- RENOUVELLEMENT AUTOMATIQUE ---

# Certbot installe un timer systemd automatiquement

# Vérifier le timer
sudo systemctl status certbot.timer
# Sortie:
# [BLACK_CIRCLE] certbot.timer - Run certbot twice daily
#    Loaded: loaded (/lib/systemd/system/certbot.timer; enabled)
#    Active: active (waiting)
#    Trigger: Next run at 2024-01-15 12:00:00

# Le timer exécute:
# - 2 fois par jour (sécurité)
# - Renouvelle si < 30 jours avant expiration
# - Recharge Apache automatiquement

# Activer le timer (si pas déjà fait)
sudo systemctl enable certbot.timer
sudo systemctl start certbot.timer

# Voir les logs de renouvellement
sudo journalctl -u certbot.timer
sudo journalctl -u certbot.service

# Fichier de logs détaillés
cat /var/log/letsencrypt/letsencrypt.log


# --- SUPPRIMER CERTIFICAT ---

# Si vous voulez supprimer un certificat
sudo certbot delete --cert-name example.com

# Lister tous vos certificats
sudo certbot certificates
# Affiche:
# Certificate Name: example.com
#   Domains: example.com www.example.com
#   Expiry Date: 2024-04-15 10:30:00
#   Certificate Path: /etc/letsencrypt/live/example.com/fullchain.pem
#   Private Key Path: /etc/letsencrypt/live/example.com/privkey.pem


# === MÉTHODE 2: CERTIFICAT AUTO-SIGNÉ (DÉVELOPPEMENT UNIQUEMENT) ===

# Certificat auto-signé = Vous êtes votre propre autorité
# GRATUIT mais navigateur affiche alerte sécurité
# [ATTENTION] JAMAIS en production !
# [OK] OK pour développement local

# Pourquoi navigateur alerte ?
# Le certificat n'est pas signé par autorité reconnue
# Navigateur ne peut pas vérifier authenticité
# Utilisateur voit: "Votre connexion n'est pas privée"


# --- CRÉER CERTIFICAT AUTO-SIGNÉ ---

# Créer certificat + clé privée en une commande
sudo openssl req -x509 -nodes -days 365 -newkey rsa:2048 \
    -keyout /etc/ssl/private/apache-selfsigned.key \
    -out /etc/ssl/certs/apache-selfsigned.crt

# Explication commande:
# openssl req: Créer certificat
# -x509: Format certificat auto-signé
# -nodes: Pas de passphrase (pas de mot de passe sur clé)
# -days 365: Valable 365 jours (1 an)
# -newkey rsa:2048: Nouvelle clé RSA 2048 bits
# -keyout: Où sauvegarder clé privée
# -out: Où sauvegarder certificat

# Questions interactives:
# Country Name (2 letter code) [AU]: FR
# State or Province Name [Some-State]: Ile-de-France
# Locality Name (eg, city) []: Paris
# Organization Name [Internet Widgits Pty Ltd]: MonEntreprise
# Organizational Unit Name []: IT
# Common Name (e.g. server FQDN) []: example.com     <- IMPORTANT!
# Email Address []: admin@example.com

# Common Name DOIT correspondre à votre domaine !
# Si localhost: Common Name = localhost
# Si example.com: Common Name = example.com


# Version non-interactive (pour scripts):
sudo openssl req -x509 -nodes -days 365 -newkey rsa:2048 \
    -keyout /etc/ssl/private/apache-selfsigned.key \
    -out /etc/ssl/certs/apache-selfsigned.crt \
    -subj "/C=FR/ST=IDF/L=Paris/O=MonEntreprise/OU=IT/CN=example.com"

# -subj: Toutes infos en une ligne
# C=Country, ST=State, L=Locality, O=Organization, OU=Unit, CN=CommonName


# --- CRÉER PARAMÈTRES DIFFIE-HELLMAN (Sécurité++) ---

# DH params = Renforce sécurité échange de clés
# Optionnel mais recommandé

sudo openssl dhparam -out /etc/ssl/certs/dhparam.pem 2048
# Attention: Prend plusieurs minutes !
# 2048 = Taille en bits (bon compromis sécurité/performance)
# 4096 = Plus sécurisé mais plus lent

# Pour 4096 bits (très lent, ~20 minutes):
# sudo openssl dhparam -out /etc/ssl/certs/dhparam.pem 4096


# --- PERMISSIONS FICHIERS SSL ---

# TRÈS IMPORTANT pour sécurité !

# Clé privée: STRICTEMENT privée !
sudo chmod 600 /etc/ssl/private/apache-selfsigned.key
sudo chown root:root /etc/ssl/private/apache-selfsigned.key
# 600 = Seulement root peut lire/écrire
# PERSONNE d'autre ne doit accéder !

# Certificat: Peut être lu (pas sensible)
sudo chmod 644 /etc/ssl/certs/apache-selfsigned.crt
# 644 = Tout le monde peut lire

# DH params: Peut être lu
sudo chmod 644 /etc/ssl/certs/dhparam.pem


# === CONFIGURATION VIRTUALHOST SSL ===

# Créer VirtualHost HTTPS (port 443)
sudo nano /etc/apache2/sites-available/example-ssl.conf

<VirtualHost *:443>
    # Port 443 = Port HTTPS standard
    
    ServerName example.com
    ServerAlias www.example.com
    ServerAdmin admin@example.com
    
    DocumentRoot /var/www/example.com/public_html
    
    
    # === ACTIVATION SSL ===
    
    SSLEngine on
    # Active SSL pour ce VirtualHost
    # Sans ça, pas de HTTPS !
    
    
    # === CERTIFICATS (Certificat auto-signé) ===
    
    SSLCertificateFile /etc/ssl/certs/apache-selfsigned.crt
    # Chemin vers certificat
    
    SSLCertificateKeyFile /etc/ssl/private/apache-selfsigned.key
    # Chemin vers clé privée
    # [ATTENTION] Protéger ce fichier (chmod 600) !
    
    # Si vous avez DH params:
    # SSLOpenSSLConfCmd DHParameters /etc/ssl/certs/dhparam.pem
    
    
    # === CERTIFICATS (Let's Encrypt) ===
    # Décommentez si vous utilisez Let's Encrypt:
    
    # SSLCertificateFile /etc/letsencrypt/live/example.com/fullchain.pem
    # SSLCertificateKeyFile /etc/letsencrypt/live/example.com/privkey.pem
    
    # fullchain.pem = Certificat + Chaîne (tout-en-un)
    # privkey.pem = Clé privée
    
    
    # === PROTOCOLES SSL/TLS (Sécurité moderne 2024) ===
    
    SSLProtocol all -SSLv3 -TLSv1 -TLSv1.1
    # Protocoles autorisés:
    # all = Tous les protocoles
    # -SSLv3 = DÉSACTIVE SSLv3 (vulnérable POODLE)
    # -TLSv1 = DÉSACTIVE TLS 1.0 (obsolète)
    # -TLSv1.1 = DÉSACTIVE TLS 1.1 (obsolète)
    #
    # Résultat: Seulement TLS 1.2 et TLS 1.3
    # C'est la config recommandée 2024 !
    #
    # Compatibilité:
    # - TLS 1.2: Tous navigateurs modernes (IE 11+, Chrome, Firefox, Safari)
    # - TLS 1.3: Navigateurs récents (Chrome 70+, Firefox 63+, Safari 12.1+)
    
    
    # === SUITES DE CHIFFREMENT (Ciphers) ===
    
    SSLCipherSuite 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
    # Liste des algorithmes de chiffrement autorisés
    #
    # Explication (simplifié):
    # - ECDHE: Échange de clés sécurisé
    # - AES128/AES256: Algorithme de chiffrement
    # - GCM: Mode d'opération (moderne)
    # - SHA256/SHA384: Fonction de hachage
    #
    # Cette liste = Compromis sécurité/performance/compatibilité
    # Note: Ordre = préférence
    
    SSLHonorCipherOrder off
    # off (Apache 2.4.17+): Client choisit (moderne)
    # on (ancien): Serveur force son choix
    #
    # TLS 1.3 ignore ce paramètre (bon!)
    
    
    # === OPTIMISATIONS PERFORMANCE ===
    
    SSLSessionCache shmcb:${APACHE_RUN_DIR}/ssl_scache(512000)
    # Cache les sessions SSL
    # Évite handshake complet à chaque requête
    # 512000 = 512 KB cache
    #
    # Sans cache:
    # Requête 1: Handshake complet (~100ms)
    # Requête 2: Handshake complet (~100ms)
    # Requête 3: Handshake complet (~100ms)
    #
    # Avec cache:
    # Requête 1: Handshake complet (~100ms)
    # Requête 2-N: Session réutilisée (~0ms) <- ÉNORME gain!
    
    SSLSessionCacheTimeout 300
    # Durée cache session: 300 secondes = 5 minutes
    # Après 5 min, nouveau handshake nécessaire
    
    
    # === OCSP STAPLING (Vérification révocation) ===
    
    SSLUseStapling On
    # Active OCSP Stapling
    # Vérifie que certificat n'est pas révoqué
    # Stapling = Serveur fait vérification au lieu du client
    # Plus rapide + Plus de confidentialité
    
    SSLStaplingCache "shmcb:logs/ssl_stapling(32768)"
    # Cache pour réponses OCSP
    # 32768 = 32 KB cache
    
    
    # === HEADERS DE SÉCURITÉ ===
    
    Header always set Strict-Transport-Security "max-age=31536000; includeSubDomains; preload"
    # HSTS - Force HTTPS pendant 1 an
    # max-age=31536000 = 31536000 secondes = 365 jours = 1 an
    # includeSubDomains = Applique aussi aux sous-domaines
    # preload = Eligible pour liste HSTS navigateurs
    #
    # [ATTENTION] ATTENTION CRITIQUE:
    # Une fois activé, navigateur SE SOUVIENT
    # Impossible revenir HTTP pendant max-age !
    # N'activez QUE si:
    # 1. HTTPS fonctionne parfaitement
    # 2. Vous êtes CERTAIN de garder HTTPS
    # 3. Tous sous-domaines sont en HTTPS
    #
    # Pour débuter, utilisez max-age plus court:
    # Header always set Strict-Transport-Security "max-age=300"
    # 300 secondes = 5 minutes (pour tester)
    
    Header always set X-Frame-Options "SAMEORIGIN"
    # Protection clickjacking
    
    Header always set X-Content-Type-Options "nosniff"
    # Empêche sniffing MIME
    
    Header always set X-XSS-Protection "1; mode=block"
    # Protection XSS (ancien navigateurs)
    
    
    # === VARIABLES SSL (optionnel) ===
    
    SSLOptions +StdEnvVars
    # Exporte variables SSL vers environnement
    # Permet à PHP/scripts d'accéder infos SSL
    # Variables disponibles:
    # - SSL_PROTOCOL (TLSv1.2, TLSv1.3)
    # - SSL_CIPHER (algorithme utilisé)
    # - SSL_CLIENT_S_DN (DN du certificat client)
    # etc.
    
    
    # === RÉPERTOIRE ===
    
    <Directory /var/www/example.com/public_html>
        Options -Indexes +FollowSymLinks
        AllowOverride All
        Require all granted
    </Directory>
    
    
    # === LOGS ===
    
    ErrorLog ${APACHE_LOG_DIR}/example-ssl-error.log
    CustomLog ${APACHE_LOG_DIR}/example-ssl-access.log combined
</VirtualHost>

# Sauvegarder le fichier

# Activer le site
sudo a2ensite example-ssl.conf

# Tester config
sudo apachectl configtest

# Recharger Apache
sudo systemctl reload apache2


# === REDIRECTION HTTP -> HTTPS ===

# Forcer tous visiteurs à utiliser HTTPS
# Modifier VirtualHost HTTP (port 80)

sudo nano /etc/apache2/sites-available/example.conf

<VirtualHost *:80>
    ServerName example.com
    ServerAlias www.example.com
    
    # MÉTHODE 1: Redirect (Simple et efficace)
    Redirect permanent / https://example.com/
    # permanent = 301 (redirection permanente)
    # / = Toutes les pages
    # Google et navigateurs comprennent migration HTTPS
    
    # Exemples:
    # http://example.com/ -> https://example.com/
    # http://example.com/contact -> https://example.com/contact
    # http://example.com/blog/article?id=123 -> https://example.com/blog/article?id=123
</VirtualHost>

# OU

<VirtualHost *:80>
    ServerName example.com
    ServerAlias www.example.com
    
    # MÉTHODE 2: RewriteEngine (Plus flexible)
    RewriteEngine On
    RewriteCond %{HTTPS} off
    RewriteRule ^(.*)$ https://%{HTTP_HOST}$1 [R=301,L]
    # Si pas HTTPS, redirige vers HTTPS avec même URL
</VirtualHost>

# Recharger
sudo systemctl reload apache2


# === CONFIGURATION SSL GLOBALE (Performance++) ===

# Pour améliorer performances SSL sur TOUS vos sites
# Configuration une seule fois

# Ubuntu/Debian
sudo nano /etc/apache2/mods-available/ssl.conf

# CentOS
sudo nano /etc/httpd/conf.d/ssl.conf

# Ajouter/modifier:

# Cache sessions SSL (partagé entre tous VirtualHosts)
SSLSessionCache shmcb:/var/cache/apache2/ssl_scache(512000)
SSLSessionCacheTimeout 300

# OCSP Stapling cache (partagé)
SSLStaplingCache shmcb:/var/cache/apache2/ssl_stapling(128000)

# Créer dossiers cache si n'existent pas
sudo mkdir -p /var/cache/apache2
sudo chown www-data:www-data /var/cache/apache2    # Ubuntu
sudo chown apache:apache /var/cache/apache2        # CentOS


# === TESTER CONFIGURATION SSL ===

# Test local (ligne de commande)
openssl s_client -connect localhost:443
# Affiche infos connexion SSL:
# - Protocole utilisé (TLSv1.2, TLSv1.3)
# - Cipher utilisé
# - Certificat
# - Chaîne de certificats

# Taper GET / HTTP/1.1 puis Entrée deux fois
# Pour voir réponse HTTP

# Test protocole spécifique
openssl s_client -connect example.com:443 -tls1_2
# Force TLS 1.2

openssl s_client -connect example.com:443 -tls1_3
# Force TLS 1.3

# Tester protocole obsolète (doit échouer!)
openssl s_client -connect example.com:443 -tls1
# Si erreur "no protocols available" = Bon ! TLS 1.0 désactivé


# Test avec curl
curl -v https://example.com
# -v = verbose (affiche détails SSL)

curl --tlsv1.2 https://example.com
# Force TLS 1.2

curl --tlsv1.3 https://example.com
# Force TLS 1.3


# Test en ligne (le meilleur!)
# https://www.ssllabs.com/ssltest/
# 
# Analyse COMPLÈTE de votre config SSL:
# - Note A+ à F
# - Protocoles supportés
# - Vulnérabilités
# - Compatibilité navigateurs
# - Recommandations
#
# Visez note A ou A+ !

# Autre test en ligne:
# https://www.immuniweb.com/ssl/


# === DÉPANNAGE SSL ===

# Erreur: "SSL received a record that exceeded the maximum permissible length"
# Cause: Port 443 pas ouvert ou Apache écoute pas
# Solution:
sudo ufw allow 443/tcp
sudo netstat -tlnp | grep :443

# Erreur: "ERR_SSL_PROTOCOL_ERROR"
# Cause: Config SSL invalide
# Solution:
sudo apachectl configtest
# Corriger erreurs

# Erreur: "NET::ERR_CERT_AUTHORITY_INVALID" (certificat auto-signé)
# Normal pour certificat auto-signé
# Navigateur: Cliquer "Avancé" -> "Accepter le risque"
# Chrome: Taper "thisisunsafe" sur page erreur

# Erreur: "Your connection is not private"
# Causes possibles:
# 1. Certificat expiré
# 2. Common Name incorrect
# 3. Certificat auto-signé (normal développement)
# Solution:
sudo certbot renew    # Si Let's Encrypt
# Ou recréer certificat auto-signé avec bon CN

# Vérifier expiration certificat
openssl x509 -in /etc/ssl/certs/apache-selfsigned.crt -noout -dates
# Affiche:
# notBefore=Jan 15 10:00:00 2024 GMT
# notAfter=Jan 15 10:00:00 2025 GMT

# Let's Encrypt:
sudo certbot certificates


# === RÉSUMÉ DÉBUTANT - HTTPS AVEC LET'S ENCRYPT ===

# 1. Installer Certbot
sudo apt install certbot python3-certbot-apache

# 2. Obtenir certificat (configuration automatique)
sudo certbot --apache -d example.com -d www.example.com

# 3. Choisir "2: Redirect" pour forcer HTTPS

# 4. Tester renouvellement automatique
sudo certbot renew --dry-run

# 5. Vérifier site
# https://example.com

# 6. Tester avec SSL Labs
# https://www.ssllabs.com/ssltest/

# C'est tout ! Certbot fait TOUT automatiquement !


# === RÉSUMÉ DÉBUTANT - HTTPS DÉVELOPPEMENT LOCAL ===

# 1. Activer SSL
sudo a2enmod ssl
sudo a2enmod socache_shmcb
sudo systemctl restart apache2

# 2. Créer certificat auto-signé
sudo openssl req -x509 -nodes -days 365 -newkey rsa:2048 \
    -keyout /etc/ssl/private/apache-selfsigned.key \
    -out /etc/ssl/certs/apache-selfsigned.crt

# 3. Créer VirtualHost HTTPS (voir config ci-dessus)

# 4. Activer et recharger
sudo a2ensite example-ssl.conf
sudo apachectl configtest
sudo systemctl reload apache2

# 5. Tester
# https://localhost (accepter alerte navigateur)

[OK] REVERSE PROXY - APACHE DEVANT AUTRES APPLICATIONS

# === COMPRENDRE REVERSE PROXY ===

# Reverse Proxy = Apache fait intermédiaire
# Client -> Apache -> Application Backend -> Apache -> Client

# ANALOGIE: Réceptionniste d'hôtel
# - Client arrive (navigateur web)
# - Réceptionniste accueille (Apache)
# - Réceptionniste transmet au service (app backend)
# - Service répond via réceptionniste
# - Client ne voit que réceptionniste

# Pourquoi utiliser reverse proxy ?
# [OK] SSL/HTTPS géré par Apache (app backend n'a pas besoin)
# [OK] Cache statique (Apache sert images/CSS directement)
# [OK] Load balancing (répartir charge sur plusieurs serveurs)
# [OK] Sécurité (app backend pas exposée directement)
# [OK] Logs centralisés dans Apache
# [OK] Compression gzip par Apache
# [OK] Une seule IP pour plusieurs applications

# Cas d'usage typiques:
# - Application Node.js sur port 3000
# - API Python Flask/Django sur port 8000
# - Application Java sur port 8080
# - Plusieurs microservices
# - Load balancing entre serveurs

# Architecture typique:
# Internet -> Apache:80/443 -> Application:3000 (localhost)
# Application écoute SEULEMENT sur localhost (pas exposée!)


# === ACTIVER MODULES PROXY ===

# Modules nécessaires
sudo a2enmod proxy
# Module proxy de base

sudo a2enmod proxy_http
# Support protocole HTTP
# Pour proxyfier HTTP/HTTPS

sudo a2enmod proxy_fcgi
# Support FastCGI (pour PHP-FPM par exemple)

sudo a2enmod proxy_wstunnel
# Support WebSocket
# Nécessaire pour apps temps réel (chat, etc.)

sudo a2enmod proxy_balancer
# Load balancer (répartir charge)

sudo a2enmod lbmethod_byrequests
# Méthode load balancing: par requête (round-robin)

sudo a2enmod lbmethod_bytraffic
# Méthode load balancing: par trafic (bande passante)

sudo a2enmod lbmethod_bybusyness
# Méthode load balancing: par occupation serveur

# Redémarrer Apache
sudo systemctl restart apache2    # Ubuntu
sudo systemctl restart httpd      # CentOS

# Vérifier modules actifs
sudo apachectl -M | grep proxy


# === PROXY HTTP SIMPLE ===

# Scénario: Application Node.js sur localhost:3000
# On veut: http://example.com -> Application Node.js

sudo nano /etc/apache2/sites-available/nodeapp.conf

<VirtualHost *:80>
    ServerName example.com
    ServerAlias www.example.com
    
    # === CONFIGURATION PROXY ===
    
    ProxyPreserveHost On
    # Garde le nom d'hôte original (example.com)
    # Sans ça, app backend reçoit "localhost:3000"
    # Avec ça, app backend reçoit "example.com"
    # Important pour apps qui génèrent URLs
    
    ProxyPass / http://localhost:3000/
    # ProxyPass = "Redirige vers"
    # / = Toutes les URLs (tout le site)
    # http://localhost:3000/ = Destination
    #
    # Exemples:
    # http://example.com/ -> http://localhost:3000/
    # http://example.com/api/users -> http://localhost:3000/api/users
    # http://example.com/contact -> http://localhost:3000/contact
    
    ProxyPassReverse / http://localhost:3000/
    # ProxyPassReverse = Ajuste headers de réponse
    # Nécessaire pour redirections correctes
    # Si app backend fait redirect vers http://localhost:3000/login
    # Apache transforme en http://example.com/login
    # Sans ça, utilisateur verrait localhost dans URL (cassé!)
    
    # === LOGS ===
    ErrorLog ${APACHE_LOG_DIR}/nodeapp-error.log
    CustomLog ${APACHE_LOG_DIR}/nodeapp-access.log combined
</VirtualHost>

# Activer le site
sudo a2ensite nodeapp.conf
sudo apachectl configtest
sudo systemctl reload apache2

# Votre app Node.js est maintenant accessible sur http://example.com !


# === PROXY AVEC CONFIGURATION AVANCÉE ===

<VirtualHost *:80>
    ServerName app.example.com
    
    # === DÉSACTIVER FORWARD PROXY (Sécurité) ===
    ProxyRequests Off
    # Off = Reverse proxy seulement
    # On = Forward proxy (peut être utilisé comme proxy ouvert!)
    # TOUJOURS mettre Off sauf si vous savez ce que vous faites
    
    ProxyPreserveHost On
    
    # === CONTRÔLE D'ACCÈS ===
    <Proxy *>
        Require all granted
        # Tout le monde peut accéder
        
        # Ou restreindre par IP:
        # Require ip 192.168.1.0/24
    </Proxy>
    
    # === PROXY CONFIGURATION ===
    ProxyPass / http://localhost:3000/
    ProxyPassReverse / http://localhost:3000/
    
    # === TIMEOUTS ===
    ProxyTimeout 300
    # Timeout connexion backend: 300 secondes = 5 minutes
    # Augmentez si app backend lente ou long-polling
    
    # === LOGS ===
    ErrorLog ${APACHE_LOG_DIR}/app-error.log
    CustomLog ${APACHE_LOG_DIR}/app-access.log combined
</VirtualHost>


# === PROXY POUR APPLICATION NODE.JS AVEC WEBSOCKET ===

# WebSocket = Connexion bidirectionnelle temps réel
# Utilisé pour: Chat, notifications live, jeux en ligne

<VirtualHost *:80>
    ServerName chat.example.com
    
    ProxyRequests Off
    ProxyPreserveHost On
    
    # === PROXY HTTP CLASSIQUE ===
    ProxyPass / http://localhost:3000/
    ProxyPassReverse / http://localhost:3000/
    
    # === SUPPORT WEBSOCKET ===
    RewriteEngine on
    
    # Si requête est WebSocket upgrade
    RewriteCond %{HTTP:Upgrade} websocket [NC]
    # %{HTTP:Upgrade} = Header "Upgrade" de la requête
    # websocket = Valeur du header
    # [NC] = No Case (insensible casse)
    
    RewriteCond %{HTTP:Connection} upgrade [NC]
    # Header "Connection: upgrade" doit être présent
    
    RewriteRule ^/?(.*) "ws://localhost:3000/$1" [P,L]
    # Redirige vers WebSocket (ws:// au lieu de http://)
    # $1 = Le chemin capturé
    # [P,L] = Proxy, Last
    #
    # Exemple:
    # ws://chat.example.com/socket.io -> ws://localhost:3000/socket.io
    
    ErrorLog ${APACHE_LOG_DIR}/chat-error.log
    CustomLog ${APACHE_LOG_DIR}/chat-access.log combined
</VirtualHost>

# Applications utilisant WebSocket:
# - Socket.IO (Node.js)
# - SignalR (.NET)
# - Django Channels (Python)
# - Action Cable (Ruby on Rails)


# === PROXY AVEC SSL/HTTPS ===

# Apache gère HTTPS, app backend reste HTTP (simple!)

<VirtualHost *:443>
    ServerName api.example.com
    
    # === CONFIGURATION SSL ===
    SSLEngine On
    SSLCertificateFile /etc/letsencrypt/live/api.example.com/fullchain.pem
    SSLCertificateKeyFile /etc/letsencrypt/live/api.example.com/privkey.pem
    
    SSLProtocol all -SSLv3 -TLSv1 -TLSv1.1
    SSLCipherSuite HIGH:!aNULL:!MD5
    
    # === PROXY VERS BACKEND HTTP ===
    ProxyPreserveHost On
    ProxyPass / http://localhost:8000/
    ProxyPassReverse / http://localhost:8000/
    
    # L'application backend reçoit requêtes déchiffrées
    # Pas besoin de gérer SSL dans l'app!
    # Apache fait tout le travail SSL
    
    # === PASSER HEADERS SSL À L'APP ===
    RequestHeader set X-Forwarded-Proto "https"
    # Dit à l'app que requête originale était HTTPS
    
    RequestHeader set X-Forwarded-SSL "on"
    # Certaines apps vérifient ce header
    
    RequestHeader set X-Forwarded-For "%{REMOTE_ADDR}s"
    # Transmet IP réelle du client
    
    ErrorLog ${APACHE_LOG_DIR}/api-ssl-error.log
    CustomLog ${APACHE_LOG_DIR}/api-ssl-access.log combined
</VirtualHost>

# Redirection HTTP -> HTTPS
<VirtualHost *:80>
    ServerName api.example.com
    Redirect permanent / https://api.example.com/
</VirtualHost>


# === LOAD BALANCER (Répartition de charge) ===

# Scénario: 3 serveurs backend pour gérer charge
# Apache répartit requêtes entre les 3

<Proxy balancer://mycluster>
    # Définir le cluster (groupe de serveurs)
    
    BalancerMember http://192.168.1.10:8080
    # Serveur 1
    
    BalancerMember http://192.168.1.11:8080
    # Serveur 2
    
    BalancerMember http://192.168.1.12:8080
    # Serveur 3
    
    ProxySet lbmethod=byrequests
    # Méthode de répartition:
    # - byrequests: Round-robin (à tour de rôle)
    # - bytraffic: Par quantité de données
    # - bybusyness: Par charge serveur
    
    # Options avancées par serveur:
    # BalancerMember http://192.168.1.10:8080 loadfactor=2
    # loadfactor=2 = Serveur 2x plus puissant, reçoit 2x plus requêtes
    
    # BalancerMember http://192.168.1.11:8080 retry=60
    # retry=60 = Réessayer serveur après 60 secondes si down
</Proxy>

<VirtualHost *:80>
    ServerName example.com
    
    ProxyPreserveHost On
    
    ProxyPass / balancer://mycluster/
    # Redirige vers le cluster (pas serveur unique)
    
    ProxyPassReverse / balancer://mycluster/
    
    # Comment ça marche:
    # Requête 1 -> Serveur 192.168.1.10
    # Requête 2 -> Serveur 192.168.1.11
    # Requête 3 -> Serveur 192.168.1.12
    # Requête 4 -> Serveur 192.168.1.10
    # etc. (à tour de rôle)
    
    ErrorLog ${APACHE_LOG_DIR}/lb-error.log
    CustomLog ${APACHE_LOG_DIR}/lb-access.log combined
</VirtualHost>


# === LOAD BALANCER AVEC STICKY SESSIONS ===

# Sticky Session = Utilisateur reste sur même serveur
# Important si app stocke session en mémoire (non partagée)

<Proxy balancer://mycluster>
    BalancerMember http://192.168.1.10:8080 route=server1
    BalancerMember http://192.168.1.11:8080 route=server2
    BalancerMember http://192.168.1.12:8080 route=server3
    
    ProxySet lbmethod=byrequests
    ProxySet stickysession=BALANCEID
    # stickysession=BALANCEID
    # Utilisateur reste sur même serveur
    # Cookie BALANCEID créé automatiquement
</Proxy>

<VirtualHost *:80>
    ServerName example.com
    
    Header add Set-Cookie "BALANCEID=.%{BALANCER_WORKER_ROUTE}e; path=/" env=BALANCER_ROUTE_CHANGED
    # Crée cookie avec route serveur
    
    ProxyPreserveHost On
    ProxyPass / balancer://mycluster/
    ProxyPassReverse / balancer://mycluster/
</VirtualHost>


# === PROXY POUR SOUS-RÉPERTOIRE ===

# Scénario: Site principal + app dans /app/

<VirtualHost *:80>
    ServerName example.com
    DocumentRoot /var/www/html
    
    # Site principal servi par Apache
    <Directory /var/www/html>
        Options -Indexes +FollowSymLinks
        AllowOverride All
        Require all granted
    </Directory>
    
    # Application Node.js dans /app
    ProxyPass /app http://localhost:3000/
    ProxyPassReverse /app http://localhost:3000/
    
    # API Python dans /api
    ProxyPass /api http://localhost:8000/
    ProxyPassReverse /api http://localhost:8000/
    
    # Résultat:
    # http://example.com/ -> Apache (site statique)
    # http://example.com/about.html -> Apache
    # http://example.com/app/ -> Node.js:3000
    # http://example.com/app/dashboard -> Node.js:3000
    # http://example.com/api/users -> Python:8000
    
    ErrorLog ${APACHE_LOG_DIR}/mixed-error.log
    CustomLog ${APACHE_LOG_DIR}/mixed-access.log combined
</VirtualHost>


# === EXCLURE CHEMINS DU PROXY ===

# Scénario: Proxyfier tout SAUF certains chemins

<VirtualHost *:80>
    ServerName example.com
    DocumentRoot /var/www/html
    
    # NE PAS proxyfier /static et /media
    ProxyPass /static !
    # ! = Exclure (ne pas proxyfier)
    # /static sera servi par Apache directement
    
    ProxyPass /media !
    # /media sera servi par Apache directement
    
    # Proxyfier tout le reste
    ProxyPass / http://localhost:8000/
    ProxyPassReverse / http://localhost:8000/
    
    # Résultat:
    # http://example.com/ -> Python:8000
    # http://example.com/api -> Python:8000
    # http://example.com/static/style.css -> Apache (rapide!)
    # http://example.com/media/image.jpg -> Apache (rapide!)
    
    # Pourquoi faire ça ?
    # - Fichiers statiques servis par Apache = BEAUCOUP plus rapide
    # - App backend libérée (ne sert pas fichiers statiques)
    # - Apache peut cacher, compresser fichiers statiques
    
    <Directory /var/www/html>
        Options -Indexes +FollowSymLinks
        AllowOverride All
        Require all granted
    </Directory>
</VirtualHost>


# === PROXY AVEC HEADERS PERSONNALISÉS ===

<VirtualHost *:80>
    ServerName example.com
    
    ProxyPreserveHost On
    
    # === AJOUTER HEADERS ===
    RequestHeader set X-Forwarded-Proto "http"
    # Protocole original (http ou https)
    
    RequestHeader set X-Forwarded-For "%{REMOTE_ADDR}s"
    # IP réelle du client
    # %{REMOTE_ADDR}s = Variable Apache
    
    RequestHeader set X-Real-IP "%{REMOTE_ADDR}s"
    # Autre façon de passer IP client
    
    RequestHeader set X-Forwarded-Host "%{HTTP_HOST}s"
    # Nom d'hôte original
    
    RequestHeader set X-Custom-Header "Ma valeur"
    # Header personnalisé
    
    # L'application backend peut lire ces headers
    # Exemple Node.js:
    # const clientIP = req.headers['x-real-ip'];
    # const proto = req.headers['x-forwarded-proto'];
    
    ProxyPass / http://localhost:3000/
    ProxyPassReverse / http://localhost:3000/
</VirtualHost>


# === PROXY AVEC CACHE (Performance++) ===

# Apache peut cacher réponses backend

# Activer modules cache
sudo a2enmod cache
sudo a2enmod cache_disk
sudo systemctl restart apache2

<VirtualHost *:80>
    ServerName example.com
    
    ProxyPreserveHost On
    
    # === CONFIGURATION CACHE ===
    CacheEnable disk /
    # Active cache disque pour /
    
    CacheRoot /var/cache/apache2/proxy
    # Où stocker cache sur disque
    
    CacheDirLevels 2
    # Structure répertoires cache
    
    CacheDirLength 1
    # Longueur noms répertoires
    
    CacheMaxFileSize 1000000
    # Taille max fichier: 1 MB
    
    CacheIgnoreHeaders Set-Cookie
    # Ne pas cacher réponses avec Set-Cookie
    
    CacheLastModifiedFactor 0.1
    # Facteur calcul fraîcheur cache
    
    # === PROXY ===
    ProxyPass / http://localhost:3000/
    ProxyPassReverse / http://localhost:3000/
    
    # Résultat:
    # Première requête: Va chercher backend (lent)
    # Requêtes suivantes: Servi depuis cache (rapide!)
</VirtualHost>

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

# Vider cache
sudo rm -rf /var/cache/apache2/proxy/*


# === PROXY AVEC TIMEOUT PERSONNALISÉ ===

<VirtualHost *:80>
    ServerName example.com
    
    ProxyPreserveHost On
    
    # === TIMEOUTS ===
    ProxyTimeout 600
    # Timeout global: 600 secondes = 10 minutes
    # Utile pour long-polling, uploads gros fichiers
    
    ProxyPass / http://localhost:3000/ timeout=600
    # Timeout pour cette route spécifique
    
    ProxyPassReverse / http://localhost:3000/
    
    # Paramètres additionnels ProxyPass:
    # ProxyPass / http://localhost:3000/ retry=0
    # retry=0 = Ne pas réessayer si backend down
    
    # ProxyPass / http://localhost:3000/ keepalive=On
    # keepalive=On = Réutiliser connexions (plus rapide)
</VirtualHost>


# === EXEMPLE COMPLET: DJANGO/PYTHON APP ===

# Application Django typique avec fichiers statiques

<VirtualHost *:443>
    ServerName monapp.com
    ServerAlias www.monapp.com
    
    # === SSL ===
    SSLEngine On
    SSLCertificateFile /etc/letsencrypt/live/monapp.com/fullchain.pem
    SSLCertificateKeyFile /etc/letsencrypt/live/monapp.com/privkey.pem
    SSLProtocol all -SSLv3 -TLSv1 -TLSv1.1
    
    # === FICHIERS STATIQUES (servis par Apache) ===
    Alias /static /var/www/monapp/static
    Alias /media /var/www/monapp/media
    
    <Directory /var/www/monapp/static>
        Require all granted
        # Cache agressif pour fichiers statiques
        ExpiresActive On
        ExpiresDefault "access plus 1 year"
    </Directory>
    
    <Directory /var/www/monapp/media>
        Require all granted
        ExpiresActive On
        ExpiresDefault "access plus 1 month"
    </Directory>
    
    # === PROXY VERS DJANGO (via Gunicorn) ===
    ProxyPreserveHost On
    
    # Ne pas proxyfier /static et /media
    ProxyPass /static !
    ProxyPass /media !
    
    # Proxyfier tout le reste vers Django
    ProxyPass / http://127.0.0.1:8000/
    ProxyPassReverse / http://127.0.0.1:8000/
    
    # Headers pour Django
    RequestHeader set X-Forwarded-Proto "https"
    RequestHeader set X-Forwarded-For "%{REMOTE_ADDR}s"
    
    # === LOGS ===
    ErrorLog ${APACHE_LOG_DIR}/monapp-error.log
    CustomLog ${APACHE_LOG_DIR}/monapp-access.log combined
</VirtualHost>

# Redirection HTTP -> HTTPS
<VirtualHost *:80>
    ServerName monapp.com
    ServerAlias www.monapp.com
    Redirect permanent / https://monapp.com/
</VirtualHost>


# === EXEMPLE COMPLET: MICROSERVICES ===

# Plusieurs applications sur sous-domaines

# Frontend React (servi statiquement)
<VirtualHost *:443>
    ServerName app.example.com
    DocumentRoot /var/www/react-app/build
    
    SSLEngine On
    SSLCertificateFile /etc/letsencrypt/live/app.example.com/fullchain.pem
    SSLCertificateKeyFile /etc/letsencrypt/live/app.example.com/privkey.pem
    
    <Directory /var/www/react-app/build>
        Options -Indexes +FollowSymLinks
        AllowOverride All
        Require all granted
        
        # React Router: Toutes routes vers index.html
        RewriteEngine On
        RewriteCond %{REQUEST_FILENAME} !-f
        RewriteCond %{REQUEST_FILENAME} !-d
        RewriteRule ^ index.html [L]
    </Directory>
</VirtualHost>

# API principale (Node.js)
<VirtualHost *:443>
    ServerName api.example.com
    
    SSLEngine On
    SSLCertificateFile /etc/letsencrypt/live/api.example.com/fullchain.pem
    SSLCertificateKeyFile /etc/letsencrypt/live/api.example.com/privkey.pem
    
    ProxyPreserveHost On
    ProxyPass / http://localhost:3000/
    ProxyPassReverse / http://localhost:3000/
    
    RequestHeader set X-Forwarded-Proto "https"
</VirtualHost>

# Service authentification (Python)
<VirtualHost *:443>
    ServerName auth.example.com
    
    SSLEngine On
    SSLCertificateFile /etc/letsencrypt/live/auth.example.com/fullchain.pem
    SSLCertificateKeyFile /etc/letsencrypt/live/auth.example.com/privkey.pem
    
    ProxyPreserveHost On
    ProxyPass / http://localhost:5000/
    ProxyPassReverse / http://localhost:5000/
    
    RequestHeader set X-Forwarded-Proto "https"
</VirtualHost>

# Service de paiement (Java)
<VirtualHost *:443>
    ServerName payment.example.com
    
    SSLEngine On
    SSLCertificateFile /etc/letsencrypt/live/payment.example.com/fullchain.pem
    SSLCertificateKeyFile /etc/letsencrypt/live/payment.example.com/privkey.pem
    
    ProxyPreserveHost On
    ProxyPass / http://localhost:8080/
    ProxyPassReverse / http://localhost:8080/
    
    RequestHeader set X-Forwarded-Proto "https"
</VirtualHost>


# === DÉPANNAGE PROXY ===

# Erreur: "Service Unavailable" (503)
# Cause: Backend application pas démarrée ou down
# Solution:
# Vérifier que app backend tourne:
sudo systemctl status nom-app
# Ou
ps aux | grep node    # Pour Node.js
ps aux | grep python  # Pour Python
# Démarrer app si nécessaire

# Erreur: "Bad Gateway" (502)
# Cause: Apache ne peut pas se connecter au backend
# Solution:
# 1. Vérifier port backend correct
netstat -tlnp | grep :3000
# 2. Vérifier backend écoute sur localhost (pas 0.0.0.0)
# 3. Vérifier firewall local pas bloqué

# Erreur: "ProxyPass: no protocol"
# Cause: Oubli http:// dans ProxyPass
# Mauvais: ProxyPass / localhost:3000/
# Bon: ProxyPass / http://localhost:3000/

# Logs pour débugger
sudo tail -f /var/log/apache2/error.log
# Ou
sudo journalctl -u apache2 -f

# Activer logs debug proxy (temporaire)
LogLevel proxy:trace8
# Dans VirtualHost
# Génère BEAUCOUP de logs, désactiver après debug

# Tester backend directement
curl http://localhost:3000
# Si fonctionne, problème dans config Apache
# Si ne fonctionne pas, problème dans backend

# Vérifier headers transmis
# Dans app backend, logger tous headers:
# Node.js: console.log(req.headers);
# Python: print(request.headers);


# === RÉSUMÉ DÉBUTANT - PROXY SIMPLE ===

# 1. Activer modules
sudo a2enmod proxy proxy_http
sudo systemctl restart apache2

# 2. Créer VirtualHost
sudo nano /etc/apache2/sites-available/app.conf

# 3. Configuration minimale
<VirtualHost *:80>
    ServerName example.com
    ProxyPreserveHost On
    ProxyPass / http://localhost:3000/
    ProxyPassReverse / http://localhost:3000/
</VirtualHost>

# 4. Activer et recharger
sudo a2ensite app.conf
sudo apachectl configtest
sudo systemctl reload apache2

# 5. Démarrer votre application backend
# node app.js (pour Node.js)
# python manage.py runserver 0.0.0.0:8000 (pour Django)
# etc.

# 6. Tester
# http://example.com


# === RÉSUMÉ DÉBUTANT - LOAD BALANCER ===

# 1. Activer modules
sudo a2enmod proxy proxy_http proxy_balancer lbmethod_byrequests
sudo systemctl restart apache2

# 2. Configuration
<Proxy balancer://cluster>
    BalancerMember http://server1:8080
    BalancerMember http://server2:8080
    BalancerMember http://server3:8080
    ProxySet lbmethod=byrequests
</Proxy>

<VirtualHost *:80>
    ServerName example.com
    ProxyPass / balancer://cluster/
    ProxyPassReverse / balancer://cluster/
</VirtualHost>

# 3. Activer et tester
sudo a2ensite cluster.conf
sudo apachectl configtest
sudo systemctl reload apache2

[OK] PHP CONFIGURATION - EXÉCUTER CODE PHP AVEC APACHE

# === COMPRENDRE PHP AVEC APACHE ===

# PHP = Langage de programmation côté serveur
# Apache doit "interpréter" les fichiers .php
# Deux méthodes principales:
# 1. mod_php (ancien, intégré dans Apache)
# 2. PHP-FPM (moderne, séparé, recommandé)

# ANALOGIE: Restaurant
# - Apache = Serveur qui prend commandes (requêtes HTTP)
# - PHP = Cuisinier qui prépare plats (exécute code)
# 
# mod_php: Cuisinier est employé du restaurant (intégré)
# PHP-FPM: Cuisinier est dans cuisine séparée (service externe)

# Pourquoi PHP-FPM est meilleur ?
# [OK] Plus performant (gestion processus optimisée)
# [OK] Moins de mémoire (processus séparés)
# [OK] Plus sécurisé (isolation)
# [OK] Peut redémarrer PHP sans redémarrer Apache
# [OK] Plusieurs versions PHP en parallèle possible
# [OK] Meilleur pour haute charge

# Quand utiliser mod_php ?
# - Serveur mutualisé simple
# - Compatibilité ancienne app
# - Configuration très simple
# 
# Quand utiliser PHP-FPM ? (RECOMMANDÉ)
# - Production moderne
# - Haute performance
# - Plusieurs sites avec versions PHP différentes
# - Meilleur contrôle ressources


# === MÉTHODE 1: MOD_PHP (Ancien, simple) ===

# --- Installation Ubuntu/Debian ---

sudo apt update

# Installer PHP et module Apache
sudo apt install php libapache2-mod-php
# php: Le langage PHP lui-même
# libapache2-mod-php: Module pour intégrer PHP dans Apache

# Modules PHP courants (optionnels mais recommandés)
sudo apt install php-mysql       # Connexion MySQL/MariaDB
sudo apt install php-curl        # Requêtes HTTP
sudo apt install php-gd          # Manipulation images
sudo apt install php-mbstring    # Gestion chaînes multi-bytes
sudo apt install php-xml         # Parser XML
sudo apt install php-zip         # Compression ZIP
sudo apt install php-json        # JSON (souvent inclus par défaut)
sudo apt install php-intl        # Internationalisation
sudo apt install php-bcmath      # Calculs précision
sudo apt install php-soap        # Services Web SOAP

# Vérifier modules PHP installés
php -m
# Liste tous les modules PHP disponibles

# Vérifier version PHP
php -v
# Affiche:
# PHP 8.2.7 (cli) (built: Jun  9 2023 19:37:27) (NTS)

# Le module est automatiquement activé
# Vérifier:
sudo apachectl -M | grep php
# Affiche: php_module (shared)

# Redémarrer Apache pour prendre en compte
sudo systemctl restart apache2

# Tester PHP
echo "<?php phpinfo(); ?>" | sudo tee /var/www/html/info.php

# Ouvrir dans navigateur:
# http://localhost/info.php
# Vous devriez voir page d'information PHP complète

# [ATTENTION] SÉCURITÉ: Supprimer info.php après test !
sudo rm /var/www/html/info.php


# --- Installation CentOS/RHEL ---

# CentOS 7
sudo yum install php php-mysql php-gd php-xml
sudo systemctl restart httpd

# CentOS 8+ / Fedora
sudo dnf install php php-mysqlnd php-gd php-xml
sudo systemctl restart httpd


# --- Configuration mod_php ---

# Fichier config PHP:
# Ubuntu/Debian: /etc/php/8.2/apache2/php.ini
# CentOS: /etc/php.ini

# Trouver emplacement exact:
php --ini
# Affiche:
# Loaded Configuration File: /etc/php/8.2/apache2/php.ini

# Éditer configuration:
sudo nano /etc/php/8.2/apache2/php.ini

# Paramètres importants (voir section Configuration PHP ci-dessous)

# Après modification php.ini:
sudo systemctl restart apache2
# [ATTENTION] Redémarrage OBLIGATOIRE avec mod_php !


# === MÉTHODE 2: PHP-FPM (Moderne, RECOMMANDÉ) ===

# FPM = FastCGI Process Manager
# PHP tourne comme service séparé
# Apache communique avec PHP via FastCGI

# --- Installation Ubuntu/Debian ---

sudo apt update

# Installer PHP-FPM
sudo apt install php-fpm
# Installe PHP-FPM (version par défaut du système)

# Ou version spécifique:
sudo apt install php8.2-fpm
sudo apt install php8.1-fpm
sudo apt install php7.4-fpm

# Installer modules PHP
sudo apt install php8.2-mysql php8.2-curl php8.2-gd php8.2-mbstring \
    php8.2-xml php8.2-zip php8.2-intl php8.2-bcmath

# [ATTENTION] Adapter numéro version (8.2) selon votre installation

# Vérifier que PHP-FPM tourne
sudo systemctl status php8.2-fpm
# Active: active (running) = OK [OK]

# Démarrer PHP-FPM (si pas démarré)
sudo systemctl start php8.2-fpm

# Activer démarrage automatique
sudo systemctl enable php8.2-fpm


# --- Installation CentOS/RHEL ---

# CentOS 8+ / Fedora
sudo dnf install php-fpm php-mysqlnd php-gd php-xml php-mbstring

# Démarrer et activer
sudo systemctl start php-fpm
sudo systemctl enable php-fpm


# --- Activer modules Apache pour PHP-FPM ---

sudo a2enmod proxy_fcgi
# Module proxy FastCGI
# Permet à Apache de communiquer avec PHP-FPM

sudo a2enmod setenvif
# Module pour définir variables d'environnement
# Utilisé pour configuration PHP-FPM

# Activer configuration PHP-FPM par défaut
sudo a2enconf php8.2-fpm
# Crée lien symbolique dans conf-enabled/
# [ATTENTION] Adapter version PHP (8.2)

# Vérifier config activée
ls -l /etc/apache2/conf-enabled/ | grep php

# Redémarrer Apache
sudo systemctl restart apache2


# --- Configuration VirtualHost pour PHP-FPM ---

# Méthode 1: Socket Unix (RECOMMANDÉ - plus rapide)

<VirtualHost *:80>
    ServerName example.com
    DocumentRoot /var/www/example.com/public_html
    
    <Directory /var/www/example.com/public_html>
        Options -Indexes +FollowSymLinks
        AllowOverride All
        Require all granted
    </Directory>
    
    # === CONFIGURATION PHP-FPM ===
    
    <FilesMatch \.php$>
        # Pour tous fichiers .php
        SetHandler "proxy:unix:/run/php/php8.2-fpm.sock|fcgi://localhost"
        # Explication:
        # proxy:unix: = Utiliser socket Unix
        # /run/php/php8.2-fpm.sock = Chemin socket PHP-FPM
        # |fcgi://localhost = Protocole FastCGI
        
        # [ATTENTION] Adapter chemin socket selon version PHP:
        # PHP 8.2: /run/php/php8.2-fpm.sock
        # PHP 8.1: /run/php/php8.1-fpm.sock
        # PHP 7.4: /run/php/php7.4-fpm.sock
    </FilesMatch>
    
    # Bloquer accès direct aux fichiers PHP dans certains dossiers
    <Directory /var/www/example.com/public_html/uploads>
        <FilesMatch \.php$>
            Require all denied
        </FilesMatch>
    </Directory>
    
    ErrorLog ${APACHE_LOG_DIR}/example-error.log
    CustomLog ${APACHE_LOG_DIR}/example-access.log combined
</VirtualHost>

# Où trouver le chemin du socket ?
ls -l /run/php/
# Affiche tous les sockets PHP disponibles
# php8.2-fpm.sock, php8.1-fpm.sock, etc.


# Méthode 2: TCP (si socket ne fonctionne pas)

<VirtualHost *:80>
    ServerName example.com
    DocumentRoot /var/www/example.com/public_html
    
    <Directory /var/www/example.com/public_html>
        Options -Indexes +FollowSymLinks
        AllowOverride All
        Require all granted
    </Directory>
    
    # PHP-FPM via TCP
    <FilesMatch \.php$>
        SetHandler "proxy:fcgi://127.0.0.1:9000"
        # 127.0.0.1:9000 = IP:Port PHP-FPM
        # Par défaut, PHP-FPM écoute sur socket Unix
        # Il faut modifier config pour écouter sur TCP
    </FilesMatch>
    
    ErrorLog ${APACHE_LOG_DIR}/example-error.log
    CustomLog ${APACHE_LOG_DIR}/example-access.log combined
</VirtualHost>

# Pour utiliser TCP, modifier config PHP-FPM:
sudo nano /etc/php/8.2/fpm/pool.d/www.conf

# Commenter ligne socket:
;listen = /run/php/php8.2-fpm.sock

# Décommenter ligne TCP:
listen = 127.0.0.1:9000

# Redémarrer PHP-FPM:
sudo systemctl restart php8.2-fpm


# === CONFIGURATION PHP (php.ini) ===

# Fichiers de configuration PHP selon méthode:

# mod_php:
# /etc/php/8.2/apache2/php.ini

# PHP-FPM:
# /etc/php/8.2/fpm/php.ini

# CLI (ligne de commande):
# /etc/php/8.2/cli/php.ini

# Trouver fichier actif:
php --ini


# --- Éditer php.ini ---

sudo nano /etc/php/8.2/fpm/php.ini


# === PARAMÈTRES ESSENTIELS ===

# --- Limites mémoire ---
memory_limit = 256M
# Mémoire max par script PHP
# Par défaut: 128M
# WordPress recommande: 256M
# Sites lourds: 512M ou plus
# 
# Calcul: Dépend de votre RAM serveur
# Serveur 2GB RAM: 256M OK
# Serveur 8GB RAM: 512M ou plus


# --- Taille upload fichiers ---
upload_max_filesize = 64M
# Taille max fichier uploadé
# Par défaut: 2M (trop petit!)
# 
# Exemples:
# 64M = Photos haute résolution
# 128M = Vidéos courtes
# 256M = Gros fichiers

post_max_size = 64M
# Taille max POST (formulaire)
# Doit être >= upload_max_filesize
# Souvent même valeur ou légèrement supérieur
# 
# Pourquoi différent ?
# POST peut contenir plusieurs fichiers + données formulaire


# --- Temps d'exécution ---
max_execution_time = 300
# Durée max exécution script (secondes)
# Par défaut: 30 secondes
# 300 = 5 minutes
# 
# Augmentez pour:
# - Import gros fichiers
# - Génération rapports complexes
# - Traitement batch
# 
# [ATTENTION] Trop élevé = Scripts mal codés bloquent serveur

max_input_time = 300
# Durée max parsing données entrée (secondes)
# Upload gros fichiers = long parsing
# Généralement même valeur que max_execution_time


# --- Affichage erreurs (DÉVELOPPEMENT) ---
display_errors = On
# Affiche erreurs à l'écran
# ON en développement (pour voir erreurs)

display_startup_errors = On
# Affiche erreurs au démarrage PHP

error_reporting = E_ALL
# Niveau erreurs à rapporter
# E_ALL = Toutes les erreurs (recommandé développement)
# 
# Niveaux:
# E_ERROR = Erreurs fatales seulement
# E_WARNING = Erreurs + warnings
# E_ALL = Tout (erreurs + warnings + notices + deprecated)


# --- Affichage erreurs (PRODUCTION) ---
display_errors = Off
# NE PAS afficher erreurs à l'écran en production!
# Risque sécurité: révèle chemins, structure code
# [ATTENTION] TRÈS IMPORTANT !

display_startup_errors = Off
# Pareil pour erreurs démarrage

error_reporting = E_ALL & ~E_DEPRECATED & ~E_STRICT
# Rapporte tout sauf deprecated et strict
# E_ALL = Toutes erreurs
# ~E_DEPRECATED = Exclut deprecated
# ~E_STRICT = Exclut strict standards

log_errors = On
# Enregistre erreurs dans fichier log
# OBLIGATOIRE en production !

error_log = /var/log/php/error.log
# Chemin fichier log erreurs PHP
# Créer dossier si n'existe pas:
# sudo mkdir -p /var/log/php
# sudo chown www-data:www-data /var/log/php


# --- Sessions ---
session.save_handler = files
# Méthode stockage sessions
# files = Fichiers sur disque (par défaut)
# Autres: memcache, redis (plus performant production)

session.save_path = "/var/lib/php/sessions"
# Où stocker fichiers sessions
# Vérifier permissions:
# sudo chown -R www-data:www-data /var/lib/php/sessions
# sudo chmod 700 /var/lib/php/sessions

session.gc_maxlifetime = 1440
# Durée vie session (secondes)
# 1440 = 24 minutes
# 3600 = 1 heure
# 86400 = 24 heures

session.cookie_httponly = On
# Cookie session pas accessible JavaScript
# Protection XSS
# TOUJOURS On !

session.cookie_secure = On
# Cookie session SEULEMENT via HTTPS
# Activer si site en HTTPS
# Off si HTTP

session.use_strict_mode = On
# Refuse session IDs non initialisés
# Sécurité++


# --- Timezone ---
date.timezone = Europe/Paris
# Fuseau horaire PHP
# OBLIGATOIRE sinon warning !
# 
# Exemples:
# Europe/Paris
# Europe/London
# America/New_York
# America/Los_Angeles
# Asia/Tokyo
# Africa/Dakar
# 
# Liste complète: https://www.php.net/manual/en/timezones.php


# --- Sécurité ---
expose_php = Off
# Masque version PHP dans headers HTTP
# Par défaut: On (affiche X-Powered-By: PHP/8.2.7)
# Off = Plus de header (meilleur sécurité)

allow_url_fopen = On
# Autorise fopen() sur URLs
# On = Peut faire file_get_contents('http://...')
# Off = Sécurité++ mais casse certaines apps

allow_url_include = Off
# Autorise include() sur URLs
# [ATTENTION] TOUJOURS Off (risque sécurité énorme!)
# Permet include('http://site-malveillant.com/hack.php')

disable_functions = exec,passthru,shell_exec,system,proc_open,popen
# Désactive fonctions dangereuses
# Liste fonctions séparées par virgules
# exec, shell_exec, etc. = Exécution commandes système
# 
# [ATTENTION] Peut casser certaines apps (vérifier avant)
# WordPress, Laravel modernes = OK
# Anciennes apps = Peuvent avoir besoin


# --- Opcache (Performance++) ---
opcache.enable = 1
# Active Opcache (cache bytecode PHP)
# ÉNORME gain performance !
# 1 = Activé, 0 = Désactivé

opcache.memory_consumption = 128
# Mémoire Opcache (MB)
# 128MB = Bon compromis
# Sites gros: 256MB ou plus

opcache.max_accelerated_files = 10000
# Nombre max fichiers cachés
# 10000 = Largement suffisant la plupart sites

opcache.revalidate_freq = 60
# Fréquence vérification modifications (secondes)
# 60 = Vérifie toutes les minutes
# Développement: 0 (toujours vérifier)
# Production: 60 ou plus


# Après modification php.ini:

# PHP-FPM:
sudo systemctl restart php8.2-fpm

# mod_php:
sudo systemctl restart apache2

# Vérifier config PHP active:
echo "<?php phpinfo(); ?>" | sudo tee /var/www/html/info.php
# Ouvrir http://localhost/info.php
# Chercher paramètres modifiés


# === CONFIGURATION POOL PHP-FPM ===

# Pool = Groupe de processus PHP-FPM
# Configuration: /etc/php/8.2/fpm/pool.d/www.conf

sudo nano /etc/php/8.2/fpm/pool.d/www.conf


# === PARAMÈTRES ESSENTIELS POOL ===

[www]
# Nom du pool
# Peut créer plusieurs pools (www, site1, site2, etc.)


# --- Utilisateur/Groupe ---
user = www-data
group = www-data
# Processus PHP tournent avec ces permissions
# Ubuntu/Debian: www-data
# CentOS: apache


# --- Socket de communication ---
listen = /run/php/php8.2-fpm.sock
# Socket Unix (RECOMMANDÉ)
# Plus rapide que TCP

listen.owner = www-data
listen.group = www-data
listen.mode = 0660
# Permissions socket
# Apache doit pouvoir lire/écrire
# 0660 = Owner+Group: read+write, Others: nothing


# --- Gestion processus ---

pm = dynamic
# Mode gestion processus:
# - static: Nombre fixe processus
# - dynamic: Nombre variable (RECOMMANDÉ)
# - ondemand: Crée processus à la demande

pm.max_children = 50
# Nombre MAX processus PHP
# Calcul important!
# 
# Formule:
# max_children = RAM_disponible / RAM_par_processus
# 
# Exemple:
# Serveur 2GB RAM
# RAM PHP par processus = ~30MB
# max_children = 2000MB / 30MB = ~66
# Mettre 50 pour sécurité (autres services aussi)
# 
# Serveur 8GB RAM, ~200 processus
# Si dépassé, erreur "max_children reached"

pm.start_servers = 5
# Processus au démarrage
# Généralement: 10-25% de max_children
# max_children=50 -> start_servers=5 à 10

pm.min_spare_servers = 5
# Minimum processus "en attente"
# Prêts à traiter requêtes immédiatement
# Si moins, PHP-FPM en crée

pm.max_spare_servers = 35
# Maximum processus "en attente"
# Si plus, PHP-FPM en tue
# Généralement: 50-75% de max_children

pm.max_requests = 500
# Nombre requêtes avant recyclage processus
# Évite fuites mémoire
# 500-1000 = Bon compromis
# 0 = Jamais recycler (déconseillé)


# --- Logs ---
php_admin_value[error_log] = /var/log/php8.2-fpm-www.log
php_admin_flag[log_errors] = on
# Logs spécifiques ce pool


# --- Limites ---
php_admin_value[memory_limit] = 256M
# Override memory_limit de php.ini
# Pour ce pool uniquement

php_admin_value[upload_max_filesize] = 64M
php_admin_value[post_max_size] = 64M


# Après modification pool:
sudo systemctl restart php8.2-fpm

# Vérifier status pool:
sudo systemctl status php8.2-fpm


# === PLUSIEURS VERSIONS PHP EN PARALLÈLE ===

# Scénario: Site ancien (PHP 7.4) et site nouveau (PHP 8.2)

# Installer plusieurs versions
sudo apt install php7.4-fpm php7.4-mysql php7.4-gd php7.4-xml
sudo apt install php8.2-fpm php8.2-mysql php8.2-gd php8.2-xml

# Démarrer tous les services
sudo systemctl start php7.4-fpm
sudo systemctl start php8.2-fpm
sudo systemctl enable php7.4-fpm
sudo systemctl enable php8.2-fpm

# Vérifier que les deux tournent
sudo systemctl status php7.4-fpm
sudo systemctl status php8.2-fpm


# VirtualHost site ancien (PHP 7.4)
<VirtualHost *:80>
    ServerName old-app.example.com
    DocumentRoot /var/www/old-app
    
    <Directory /var/www/old-app>
        Options -Indexes +FollowSymLinks
        AllowOverride All
        Require all granted
    </Directory>
    
    # PHP 7.4
    <FilesMatch \.php$>
        SetHandler "proxy:unix:/run/php/php7.4-fpm.sock|fcgi://localhost"
    </FilesMatch>
    
    ErrorLog ${APACHE_LOG_DIR}/old-app-error.log
    CustomLog ${APACHE_LOG_DIR}/old-app-access.log combined
</VirtualHost>


# VirtualHost site nouveau (PHP 8.2)
<VirtualHost *:80>
    ServerName new-app.example.com
    DocumentRoot /var/www/new-app
    
    <Directory /var/www/new-app>
        Options -Indexes +FollowSymLinks
        AllowOverride All
        Require all granted
    </Directory>
    
    # PHP 8.2
    <FilesMatch \.php$>
        SetHandler "proxy:unix:/run/php/php8.2-fpm.sock|fcgi://localhost"
    </FilesMatch>
    
    ErrorLog ${APACHE_LOG_DIR}/new-app-error.log
    CustomLog ${APACHE_LOG_DIR}/new-app-access.log combined
</VirtualHost>

# Activer sites
sudo a2ensite old-app.conf
sudo a2ensite new-app.conf
sudo apachectl configtest
sudo systemctl reload apache2

# Chaque site utilise SA version PHP !
# old-app.example.com -> PHP 7.4
# new-app.example.com -> PHP 8.2


# === TESTER CONFIGURATION PHP ===

# Créer fichier test
cat > /var/www/html/test.php << 'EOF'
<?php
echo "<h1>Test PHP</h1>";
echo "<p>PHP Version: " . phpversion() . "</p>";
echo "<p>Date: " . date('Y-m-d H:i:s') . "</p>";
echo "<p>Server API: " . php_sapi_name() . "</p>";

// Test connexion MySQL
if (extension_loaded('mysqli')) {
    echo "<p style='color:green;'>[OK] Extension MySQL chargée</p>";
} else {
    echo "<p style='color:red;'>[X] Extension MySQL manquante</p>";
}

// Test GD (images)
if (extension_loaded('gd')) {
    echo "<p style='color:green;'>[OK] Extension GD chargée</p>";
} else {
    echo "<p style='color:red;'>[X] Extension GD manquante</p>";
}

// Infos upload
echo "<p>upload_max_filesize: " . ini_get('upload_max_filesize') . "</p>";
echo "<p>post_max_size: " . ini_get('post_max_size') . "</p>";
echo "<p>memory_limit: " . ini_get('memory_limit') . "</p>";
echo "<p>max_execution_time: " . ini_get('max_execution_time') . "</p>";
?>
EOF

# Ouvrir dans navigateur:
# http://localhost/test.php


# === DÉPANNAGE PHP ===

# Erreur: "File not found" ou page blanche
# Cause: PHP pas activé correctement
# Solution:
sudo apachectl -M | grep php    # mod_php
sudo apachectl -M | grep fcgi   # PHP-FPM
sudo systemctl status php8.2-fpm

# Erreur: "Primary script unknown"
# Cause: Socket PHP-FPM incorrect ou permissions
# Solution:
ls -l /run/php/php8.2-fpm.sock
# Doit être accessible par www-data
sudo chown www-data:www-data /run/php/php8.2-fpm.sock
sudo chmod 660 /run/php/php8.2-fpm.sock

# Erreur: "502 Bad Gateway" avec PHP-FPM
# Cause: PHP-FPM pas démarré ou socket incorrect
# Solution:
sudo systemctl start php8.2-fpm
# Vérifier chemin socket dans VirtualHost

# Page blanche sans erreur
# Cause: Erreurs PHP cachées
# Solution: Voir logs
sudo tail -f /var/log/php/error.log
sudo tail -f /var/log/php8.2-fpm-www.log

# Warning: "Unable to create session directory"
# Cause: Permissions dossier sessions
# Solution:
sudo chown -R www-data:www-data /var/lib/php/sessions
sudo chmod 700 /var/lib/php/sessions

# Errors: "max_children reached"
# Cause: Trop de processus PHP demandés
# Solution: Augmenter pm.max_children dans pool.conf
sudo nano /etc/php/8.2/fpm/pool.d/www.conf
# pm.max_children = 100  (augmenter)
sudo systemctl restart php8.2-fpm


# === RÉSUMÉ DÉBUTANT - PHP-FPM ===

# 1. Installer PHP-FPM
sudo apt install php8.2-fpm php8.2-mysql php8.2-gd php8.2-xml

# 2. Démarrer service
sudo systemctl start php8.2-fpm
sudo systemctl enable php8.2-fpm

# 3. Activer modules Apache
sudo a2enmod proxy_fcgi setenvif
sudo a2enconf php8.2-fpm
sudo systemctl restart apache2

# 4. Configurer VirtualHost
<FilesMatch \.php$>
    SetHandler "proxy:unix:/run/php/php8.2-fpm.sock|fcgi://localhost"
</FilesMatch>

# 5. Tester
echo "<?php phpinfo(); ?>" > /var/www/html/info.php
# Ouvrir http://localhost/info.php

[OK] LOGS & MONITORING


# === Fichiers logs ===

# Logs accès
/var/log/apache2/access.log
/var/log/httpd/access_log

# Logs erreurs
/var/log/apache2/error.log
/var/log/httpd/error_log

# === Lire logs en temps réel ===

# Access log
sudo tail -f /var/log/apache2/access.log

# Error log
sudo tail -f /var/log/apache2/error.log

# Tous les logs
sudo tail -f /var/log/apache2/*.log

# Filtrer par IP
sudo tail -f /var/log/apache2/access.log | grep "192.168.1.100"

# Filtrer erreurs 404
sudo tail -f /var/log/apache2/access.log | grep " 404 "

# Filtrer erreurs 500
sudo tail -f /var/log/apache2/access.log | grep " 500 "

# === Configuration logging VirtualHost ===

<VirtualHost *:80>
    ServerName example.com
    
    # Logs séparés par site
    ErrorLog ${APACHE_LOG_DIR}/example-error.log
    CustomLog ${APACHE_LOG_DIR}/example-access.log combined
    
    # Formats disponibles:
    # combined - Format standard complet
    # common - Format standard simple
    # vhost_combined - Avec virtual host
    # referer - Referer tracking
    # agent - User agent tracking
</VirtualHost>

# === Formats de log personnalisés ===

# Dans apache2.conf ou httpd.conf

# Format JSON
LogFormat "{ \"time\":\"%t\", \"remote_ip\":\"%a\", \"status\":%>s, \"request\":\"%U\", \"query\":\"%q\", \"method\":\"%m\", \"referrer\":\"%{Referer}i\", \"agent\":\"%{User-agent}i\" }" json

CustomLog ${APACHE_LOG_DIR}/access.log json

# Format détaillé
LogFormat "%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\" %D" detailed
CustomLog ${APACHE_LOG_DIR}/access.log detailed

# === Rotation logs ===

# Configuration logrotate: /etc/logrotate.d/apache2

/var/log/apache2/*.log {
    daily
    missingok
    rotate 14
    compress
    delaycompress
    notifempty
    create 640 root adm
    sharedscripts
    postrotate
        if invoke-rc.d apache2 status > /dev/null 2>&1; then \
            invoke-rc.d apache2 reload > /dev/null 2>&1; \
        fi;
    endscript
}

# Forcer rotation manuelle
sudo logrotate -f /etc/logrotate.d/apache2

# === Analyse logs ===

# Compter requêtes par IP
awk '{print $1}' /var/log/apache2/access.log | sort | uniq -c | sort -rn | head

# Top 10 URLs visitées
awk '{print $7}' /var/log/apache2/access.log | sort | uniq -c | sort -rn | head

# Codes HTTP
awk '{print $9}' /var/log/apache2/access.log | sort | uniq -c | sort -rn

# User agents
awk -F'"' '{print $6}' /var/log/apache2/access.log | sort | uniq -c | sort -rn

# Bande passante par IP
awk '{sum[$1]+=$10} END {for (ip in sum) print ip, sum[ip]}' /var/log/apache2/access.log | sort -k2 -rn

# Requêtes par heure
awk '{print $4}' /var/log/apache2/access.log | cut -c 14-15 | sort | uniq -c

# Temps de réponse moyen (format detailed)
awk '{sum+=$NF; count++} END {print sum/count/1000000 " secondes"}' /var/log/apache2/access.log

# === Outils d'analyse ===

# GoAccess (analyseur en temps réel)
sudo apt install goaccess

# Analyse interactive terminal
sudo goaccess /var/log/apache2/access.log

# Générer rapport HTML
sudo goaccess /var/log/apache2/access.log -o /var/www/html/report.html --log-format=COMBINED

# Temps réel
sudo goaccess /var/log/apache2/access.log -o /var/www/html/report.html --real-time-html

# AWStats (statistiques détaillées)
sudo apt install awstats

# Webalizer
sudo apt install webalizer

[OK] PERFORMANCE & OPTIMISATION


# === Multi-Processing Modules (MPM) ===

# Voir MPM actuel
apachectl -V | grep -i mpm

# Debian/Ubuntu - Changer MPM
sudo a2dismod mpm_prefork
sudo a2enmod mpm_event
sudo systemctl restart apache2

# === MPM Prefork (défaut PHP mod_php) ===
# /etc/apache2/mods-available/mpm_prefork.conf

<IfModule mpm_prefork_module>
    StartServers             5
    MinSpareServers          5
    MaxSpareServers          10
    MaxRequestWorkers        150
    MaxConnectionsPerChild   0
</IfModule>

# === MPM Worker (multi-thread) ===
# /etc/apache2/mods-available/mpm_worker.conf

<IfModule mpm_worker_module>
    StartServers             2
    MinSpareThreads          25
    MaxSpareThreads          75
    ThreadLimit              64
    ThreadsPerChild          25
    MaxRequestWorkers        150
    MaxConnectionsPerChild   0
</IfModule>

# === MPM Event (recommandé pour performance) ===
# /etc/apache2/mods-available/mpm_event.conf

<IfModule mpm_event_module>
    StartServers             2
    MinSpareThreads          25
    MaxSpareThreads          75
    ThreadLimit              64
    ThreadsPerChild          25
    MaxRequestWorkers        150
    MaxConnectionsPerChild   0
</IfModule>

# Configuration optimisée production
<IfModule mpm_event_module>
    StartServers             3
    MinSpareThreads          75
    MaxSpareThreads          250
    ThreadsPerChild          25
    MaxRequestWorkers        400
    MaxConnectionsPerChild   1000
    ServerLimit              16
</IfModule>

# === Compression ===

# Activer mod_deflate
sudo a2enmod deflate

# Configuration
<IfModule mod_deflate.c>
    # Compresser types MIME
    AddOutputFilterByType DEFLATE text/html
    AddOutputFilterByType DEFLATE text/plain
    AddOutputFilterByType DEFLATE text/xml
    AddOutputFilterByType DEFLATE text/css
    AddOutputFilterByType DEFLATE text/javascript
    AddOutputFilterByType DEFLATE application/xml
    AddOutputFilterByType DEFLATE application/xhtml+xml
    AddOutputFilterByType DEFLATE application/rss+xml
    AddOutputFilterByType DEFLATE application/javascript
    AddOutputFilterByType DEFLATE application/x-javascript
    AddOutputFilterByType DEFLATE application/json
    AddOutputFilterByType DEFLATE image/svg+xml
    
    # Niveau compression (1-9)
    DeflateCompressionLevel 6
    
    # Exclure anciens navigateurs
    BrowserMatch ^Mozilla/4 gzip-only-text/html
    BrowserMatch ^Mozilla/4\.0[678] no-gzip
    BrowserMatch \bMSIE !no-gzip !gzip-only-text/html
    
    # Ne pas compresser images
    SetEnvIfNoCase Request_URI \.(?:gif|jpe?g|png|ico)$ no-gzip
</IfModule>

# === Cache ===

# Activer modules
sudo a2enmod expires
sudo a2enmod headers
sudo a2enmod cache
sudo a2enmod cache_disk

# Configuration expires
<IfModule mod_expires.c>
    ExpiresActive On
    ExpiresDefault "access plus 1 month"
    
    # HTML
    ExpiresByType text/html "access plus 1 hour"
    
    # CSS/JS
    ExpiresByType text/css "access plus 1 year"
    ExpiresByType application/javascript "access plus 1 year"
    ExpiresByType application/x-javascript "access plus 1 year"
    
    # Images
    ExpiresByType image/gif "access plus 1 year"
    ExpiresByType image/jpeg "access plus 1 year"
    ExpiresByType image/png "access plus 1 year"
    ExpiresByType image/svg+xml "access plus 1 year"
    ExpiresByType image/x-icon "access plus 1 year"
    
    # Fonts
    ExpiresByType font/ttf "access plus 1 year"
    ExpiresByType font/woff "access plus 1 year"
    ExpiresByType font/woff2 "access plus 1 year"
    ExpiresByType application/font-woff "access plus 1 year"
    
    # Media
    ExpiresByType audio/ogg "access plus 1 year"
    ExpiresByType video/mp4 "access plus 1 year"
    ExpiresByType video/webm "access plus 1 year"
</IfModule>

# Cache headers
<IfModule mod_headers.c>
    # Cache images 1 an
    <FilesMatch "\.(ico|jpg|jpeg|png|gif|svg|webp)$">
        Header set Cache-Control "max-age=31536000, public"
    </FilesMatch>
    
    # Cache CSS/JS 1 an
    <FilesMatch "\.(css|js)$">
        Header set Cache-Control "max-age=31536000, public"
    </FilesMatch>
    
    # Pas de cache HTML
    <FilesMatch "\.(html|htm)$">
        Header set Cache-Control "no-cache, no-store, must-revalidate"
        Header set Pragma "no-cache"
        Header set Expires 0
    </FilesMatch>
</IfModule>

# === HTTP/2 ===

# Activer HTTP/2 (nécessite SSL)
sudo a2enmod http2

# Configuration VirtualHost
<VirtualHost *:443>
    ServerName example.com
    
    Protocols h2 http/1.1
    
    SSLEngine on
    SSLCertificateFile /path/to/cert.crt
    SSLCertificateKeyFile /path/to/cert.key
</VirtualHost>

# Vérifier HTTP/2
curl -I --http2 https://example.com

# === KeepAlive ===

# /etc/apache2/apache2.conf

# Activer KeepAlive
KeepAlive On

# Nombre max requêtes par connexion
MaxKeepAliveRequests 100

# Timeout connexion keepalive
KeepAliveTimeout 5

# === Timeout ===

# Timeout général (secondes)
Timeout 300

# === Limites ===

# Taille max requête
LimitRequestBody 10485760       # 10 MB

# Nombre max champs header
LimitRequestFields 100

# Taille max ligne header
LimitRequestFieldSize 8190

# Taille max ligne requête
LimitRequestLine 8190

[OK] SÉCURITÉ


# === Cacher version Apache ===

# /etc/apache2/conf-available/security.conf

ServerTokens Prod
ServerSignature Off

# ServerTokens options:
# Prod - Apache
# Major - Apache/2
# Minor - Apache/2.4
# Min - Apache/2.4.41
# OS - Apache/2.4.41 (Ubuntu)
# Full - Apache/2.4.41 (Ubuntu) PHP/7.4.3

# === Désactiver TRACE ===

TraceEnable off

# === Limiter méthodes HTTP ===

<Directory /var/www/html>
    <LimitExcept GET POST HEAD>
        Require all denied
    </LimitExcept>
</Directory>

# === Protection DDoS basique ===

# Activer modules
sudo a2enmod evasive
sudo a2enmod qos
sudo apt install libapache2-mod-evasive

# Configuration mod_evasive
<IfModule mod_evasive20.c>
    DOSHashTableSize 3097
    DOSPageCount 5
    DOSSiteCount 100
    DOSPageInterval 1
    DOSSiteInterval 1
    DOSBlockingPeriod 10
    DOSEmailNotify admin@example.com
    DOSLogDir /var/log/apache2/evasive
</IfModule>

# === Limiter taux requêtes ===

# Activer mod_ratelimit
sudo a2enmod ratelimit

# Limiter à 400 KB/s par connexion
<Location /downloads>
    SetOutputFilter RATE_LIMIT
    SetEnv rate-limit 400
</Location>

# === ModSecurity (WAF) ===

# Installer ModSecurity
sudo apt install libapache2-mod-security2

# Activer module
sudo a2enmod security2

# Copier config recommandée
sudo cp /etc/modsecurity/modsecurity.conf-recommended /etc/modsecurity/modsecurity.conf

# Éditer config
sudo nano /etc/modsecurity/modsecurity.conf

# Passer en mode actif
SecRuleEngine On

# Installer règles OWASP
sudo apt install modsecurity-crs

# Ou manuellement
cd /etc/modsecurity
sudo git clone https://github.com/coreruleset/coreruleset.git
sudo mv coreruleset/crs-setup.conf.example crs-setup.conf
sudo mv coreruleset/rules /etc/modsecurity/

# Activer dans Apache
# /etc/apache2/mods-enabled/security2.conf
<IfModule security2_module>
    SecRuleEngine On
    Include /etc/modsecurity/crs-setup.conf
    Include /etc/modsecurity/rules/*.conf
</IfModule>

# === Fail2Ban ===

# Installer Fail2Ban
sudo apt install fail2ban

# Configuration Apache
sudo nano /etc/fail2ban/jail.local

[apache-auth]
enabled = true
port = http,https
logpath = /var/log/apache2/error.log

[apache-badbots]
enabled = true
port = http,https
logpath = /var/log/apache2/access.log
maxretry = 2

[apache-noscript]
enabled = true
port = http,https
logpath = /var/log/apache2/error.log

[apache-overflows]
enabled = true
port = http,https
logpath = /var/log/apache2/error.log
maxretry = 2

[apache-nohome]
enabled = true
port = http,https
logpath = /var/log/apache2/error.log

[apache-botsearch]
enabled = true
port = http,https
logpath = /var/log/apache2/error.log

# Redémarrer Fail2Ban
sudo systemctl restart fail2ban

# Vérifier status
sudo fail2ban-client status
sudo fail2ban-client status apache-auth

# Débannir IP
sudo fail2ban-client set apache-auth unbanip 192.168.1.100

# === Bloquer pays (GeoIP) ===

# Installer GeoIP
sudo apt install libapache2-mod-geoip geoip-database

# Activer module
sudo a2enmod geoip

# Configuration
<IfModule mod_geoip.c>
    GeoIPEnable On
    GeoIPDBFile /usr/share/GeoIP/GeoIP.dat
    
    # Bloquer pays
    SetEnvIf GEOIP_COUNTRY_CODE CN BlockCountry
    SetEnvIf GEOIP_COUNTRY_CODE RU BlockCountry
    
    <Directory /var/www/html>
        Require all granted
        Require not env BlockCountry
    </Directory>
</IfModule>

# === Headers de sécurité ===

<IfModule mod_headers.c>
    # XSS Protection
    Header set X-XSS-Protection "1; mode=block"
    
    # Clickjacking Protection
    Header always set X-Frame-Options "SAMEORIGIN"
    
    # MIME Sniffing Protection
    Header set X-Content-Type-Options "nosniff"
    
    # Referrer Policy
    Header set Referrer-Policy "strict-origin-when-cross-origin"
    
    # Content Security Policy
    Header set Content-Security-Policy "default-src 'self'; script-src 'self' 'unsafe-inline'; style-src 'self' 'unsafe-inline'"
    
    # Permissions Policy
    Header set Permissions-Policy "geolocation=(), microphone=(), camera=()"
    
    # HSTS (HTTPS seulement)
    Header always set Strict-Transport-Security "max-age=31536000; includeSubDomains; preload"
</IfModule>

# === Désactiver listage répertoires ===

<Directory /var/www/html>
    Options -Indexes
</Directory>

# === Permissions fichiers ===

# Permissions recommandées
sudo chown -R www-data:www-data /var/www/html
sudo find /var/www/html -type d -exec chmod 755 {} \;
sudo find /var/www/html -type f -exec chmod 644 {} \;

# Logs
sudo chown -R root:adm /var/log/apache2
sudo chmod 640 /var/log/apache2/*

[OK] MONITORING & STATUS


# === Activer mod_status ===

sudo a2enmod status

# Configuration
# /etc/apache2/mods-available/status.conf

<Location /server-status>
    SetHandler server-status
    Require local
    # Ou autoriser IP spécifique
    # Require ip 192.168.1.0/24
</Location>

# Extended status (plus détaillé)
ExtendedStatus On

# Accéder au status
# http://localhost/server-status
# http://localhost/server-status?refresh=5    # Auto-refresh

# === mod_info ===

sudo a2enmod info

<Location /server-info>
    SetHandler server-info
    Require local
</Location>

# Accéder: http://localhost/server-info

# === Statistiques système ===

# Processus Apache
ps aux | grep apache2
ps aux | grep httpd

# Nombre de processus
ps aux | grep -c apache2

# Mémoire utilisée
ps aux | grep apache2 | awk '{sum+=$6} END {print sum/1024 " MB"}'

# Connexions actives
netstat -an | grep :80 | wc -l
ss -tan | grep :80 | wc -l

# Top connexions par IP
netstat -ntu | grep :80 | awk '{print $5}' | cut -d: -f1 | sort | uniq -c | sort -rn | head

# === Apache Bench (test performance) ===

# Test simple
ab -n 1000 -c 10 http://localhost/

# Avec keepalive
ab -n 1000 -c 10 -k http://localhost/

# POST avec données
ab -n 100 -c 10 -p data.txt -T application/x-www-form-urlencoded http://localhost/form

# Paramètres:
# -n : nombre total requêtes
# -c : nombre requêtes concurrentes
# -k : keepalive
# -t : durée test (secondes)
# -p : fichier données POST
# -T : content-type

# === Autres outils monitoring ===

# htop (processus)
sudo apt install htop
htop

# iftop (bande passante)
sudo apt install iftop
sudo iftop -i eth0

# netstat (connexions)
netstat -tulpn | grep apache

# lsof (fichiers ouverts)
sudo lsof -i :80
sudo lsof -u www-data

[OK] BENCHMARKING


# === Apache Bench (ab) ===

# Test basique
ab -n 1000 -c 100 http://localhost/

# Test prolongé
ab -t 60 -c 100 http://localhost/

# Avec authentication
ab -n 1000 -c 10 -A username:password http://localhost/

# === Siege ===

sudo apt install siege

# Test simple
siege -c 25 -t 1M http://localhost/

# Test URLs multiples
siege -c 25 -t 1M -f urls.txt

# urls.txt contient:
http://localhost/page1
http://localhost/page2
http://localhost/page3

# Benchmark mode
siege -b -c 100 -t 1M http://localhost/

# === wrk (moderne) ===

sudo apt install wrk

# Test
wrk -t12 -c400 -d30s http://localhost/

# Avec script Lua
wrk -t12 -c400 -d30s -s script.lua http://localhost/

# === JMeter ===
# https://jmeter.apache.org/

# === Locust ===
# https://locust.io/

[OK] BACKUP & MIGRATION


# === Sauvegarder configuration ===

# Backup complet config
sudo tar -czf apache-config-backup.tar.gz \
    /etc/apache2/ \
    /etc/httpd/

# Backup sites
sudo tar -czf apache-sites-backup.tar.gz \
    /var/www/

# Backup avec date
sudo tar -czf apache-backup-$(date +%Y%m%d).tar.gz \
    /etc/apache2/ \
    /var/www/

# === Restaurer configuration ===

sudo tar -xzf apache-config-backup.tar.gz -C /

# === Migration vers nouveau serveur ===

# Serveur source
sudo tar -czf apache-full-backup.tar.gz \
    /etc/apache2/ \
    /var/www/ \
    /etc/ssl/

# Transférer
scp apache-full-backup.tar.gz user@new-server:/tmp/

# Serveur destination
sudo tar -xzf /tmp/apache-full-backup.tar.gz -C /
sudo systemctl restart apache2

# === Script backup automatique ===

#!/bin/bash
# backup-apache.sh

BACKUP_DIR="/backup/apache"
DATE=$(date +%Y%m%d-%H%M%S)
BACKUP_FILE="apache-backup-$DATE.tar.gz"

# Créer backup
sudo tar -czf "$BACKUP_DIR/$BACKUP_FILE" \
    /etc/apache2/ \
    /var/www/ \
    /etc/ssl/certs/ \
    /etc/ssl/private/

# Garder seulement 30 derniers backups
find $BACKUP_DIR -name "apache-backup-*.tar.gz" -mtime +30 -delete

# Cron job (tous les jours à 2h)
# crontab -e
# 0 2 * * * /usr/local/bin/backup-apache.sh

[OK] DÉPANNAGE


# === Tester configuration ===

# Test syntaxe
sudo apache2ctl configtest
sudo apachectl configtest
sudo apache2ctl -t

# Afficher configuration chargée
apache2ctl -S
apachectl -S

# === Apache ne démarre pas ===

# Vérifier logs
sudo tail -50 /var/log/apache2/error.log
sudo journalctl -xeu apache2

# Vérifier syntaxe
sudo apache2ctl configtest

# Vérifier ports disponibles
sudo netstat -tulpn | grep :80
sudo ss -tulpn | grep :80

# Tuer processus sur port 80
sudo fuser -k 80/tcp

# Vérifier permissions
ls -la /var/www/html
ls -la /etc/apache2/

# === Erreur "Name or service not known" ===

# Ajouter ServerName
sudo nano /etc/apache2/apache2.conf

# Ajouter:
ServerName localhost

# === Port 80 déjà utilisé ===

# Trouver processus
sudo lsof -i :80
sudo netstat -tulpn | grep :80

# Arrêter nginx si installé
sudo systemctl stop nginx

# === Permission denied ===

# Vérifier SELinux (RHEL/CentOS)
sudo getenforce

# Autoriser Apache
sudo setsebool -P httpd_enable_network_connect 1
sudo setsebool -P httpd_can_network_connect 1

# Vérifier permissions
sudo chown -R www-data:www-data /var/www/html
sudo chmod -R 755 /var/www/html

# === Erreur 403 Forbidden ===

# Vérifier configuration Directory
<Directory /var/www/html>
    Options Indexes FollowSymLinks
    AllowOverride All
    Require all granted
</Directory>

# Vérifier permissions fichiers
sudo chmod 644 /var/www/html/index.html
sudo chmod 755 /var/www/html

# === Erreur 500 Internal Server Error ===

# Vérifier logs
sudo tail -50 /var/log/apache2/error.log

# Désactiver .htaccess temporairement
sudo mv /var/www/html/.htaccess /var/www/html/.htaccess.bak

# Vérifier syntaxe .htaccess
apache2ctl -t

# === Erreur 404 Not Found ===

# Vérifier DocumentRoot
apache2ctl -S

# Vérifier fichier existe
ls -la /var/www/html/

# === PHP ne fonctionne pas ===

# Vérifier module PHP chargé
apache2ctl -M | grep php

# Activer module
sudo a2enmod php8.2

# Vérifier PHP-FPM
sudo systemctl status php8.2-fpm

# Test fichier PHP
echo "<?php phpinfo(); ?>" | sudo tee /var/www/html/info.php

# === SSL ne fonctionne pas ===

# Vérifier module SSL
apache2ctl -M | grep ssl

# Activer SSL
sudo a2enmod ssl

# Vérifier certificat
openssl x509 -in /etc/ssl/certs/cert.crt -text -noout

# Test port 443
sudo netstat -tulpn | grep :443

# === .htaccess ignoré ===

# Vérifier AllowOverride
<Directory /var/www/html>
    AllowOverride All
</Directory>

# Vérifier module rewrite
sudo a2enmod rewrite

# === Performances lentes ===

# Vérifier processus
ps aux | grep apache2

# Vérifier mémoire
free -h

# Vérifier logs access
sudo tail -100 /var/log/apache2/access.log

# Activer status
curl http://localhost/server-status

# === Redémarrage impossible ===

# Arrêt forcé
sudo killall apache2
sudo killall httpd

# Nettoyer PID
sudo rm /var/run/apache2/apache2.pid

# Démarrer
sudo systemctl start apache2

[OK] COMMANDES UTILES


# Syntaxe fichiers
sudo apache2ctl -t
sudo apachectl configtest

# Lister modules
apache2ctl -M
apachectl -l

# Lister virtual hosts
apache2ctl -S

# Version
apache2 -v
apache2 -V

# Démarrer/arrêter
sudo systemctl start apache2
sudo systemctl stop apache2
sudo systemctl restart apache2
sudo systemctl reload apache2

# Status
sudo systemctl status apache2

# Logs temps réel
sudo tail -f /var/log/apache2/error.log
sudo tail -f /var/log/apache2/access.log

# Activer site
sudo a2ensite sitename
sudo systemctl reload apache2

# Désactiver site
sudo a2dissite sitename
sudo systemctl reload apache2

# Activer module
sudo a2enmod modulename
sudo systemctl restart apache2

# Désactiver module
sudo a2dismod modulename
sudo systemctl restart apache2

# Test configuration
sudo apache2ctl configtest

# Rechargement gracieux
sudo apache2ctl graceful

[OK] EXEMPLES CONFIGURATIONS COMPLÈTES


# === Site WordPress ===

<VirtualHost *:80>
    ServerName myblog.com
    ServerAlias www.myblog.com
    ServerAdmin admin@myblog.com
    
    DocumentRoot /var/www/myblog
    
    <Directory /var/www/myblog>
        Options -Indexes +FollowSymLinks
        AllowOverride All
        Require all granted
    </Directory>
    
    # PHP-FPM
    <FilesMatch \.php$>
        SetHandler "proxy:unix:/run/php/php8.2-fpm.sock|fcgi://localhost"
    </FilesMatch>
    
    # Logs
    ErrorLog ${APACHE_LOG_DIR}/myblog-error.log
    CustomLog ${APACHE_LOG_DIR}/myblog-access.log combined
    
    # Sécurité
    <FilesMatch "^\.">
        Require all denied
    </FilesMatch>
</VirtualHost>

# === Site Laravel/Symfony ===

<VirtualHost *:80>
    ServerName myapp.com
    ServerAdmin admin@myapp.com
    
    DocumentRoot /var/www/myapp/public
    
    <Directory /var/www/myapp/public>
        Options -Indexes +FollowSymLinks
        AllowOverride All
        Require all granted
        
        # Laravel/Symfony routing
        FallbackResource /index.php
    </Directory>
    
    # PHP-FPM
    <FilesMatch \.php$>
        SetHandler "proxy:unix:/run/php/php8.2-fpm.sock|fcgi://localhost"
    </FilesMatch>
    
    # Bloquer accès storage/vendor
    <Directory /var/www/myapp/storage>
        Require all denied
    </Directory>
    
    <Directory /var/www/myapp/vendor>
        Require all denied
    </Directory>
    
    ErrorLog ${APACHE_LOG_DIR}/myapp-error.log
    CustomLog ${APACHE_LOG_DIR}/myapp-access.log combined
</VirtualHost>

# === Application Node.js (Reverse Proxy) ===

<VirtualHost *:80>
    ServerName nodeapp.com
    ServerAdmin admin@nodeapp.com
    
    ProxyRequests Off
    ProxyPreserveHost On
    
    <Proxy *>
        Require all granted
    </Proxy>
    
    # Proxy vers Node.js
    ProxyPass / http://localhost:3000/
    ProxyPassReverse / http://localhost:3000/
    
    # WebSocket support
    RewriteEngine on
    RewriteCond %{HTTP:Upgrade} websocket [NC]
    RewriteCond %{HTTP:Connection} upgrade [NC]
    RewriteRule ^/?(.*) "ws://localhost:3000/$1" [P,L]
    
    # Logs
    ErrorLog ${APACHE_LOG_DIR}/nodeapp-error.log
    CustomLog ${APACHE_LOG_DIR}/nodeapp-access.log combined
</VirtualHost>

# === Site statique avec cache agressif ===

<VirtualHost *:80>
    ServerName static.example.com
    DocumentRoot /var/www/static
    
    <Directory /var/www/static>
        Options -Indexes +FollowSymLinks
        AllowOverride None
        Require all granted
    </Directory>
    
    # Cache agressif
    <IfModule mod_expires.c>
        ExpiresActive On
        ExpiresDefault "access plus 1 year"
    </IfModule>
    
    <IfModule mod_headers.c>
        Header set Cache-Control "max-age=31536000, public, immutable"
    </IfModule>
    
    # Compression
    <IfModule mod_deflate.c>
        AddOutputFilterByType DEFLATE text/html text/css application/javascript image/svg+xml
    </IfModule>
    
    ErrorLog ${APACHE_LOG_DIR}/static-error.log
    CustomLog ${APACHE_LOG_DIR}/static-access.log combined
</VirtualHost>

[OK] RESSOURCES


# Documentation officielle
https://httpd.apache.org/docs/2.4/

# Ubuntu Apache2 Guide
https://ubuntu.com/server/docs/web-servers-apache

# Security Best Practices
https://httpd.apache.org/docs/2.4/misc/security_tips.html

# mod_rewrite Guide
https://httpd.apache.org/docs/2.4/rewrite/

# Virtual Host Documentation
https://httpd.apache.org/docs/2.4/vhosts/

# SSL/TLS Guide
https://httpd.apache.org/docs/2.4/ssl/

# Performance Tuning
https://httpd.apache.org/docs/2.4/misc/perf-tuning.html

# Forums & Communauté
https://stackoverflow.com/questions/tagged/apache
https://serverfault.com/questions/tagged/apache2

# Let's Encrypt (Certbot)
https://certbot.eff.org/

# Apache Lounge (Windows)
https://www.apachelounge.com/

# Configuration Generator
https://mozilla.github.io/server-side-tls/ssl-config-generator/