Authentification à deux facteurs requise

Pour renforcer la sécurité de votre compte, veuillez activer l'authentification à deux facteurs (2FA). Cette fonctionnalité est obligatoire pour protéger vos données.

DevOups
Entreprise
Retour à la documentation

HAProxy

Load balancer et proxy inverse haute performance pour la gestion du trafic et la répartition de charge.

🏗️

Architecture et structure

Comprendre l'architecture modulaire de HAProxy et l'organisation des fichiers de configuration

Notre implémentation de HAProxy utilise une architecture modulaire qui sépare les différentes responsabilités en fichiers de configuration distincts. Cette approche facilite la maintenance, permet une meilleure organisation du code, et rend la configuration plus lisible et modulaire.

Cette architecture a été spécifiquement choisie pour faciliter l'ajout d'autres applications plus tard : chaque nouvelle application peut être ajoutée simplement en créant un nouveau fichier ACL dans acls/ et un nouveau fichier backend dans backends/, sans modifier les fichiers de configuration existants.

Cette section explique le flux de trafic, la structure des fichiers, et les exemples de configuration.

HAProxy fonctionne selon un modèle en trois étapes : les Frontends reçoivent les requêtes, les ACLs et le routage déterminent où diriger le trafic, et les Backends traitent les requêtes. Voici comment le trafic circule :

Architecture modulaire HAProxy

Frontend unifié : Un seul frontend (frontend-web-in.cfg) gère à la fois HTTP (port 80) et HTTPS (port 443), simplifiant la configuration.

ACLs & Routage : Règles de routage basées sur le hostname définies dans acls/*.cfg pour diriger le trafic vers les backends appropriés.

Backends : Serveurs applicatifs (127.0.0.1:port) définis dans backends/*.cfg qui traitent les requêtes et retournent les réponses.

Configuration modulaire : Global, Defaults, Frontend unifié, ACLs et Backends sont organisés en fichiers séparés pour faciliter la maintenance et l'ajout de nouvelles applications. Cette architecture permet d'ajouter une nouvelle application en créant simplement deux fichiers (un ACL et un backend) sans toucher aux configurations existantes.

bash
# Flux de trafic HAProxy
#
# 1. Frontend unifié (web-in)
#    - HTTP (port 80) : reçoit les requêtes non chiffrées
#    - HTTPS (port 443) : reçoit les requêtes chiffrées SSL/TLS
#    - Configuration des headers (X-Forwarded-*, HSTS, etc.)
#
# 2. ACLs & Routage (acls/*.cfg)
#    - Analyse du hostname (ex: devoups.elyamaje.com)
#    - Règles de routage basées sur le domaine
#    - Décision de redirection vers le bon backend
#
# 3. Backends (backends/*.cfg)
#    - Serveurs locaux (127.0.0.1:port)
#    - Traitement des requêtes et retour des réponses
#    - default-backend.cfg pour les domaines non configurés

La configuration HAProxy est organisée en fichiers modulaires dans le répertoire /etc/haproxy/conf.d/. Cette structure permet de séparer les responsabilités et facilite la maintenance.

Structure des fichiers de configuration

Chaque fichier a une responsabilité spécifique :

  • global.cfg : Paramètres globaux (logging, stats socket, SSL, etc.)
  • defaults.cfg : Valeurs par défaut pour tous les frontends/backends
  • frontend-web-in.cfg : Frontend unifié gérant HTTP (port 80) et HTTPS (port 443)
  • acls/ : ACLs et règles de routage par application
  • backends/ : Définitions des backends par application, avec default-backend.cfg en dernier

Avantage de cette structure : Pour ajouter une nouvelle application, il suffit de créer un fichier dans `acls/` (pour le routage) et un fichier dans `backends/` (pour la définition des serveurs), sans modifier les fichiers existants. Le playbook Ansible assemble automatiquement tous les fichiers lors de la génération de haproxy.cfg.

bash
# Structure des fichiers
/etc/haproxy/
├── haproxy.cfg                    # Fichier principal (assemblé automatiquement)
├── certs/                        # Certificats SSL (.pem)
├── errors/                       # Pages d'erreur personnalisées
└── conf.d/
    ├── global.cfg                 # Configuration globale
    ├── defaults.cfg               # Paramètres par défaut
    ├── maintenance.cfg            # Mode maintenance (optionnel)
    ├── stats.cfg                  # Interface statistiques (optionnel)
    ├── frontend-web-in.cfg        # Frontend unifié HTTP+HTTPS
    ├── acls/                      # ACLs par application
    │   ├── app1.cfg
    │   └── app2.cfg
    └── backends/                  # Backends par application
        ├── app1-backend.cfg
        ├── app2-backend.cfg
        └── default-backend.cfg    # Backend par défaut (toujours en dernier)

Le fichier principal haproxy.cfg est assemblé automatiquement par le playbook Ansible en concaténant les fichiers dans un ordre précis. L'ordre d'assemblage est crucial pour le bon fonctionnement de HAProxy.

Configuration principale (haproxy.cfg)

L'ordre d'assemblage est critique :

  1. global.cfg : Configuration globale (logging, stats socket, SSL)
  2. defaults.cfg : Valeurs par défaut pour tous les frontends/backends
  3. maintenance.cfg et stats.cfg : Configurations spéciales (optionnelles)
  4. frontend-web-in.cfg : Frontend unifié HTTP+HTTPS (optionnel)
  5. **acls/*.cfg** : ACLs et règles de routage par application
  6. **backends/*.cfg** : Backends par application (sauf default-backend.cfg)
  7. default-backend.cfg : Backend par défaut pour les domaines non configurés (toujours en dernier)

Note : Le fichier haproxy.cfg est généré automatiquement par le playbook Ansible. Ne le modifiez pas manuellement.

bash
# Ordre d'assemblage automatique de haproxy.cfg
# (géré par le playbook Ansible)

# 1. Configuration de base (toujours présents)
global.cfg
defaults.cfg

# 2. Configurations optionnelles (si elles existent)
maintenance.cfg    # Optionnel
stats.cfg          # Optionnel
frontend-web-in.cfg  # Optionnel

# 3. ACLs et routage (par application)
acls/*.cfg

# 4. Backends (par application, sauf default)
backends/*.cfg  # Exclut default-backend.cfg

# 5. Backend par défaut (toujours en dernier)
backends/default-backend.cfg

Notre architecture utilise un frontend unifié qui gère à la fois HTTP (port 80) et HTTPS (port 443) dans un seul fichier. Les ACLs et le routage sont définis dans les fichiers séparés du répertoire acls/.

Exemple : Configuration du frontend unifié (HTTP + HTTPS)

Points clés de cette configuration :

  • **bind *:80** : Écoute sur le port 80 (HTTP) pour toutes les interfaces
  • **bind *:443 ssl crt /etc/haproxy/certs/** : Écoute sur le port 443 (HTTPS) avec tous les certificats SSL
  • alpn http/1.1 : Support du protocole HTTP/1.1 via ALPN
  • Headers X-Forwarded-* : Transmission correcte des informations du client (IP, protocole)
  • Strict-Transport-Security : HSTS uniquement sur les connexions HTTPS (condition { ssl_fc })
  • default_backend : Backend par défaut pour les domaines non configurés
  • Les ACLs et règles de routage sont définies dans les fichiers acls/*.cfg pour une meilleure modularité
bash
# /etc/haproxy/conf.d/frontend-web-in.cfg

frontend web-in
    bind *:80
    bind *:443 ssl crt /etc/haproxy/certs/ alpn http/1.1
    mode http
    option httplog
    option forwardfor
    option http-server-close

    # Headers sécurisés: Configuration des en-têtes IP du client
    http-request add-header X-Real-IP %[src]
    http-request set-header X-Forwarded-Proto http  if !{ ssl_fc }
    http-request set-header X-Forwarded-Proto https if  { ssl_fc }
    http-request set-header HTTPS off if !{ ssl_fc }
    http-request set-header HTTPS on  if  { ssl_fc }
    http-request set-header X-Client-IP %[src]
    http-request set-header X-Forwarded-For %[src]

    # HSTS uniquement sur HTTPS
    http-response set-header Strict-Transport-Security "max-age=63072000; includeSubDomains; preload" if { ssl_fc }

    # Les ACLs et use_backend sont définis dans acls/*.cfg
    default_backend default_error_backend

Les ACLs et règles de routage sont définies dans des fichiers séparés dans le répertoire acls/. Chaque fichier correspond généralement à une application et contient les ACLs pour identifier le domaine et les règles use_backend pour diriger le trafic.

Exemple : Configuration d'une ACL et routage

Structure typique d'un fichier ACL :

  • acl : Définit une condition (ici, vérification du hostname)
  • use_backend : Dirige le trafic vers le backend spécifié si la condition ACL est vraie
  • Chaque application peut avoir son propre fichier ACL pour une meilleure organisation
bash
# /etc/haproxy/conf.d/acls/myapp.cfg

# ACL pour identifier le domaine
acl is_myapp hdr(host) -i myapp.example.com

# Routage vers le backend correspondant
use_backend myapp_backend if is_myapp

Les backends sont définis dans des fichiers séparés dans le répertoire backends/. Chaque backend correspond généralement à une application et définit les serveurs qui traitent les requêtes.

Exemple : Configuration d'un backend

Points clés d'un backend :

  • mode http : Mode HTTP (ou tcp pour TCP)
  • balance : Algorithme de répartition de charge (roundrobin, leastconn, etc.)
  • option httpchk : Vérification de santé HTTP (optionnel)
  • server : Définition des serveurs backend avec leur adresse et port
  • check : Active la vérification de santé du serveur
  • backup : Serveur de secours utilisé uniquement si les serveurs principaux sont indisponibles
bash
# /etc/haproxy/conf.d/backends/myapp-backend.cfg

backend myapp_backend
    mode http
    balance roundrobin
    option httpchk GET /health
    server app1 127.0.0.1:8080 check
    server app2 127.0.0.1:8081 check backup
⚙️

Installation et configuration

Guide complet pour installer et configurer HAProxy sur votre serveur

HAProxy est un load balancer et reverse proxy haute performance. Cette section vous guide à travers l'installation complète, la configuration initiale et la vérification du bon fonctionnement du service. Assurez-vous d'avoir les privilèges root (sudo) avant de commencer.

La première étape consiste à mettre à jour la liste des paquets et installer HAProxy ainsi que ses dépendances. Les paquets suivants sont nécessaires :

Installation de HAProxy et dépendances

  • haproxy : Le serveur HAProxy principal
  • ssl-cert : Utilitaires pour la gestion des certificats SSL
  • openssl : Bibliothèque cryptographique
  • certbot : Outil pour obtenir des certificats Let's Encrypt
  • cron : Pour automatiser le renouvellement des certificats
bash
sudo apt-get update -y
sudo apt-get install -y haproxy ssl-cert openssl certbot cron

HAProxy nécessite plusieurs répertoires pour fonctionner correctement. Le répertoire /etc/haproxy/certs contiendra vos certificats SSL, /run/haproxy est utilisé pour les sockets de communication, et /etc/haproxy/errors pour les pages d'erreur personnalisées.

Création des répertoires nécessaires

Les permissions 755 permettent la lecture et l'exécution par tous, mais seule la modification par root. C'est la configuration de sécurité recommandée.

bash
sudo mkdir -p /etc/haproxy/certs /run/haproxy /etc/haproxy/errors && \
sudo chmod 755 /etc/haproxy/certs /run/haproxy /etc/haproxy/errors && \
sudo chown root:root /etc/haproxy/certs /run/haproxy /etc/haproxy/errors

Une fois HAProxy installé, il faut activer le service pour qu'il démarre automatiquement au boot du système, puis le démarrer manuellement.

Activation et démarrage du service

La commande enable configure le service pour démarrer automatiquement. La commande start démarre le service immédiatement.

bash
sudo systemctl enable haproxy
sudo systemctl start haproxy

Après le démarrage, vérifiez que le service fonctionne correctement et consultez la version installée de HAProxy.

Vérification du statut

La première commande affiche l'état détaillé du service (actif, en erreur, etc.). La seconde affiche la version de HAProxy installée.

bash
sudo systemctl status haproxy
sudo haproxy -v

Avant de recharger ou redémarrer HAProxy, il est crucial de valider la syntaxe de votre fichier de configuration. Cette commande vérifie que la configuration est correcte sans redémarrer le service.

Validation de la configuration

Si la configuration est valide, vous verrez 'Configuration file is valid'. En cas d'erreur, le message indiquera la ligne et le type d'erreur.

bash
sudo haproxy -c -f /etc/haproxy/haproxy.cfg

Contrairement à restart, reload permet de recharger la configuration sans interrompre les connexions actives. C'est la méthode recommandée en production.

Recharger la configuration sans coupure

Cette commande est non-bloquante et n'interrompt pas les connexions existantes. Utilisez restart uniquement si reload ne fonctionne pas.

bash
sudo systemctl reload haproxy
📝

Gestion de la configuration

Commandes essentielles pour gérer et déboguer la configuration HAProxy

La gestion de la configuration HAProxy est un aspect crucial de son administration. Cette section couvre les commandes pour valider, déboguer et maintenir votre configuration. Il est recommandé de toujours valider la configuration avant de la déployer en production.

Cette commande valide la syntaxe de votre fichier de configuration sans modifier l'état du service. Elle est essentielle avant chaque déploiement.

Vérifier la syntaxe de la configuration

Retourne 'Configuration file is valid' si tout est correct, sinon affiche les erreurs de syntaxe avec leur emplacement.

bash
sudo haproxy -c -f /etc/haproxy/haproxy.cfg

Quand la validation échoue, cette commande fournit des informations de débogage plus détaillées pour identifier précisément les problèmes.

Voir les erreurs de configuration détaillées

Le mode -db (debug) affiche des messages d'erreur plus verbaux et détaillés pour faciliter le diagnostic.

bash
sudo haproxy -db -f /etc/haproxy/haproxy.cfg

Contrairement à reload, restart arrête complètement le service puis le redémarre. Cela interrompt toutes les connexions actives.

Redémarrer le service (avec coupure)

Utilisez restart uniquement si reload ne fonctionne pas ou si vous avez modifié des paramètres qui nécessitent un redémarrage complet.

bash
sudo systemctl restart haproxy

Les logs sont essentiels pour diagnostiquer les problèmes et surveiller l'activité de HAProxy. Cette commande affiche les logs en temps réel et se met à jour automatiquement.

Voir les logs en temps réel

Appuyez sur Ctrl+C pour quitter le mode suivi. Utilisez -n 100 pour voir les 100 dernières lignes au lieu du suivi en temps réel.

bash
sudo journalctl -u haproxy -f
🔒

Gestion SSL avec Let's Encrypt

Configuration complète des certificats SSL pour HAProxy, avec Let's Encrypt ou certificats auto-signés

La sécurisation des communications avec SSL/TLS est essentielle pour protéger les données en transit. Let's Encrypt offre des certificats gratuits et renouvelables automatiquement. Cette section vous guide à travers l'obtention d'un certificat, sa configuration pour HAProxy, et sa gestion. Notez que pour obtenir un certificat Let's Encrypt, votre domaine doit pointer vers le serveur et les ports 80 et 443 doivent être accessibles.

PRÉREQUIS - Création des répertoires et installation

Préparer l'environnement pour les certificats SSL. Remplacez 'domaine.elyamaje.com' par votre domaine.

bash
sudo mkdir -p /etc/haproxy/certs
sudo apt update && sudo apt install -y certbot
sudo chown -R root:root /etc/haproxy/certs
sudo chmod 755 /etc/haproxy/certs

Certbot doit utiliser le port 80 pour valider la propriété du domaine. C'est pourquoi nous arrêtons HAProxy temporairement. Le mode standalone fait que certbot écoute directement sur le port 80.

ÉTAPE 1 : Obtenir un certificat Let's Encrypt (remplacez le domaine)

Important : Remplacez 'domaine.elyamaje.com' par votre domaine réel et l'email par votre adresse. L'email est utilisé pour les notifications de renouvellement. Le certificat sera stocké dans /etc/letsencrypt/live/votre-domaine.com/

bash
sudo systemctl stop haproxy
sudo certbot certonly --standalone --non-interactive --agree-tos --email "equipe2elyamaje@gmail.com" -d "domaine.elyamaje.com"

HAProxy nécessite un fichier unique (.pem) contenant à la fois le certificat (fullchain.pem) et la clé privée (privkey.pem). L'ordre est important : d'abord le certificat, puis la clé.

ÉTAPE 2 : Combiner le certificat et la clé privée pour HAProxy

Alternative avec tee (plus sûr pour les permissions) : sudo bash -c 'cat /etc/letsencrypt/live/devoups.elyamaje.com/fullchain.pem /etc/letsencrypt/live/devoups.elyamaje.com/privkey.pem' | sudo tee /etc/haproxy/certs/devoups.elyamaje.com.pem > /dev/null

bash
sudo cat "/etc/letsencrypt/live/domaine.elyamaje.com/fullchain.pem" "/etc/letsencrypt/live/domaine.elyamaje.com/privkey.pem" > "/etc/haproxy/certs/domaine.elyamaje.com.pem"

Les certificats SSL contiennent des informations sensibles (clés privées). Il est crucial de restreindre les permissions pour éviter qu'ils soient lus par des utilisateurs non autorisés.

Sécuriser le fichier de certificat

Les permissions 600 (rw-------) permettent uniquement au propriétaire (root) de lire et écrire. Aucun autre utilisateur ne peut y accéder.

bash
sudo chmod 600 "/etc/haproxy/certs/domaine.elyamaje.com.pem"
sudo chown root:root "/etc/haproxy/certs/domaine.elyamaje.com.pem"

Avant de configurer le renouvellement automatique, testez-le avec --dry-run pour vérifier que tout fonctionne sans réellement renouveler le certificat.

Tester le renouvellement automatique

Simule le processus de renouvellement sans effectuer de changements réels. Idéal pour valider votre configuration cron.

bash
sudo certbot renew --dry-run

Les certificats Let's Encrypt expirent après 90 jours. Cette commande renouvelle tous les certificats qui approchent de l'expiration (moins de 30 jours restants par défaut).

Renouveler le certificat SSL

Attention : avec --force-renew, cette commande renouvellera le certificat même s'il n'est pas encore proche de l'expiration. À utiliser avec précaution.

bash
sudo certbot renew

Liste tous les certificats Let's Encrypt actuellement installés sur le serveur avec leurs informations de validité.

Voir les certificats installés

Affiche pour chaque certificat : le nom du domaine, le chemin des fichiers, la date d'expiration et le statut.

bash
sudo certbot certificates
🔐

Certificats SSL auto-signés (Alternative)

Créer un certificat SSL auto-signé pour le développement ou le test

Les certificats auto-signés sont utiles pour le développement, les tests, ou les environnements internes où vous n'avez pas besoin d'un certificat reconnu publiquement. Attention : les navigateurs afficheront un avertissement de sécurité pour ces certificats car ils ne sont pas signés par une autorité de certification reconnue. Ne les utilisez pas en production pour des sites publics.

Cette commande génère un certificat SSL auto-signé avec OpenSSL. Le certificat sera valide pendant 365 jours. Les paramètres -x509 et -nodes créent un certificat auto-signé sans protection par mot de passe de la clé privée.

Créer un certificat auto-signé (remplacez le domaine)

Paramètres importants :

  • -x509 : Génère un certificat auto-signé
  • -nodes : Pas de chiffrement de la clé privée (nécessaire pour HAProxy)
  • -days 365 : Validité de 1 an
  • -newkey rsa:2048 : Clé RSA de 2048 bits
  • -subj : Spécifie les informations du certificat (pays, état, organisation, nom commun)

Adaptez le sujet (-subj) selon vos besoins et remplacez 'domaine.elyamaje.com' par votre domaine.

bash
sudo openssl req -x509 -nodes -days 365 -newkey rsa:2048 -keyout "/etc/haproxy/certs/domaine.elyamaje.com.key" -out "/etc/haproxy/certs/domaine.elyamaje.com.crt" -subj "/C=FR/ST=France/L=Paris/O=ElyaMaje/CN=domaine.elyamaje.com"

Comme pour les certificats Let's Encrypt, HAProxy nécessite un fichier .pem unique contenant le certificat et la clé privée dans cet ordre.

Combiner le certificat et la clé pour HAProxy

L'ordre est crucial : d'abord le certificat (.crt), puis la clé privée (.key). Un mauvais ordre empêchera HAProxy de charger le certificat.

bash
sudo cat "/etc/haproxy/certs/domaine.elyamaje.com.crt" "/etc/haproxy/certs/domaine.elyamaje.com.key" > "/etc/haproxy/certs/domaine.elyamaje.com.pem"

Sécuriser et nettoyer les fichiers temporaires

Supprimer les fichiers temporaires après avoir créé le fichier .pem combiné.

bash
sudo chmod 600 "/etc/haproxy/certs/domaine.elyamaje.com.pem"
sudo chown root:root "/etc/haproxy/certs/domaine.elyamaje.com.pem"
sudo rm "/etc/haproxy/certs/domaine.elyamaje.com.key" "/etc/haproxy/certs/domaine.elyamaje.com.crt"
🔍

Vérification et test des certificats SSL

Outils et commandes pour vérifier et tester vos certificats SSL

Après avoir configuré un certificat SSL, il est important de vérifier qu'il est correctement installé et fonctionnel. Cette section fournit les outils pour inspecter les informations du certificat, valider la configuration HAProxy, et tester la connexion SSL depuis l'extérieur.

Inspectez les détails d'un certificat pour vérifier qu'il est correctement configuré, identifier son émetteur et vérifier sa période de validité.

Vérifier les informations du certificat

Affiche :

  • Subject : Le domaine pour lequel le certificat est émis
  • Issuer : L'autorité de certification (Let's Encrypt pour les certificats Let's Encrypt)
  • Not Before/After : Les dates de validité du certificat
bash
sudo openssl x509 -in "/etc/haproxy/certs/devoups.elyamaje.com.pem" -text -noout | grep -E "(Subject:|Issuer:|Not Before:|Not After:)"

Après avoir configuré un nouveau certificat SSL, il est essentiel de valider la configuration HAProxy avant de redémarrer le service pour éviter une interruption de service.

Vérifier la configuration HAProxy avant redémarrage

Ces trois commandes en séquence :

  1. Valident la syntaxe de la configuration
  2. Démarrant HAProxy si la validation réussit
  3. Affichent le statut détaillé pour confirmer que le service fonctionne
bash
sudo haproxy -c -f /etc/haproxy/haproxy.cfg
sudo systemctl start haproxy
sudo systemctl status haproxy --no-pager -l

Teste la connexion SSL/TLS depuis l'extérieur pour vérifier que le certificat est correctement configuré et que le serveur répond correctement sur le port 443.

Tester la connexion SSL

Cette commande simule une connexion SSL client et affiche les informations du certificat présenté par le serveur. Remplacez 'domaine.elyamaje.com' par votre domaine. Le paramètre -servername est important pour SNI (Server Name Indication).

bash
openssl s_client -connect domaine.elyamaje.com:443 -servername domaine.elyamaje.com < /dev/null