Aller au contenu
medium

HAProxy : load balancing et haute disponibilité

29 min de lecture

logo haproxy

Ce guide vous permet de déployer HAProxy pour répartir le trafic HTTP entre plusieurs serveurs backend. Vous apprendrez à configurer le load balancing round-robin, les health checks automatiques, les sticky sessions et la protection contre les abus. À la fin, vous disposerez d’un reverse proxy prêt pour la production.

Public cible : administrateurs système, DevOps, développeurs souhaitant améliorer la disponibilité de leurs applications.

Prérequis : un système Linux (Ubuntu/Debian) avec accès root, et au moins deux serveurs backend (ou containers Docker).

HAProxy (High Availability Proxy) est un répartiteur de charge (load balancer) et reverse proxy open source. Créé en 2000 par Willy Tarreau, il est utilisé à grande échelle en production pour gérer des millions de connexions simultanées.

Analogie : imaginez un standardiste téléphonique qui reçoit tous les appels entrants et les distribue aux différents opérateurs disponibles. HAProxy joue ce rôle pour vos serveurs web : il reçoit les requêtes des utilisateurs et les répartit intelligemment entre vos serveurs.

Pourquoi utiliser HAProxy ?

Sans HAProxyAvec HAProxy
Un seul serveur reçoit tout le traficLe trafic est réparti entre plusieurs serveurs
Si le serveur tombe, le site est indisponibleLe trafic bascule automatiquement vers les serveurs sains
Pas de protection contre les pics de chargeGestion des files d’attente et rate limiting
Configuration SSL sur chaque serveurTerminaison SSL centralisée

Ce guide utilise HAProxy 3.2.5, la branche stable qui bénéficie de l’audit de sécurité ANSSI/Almond ITSEF.

Pour une installation sécurisée, compilez depuis les sources officielles téléchargées sur haproxy.org :

  1. Installez les dépendances de compilation :

    Fenêtre de terminal
    sudo apt install -y build-essential libssl-dev libpcre2-dev zlib1g-dev liblua5.4-dev
  2. Téléchargez et extrayez les sources :

    Fenêtre de terminal
    cd /tmp
    curl -LO https://www.haproxy.org/download/3.2/src/haproxy-3.2.5.tar.gz
    tar xzf haproxy-3.2.5.tar.gz
    cd haproxy-3.2.5
  3. Compilez avec les options recommandées :

    Fenêtre de terminal
    make -j$(nproc) TARGET=linux-glibc USE_OPENSSL=1 USE_PCRE2=1 USE_ZLIB=1 USE_LUA=1 USE_PROMEX=1

    Options de compilation :

    • USE_OPENSSL=1 : support TLS
    • USE_PCRE2=1 : expressions régulières performantes
    • USE_ZLIB=1 : compression HTTP
    • USE_LUA=1 : scripting Lua
    • USE_PROMEX=1 : exporteur Prometheus intégré
  4. Installez :

    Fenêtre de terminal
    sudo make install PREFIX=/usr/local
  5. Vérifiez l’installation :

    Fenêtre de terminal
    /usr/local/sbin/haproxy -v

    Vous devriez voir :

    HAProxy version 3.2.5-ba0fd6b 2025/09/23 - https://haproxy.org/
    Status: long-term supported branch - will stop receiving fixes around Q2 2030.

Avant de configurer HAProxy, comprenons les briques fondamentales de son architecture.

HAProxy utilise trois types de blocs de configuration :

BlocRôleAnalogie
frontendPoint d’entrée qui reçoit les connexions clientsL’accueil d’un hôtel
backendGroupe de serveurs qui traitent les requêtesLes chambres disponibles
listenCombine frontend + backend en un seul blocUn hôtel simple avec accueil intégré

Architecture HAProxy : Frontend répartit les requêtes vers les serveurs Backend

HAProxy propose plusieurs méthodes pour distribuer le trafic :

AlgorithmeDescriptionCas d’usage
roundrobinDistribue les requêtes à tour de rôleServeurs identiques, charge équilibrée
leastconnEnvoie vers le serveur avec le moins de connexionsRequêtes longues (téléchargements, WebSocket)
sourceHash basé sur l’IP source (sticky)Affinité de session sans cookie
uriHash basé sur l’URICache distribué
randomSélection aléatoireSimple et efficace à grande échelle

Les ACLs permettent de prendre des décisions de routage basées sur des conditions :

acl is_api path_beg /api # Vrai si le chemin commence par /api
acl is_admin hdr(host) -i admin.example.com # Vrai si Host = admin...
use_backend api_servers if is_api
use_backend admin_servers if is_admin
default_backend web_servers

Types de conditions courantes :

ConditionDescription
path_beg /apiLe chemin commence par “/api”
path_end .jpgLe chemin finit par “.jpg”
hdr(host) -i example.comL’en-tête Host vaut “example.com”
src 192.168.1.0/24L’IP source est dans ce sous-réseau

Les health checks vérifient automatiquement que vos serveurs backend fonctionnent :

  • TCP check : vérifie que le port répond (par défaut)
  • HTTP check : envoie une requête HTTP et attend un code 200
  • Si un serveur ne répond pas, HAProxy le retire automatiquement du pool

Maintenant que vous comprenez les concepts, passons à la pratique. Le fichier de configuration principal est /etc/haproxy/haproxy.cfg. La configuration ci-dessous est un point de départ fonctionnel que vous pouvez copier, puis adapter à votre infrastructure.

Ce que fait cette configuration :

  • Écoute sur le port 80 (HTTP)
  • Répartit le trafic entre deux serveurs web (192.168.1.10 et 192.168.1.11)
  • Vérifie automatiquement que les serveurs répondent (health checks)
  • Fournit une page de statistiques sécurisée sur le port 8404
/etc/haproxy/haproxy.cfg
global
log /dev/log local0
log /dev/log local1 notice
maxconn 4096
user haproxy
group haproxy
daemon
defaults
mode http
log global
option httplog
option dontlognull
timeout connect 5s
timeout client 30s
timeout server 30s
timeout http-request 10s
# Page de statistiques (sécurisée)
listen stats
bind 127.0.0.1:8404
stats enable
stats uri /stats
stats refresh 10s
stats show-legends
stats auth admin:CHANGEZ_CE_MOT_DE_PASSE
# Frontend HTTP
frontend http_front
bind *:80
default_backend web_backend
# Backend avec load balancing
backend web_backend
balance roundrobin
option httpchk
http-check send meth GET uri /health
http-check expect status 200
server web1 192.168.1.10:80 check
server web2 192.168.1.11:80 check

Avant d’appliquer une configuration, toujours la valider :

Fenêtre de terminal
# Vérifie la syntaxe
sudo haproxy -c -f /etc/haproxy/haproxy.cfg

Si aucune erreur n’est affichée, la configuration est valide.

Fenêtre de terminal
# Démarrer le service
sudo systemctl enable haproxy
sudo systemctl start haproxy
# Vérifier le statut
sudo systemctl status haproxy

Testez que le load balancing fonctionne :

Fenêtre de terminal
# Envoyez plusieurs requêtes
for i in {1..4}; do curl -s http://localhost/ | head -1; done

Vous devriez voir les réponses alterner entre vos backends.

Accédez à la page de statistiques : http://votre-ip:8404/stats

La configuration de base fonctionne pour la plupart des sites statiques. Mais dès que votre application devient plus complexe, vous aurez besoin de fonctionnalités avancées. Voyons les cas les plus courants.

Le problème : imaginez un site e-commerce où l’utilisateur ajoute des articles à son panier. Si la première requête va vers le serveur A (qui stocke le panier), mais que la deuxième va vers le serveur B… le panier apparaît vide ! C’est frustrant pour l’utilisateur.

La solution : les sticky sessions garantissent qu’un utilisateur est toujours renvoyé vers le même serveur backend. HAProxy utilise un cookie pour “se souvenir” du serveur assigné à chaque visiteur.

Fenêtre de terminal
backend web_backend
balance roundrobin
cookie SERVERID insert indirect nocache
server web1 192.168.1.10:80 check cookie web1
server web2 192.168.1.11:80 check cookie web2

Comment ça fonctionne :

  1. À la première connexion, HAProxy choisit un serveur (ex: web1)
  2. Il ajoute un cookie SERVERID=web1 dans la réponse
  3. Les requêtes suivantes avec ce cookie vont toujours vers web1

Vérification :

Fenêtre de terminal
# Première requête : récupère le cookie
curl -c cookies.txt http://localhost/
# Requêtes suivantes : utilise le cookie (même serveur)
curl -b cookies.txt http://localhost/
curl -b cookies.txt http://localhost/

Le problème : votre application a plusieurs composants — une API, des fichiers statiques, des WebSockets — chacun sur des serveurs différents. Comment diriger chaque type de requête vers le bon groupe de serveurs ?

La solution : utilisez des ACLs (règles de filtrage) pour analyser l’URL et router intelligemment. C’est comme un aiguillage ferroviaire : selon la destination inscrite sur le billet (l’URL), le train (la requête) est envoyé sur la bonne voie.

Fenêtre de terminal
frontend http_front
bind *:80
# Définition des ACLs
acl is_api path_beg /api
acl is_static path_beg /static /images /css /js
acl is_websocket hdr(Upgrade) -i WebSocket
# Validation du Host (whitelist)
acl valid_host hdr(host) -i example.com www.example.com api.example.com
http-request deny deny_status 400 unless valid_host
# Routage vers les backends appropriés
use_backend api_backend if is_api
use_backend static_backend if is_static
use_backend websocket_backend if is_websocket
default_backend web_backend

Le problème : un serveur peut être “debout” (le processus tourne) mais “malade” (la base de données est déconnectée, le disque est plein…). Un simple check TCP ne détecte pas ces situations.

La solution : configurez des health checks HTTP qui appellent un endpoint /health de votre application. Cet endpoint vérifie que tout fonctionne (DB, cache, espace disque…) et renvoie un code 200 si OK. HAProxy retire automatiquement les serveurs qui ne répondent pas correctement.

Fenêtre de terminal
backend web_backend
balance roundrobin
# Active les health checks HTTP (syntaxe HAProxy 3.x)
option httpchk
http-check send meth GET uri /health ver HTTP/1.1 hdr Host localhost
# Attend un code 200
http-check expect status 200
# Ou vérifie le contenu de la réponse
# http-check expect string "status":"healthy"
# Paramètres des checks
server web1 192.168.1.10:80 check inter 5s fall 3 rise 2
server web2 192.168.1.11:80 check inter 5s fall 3 rise 2

Paramètres des serveurs :

ParamètreDescription
checkActive les health checks
inter 5sIntervalle entre les checks (5 secondes)
fall 3Nombre d’échecs avant de considérer le serveur DOWN
rise 2Nombre de succès pour remettre le serveur UP

Le problème : chaque serveur backend doit gérer son propre certificat SSL, ce qui complique le renouvellement et consomme des ressources CPU pour le chiffrement.

La solution : HAProxy devient le point unique de terminaison SSL. Il déchiffre les requêtes HTTPS entrantes, puis les transmet en HTTP simple (ou HTTPS) vers vos backends. Avantages :

  • Un seul certificat à gérer
  • Vos backends sont allégés
  • Renouvellement centralisé (Let’s Encrypt, etc.)
Fenêtre de terminal
frontend https_front
bind *:443 ssl crt /etc/haproxy/certs/site.pem alpn h2,http/1.1
bind *:80
# Redirige HTTP vers HTTPS
http-request redirect scheme https unless { ssl_fc }
# Ajoute l'en-tête X-Forwarded-Proto
http-request set-header X-Forwarded-Proto https if { ssl_fc }
default_backend web_backend

Pourquoi durcir TLS ? Les protocoles et algorithmes de chiffrement évoluent. Ce qui était sécurisé en 2015 (TLS 1.0, SHA-1) est aujourd’hui vulnérable. La configuration ci-dessous applique les bonnes pratiques 2026 :

  • TLS 1.2 minimum : désactive les versions obsolètes (1.0, 1.1)
  • Suites modernes : uniquement AES-GCM et ChaCha20 (rapides et sécurisés)
  • Courbes elliptiques sûres : X25519, P-256, P-384

Ajoutez ces paramètres dans la section global de votre configuration :

Fenêtre de terminal
global
# TLS : version minimale et suites modernes
ssl-default-bind-options ssl-min-ver TLSv1.2 no-tls-tickets
ssl-default-bind-ciphersuites TLS_AES_128_GCM_SHA256:TLS_AES_256_GCM_SHA384:TLS_CHACHA20_POLY1305_SHA256
ssl-default-bind-ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384
# Courbes elliptiques sécurisées
ssl-default-bind-curves X25519:P-256:P-384
# Mêmes paramètres côté serveur (si re-chiffrement vers backends HTTPS)
ssl-default-server-options ssl-min-ver TLSv1.2 no-tls-tickets
ssl-default-server-ciphersuites TLS_AES_128_GCM_SHA256:TLS_AES_256_GCM_SHA384:TLS_CHACHA20_POLY1305_SHA256

HAProxy est en première ligne face à Internet. C’est à la fois un risque (point d’entrée unique) et une opportunité (point de contrôle centralisé). Voyons comment le sécuriser.

Le problème : un attaquant ou un bot peut envoyer des milliers de requêtes par seconde, saturant vos serveurs et rendant le site inaccessible pour les vrais utilisateurs.

La solution : le rate limiting compte les requêtes de chaque IP et bloque celles qui dépassent un seuil raisonnable. C’est comme un videur de boîte de nuit qui refuse l’entrée aux personnes qui essaient d’entrer trop souvent.

Attention : des limites trop strictes peuvent bloquer des utilisateurs légitimes (plusieurs personnes derrière le même NAT d’entreprise). Commencez avec des valeurs conservatrices et ajustez selon vos logs.

Fenêtre de terminal
frontend http_front
bind *:80
# Table de suivi des requêtes par IP
stick-table type ip size 100k expire 30s store http_req_rate(10s)
# Comptabilise les requêtes par IP
http-request track-sc0 src
# Bloque si plus de 50 requêtes en 10 secondes
http-request deny deny_status 429 if { sc_http_req_rate(0) gt 50 }
default_backend web_backend

Explication :

  • stick-table : crée une table pour stocker les compteurs par IP
  • track-sc0 : associe chaque requête à son IP source
  • deny_status 429 : renvoie “Too Many Requests” si la limite est dépassée

Le problème : les navigateurs modernes proposent des protections contre le clickjacking, le XSS, le MIME sniffing… mais ces protections ne sont activées que si le serveur envoie les bons en-têtes HTTP.

La solution : configurez HAProxy pour ajouter automatiquement ces en-têtes de sécurité à toutes les réponses. C’est un gain rapide en sécurité, sans modification de vos applications.

Ce que fait chaque en-tête :

En-têteProtection apportée
Strict-Transport-SecurityForce HTTPS pendant 1 an (empêche le downgrade HTTP)
X-Frame-OptionsEmpêche l’intégration de votre site dans une iframe (anti-clickjacking)
X-Content-Type-OptionsEmpêche le navigateur de “deviner” le type MIME
Content-Security-PolicyContrôle quelles ressources peuvent être chargées
Fenêtre de terminal
frontend https_front
bind *:443 ssl crt /etc/haproxy/certs/site.pem
# Headers de sécurité
http-response set-header Strict-Transport-Security "max-age=31536000; includeSubDomains; preload"
http-response set-header X-Frame-Options "SAMEORIGIN"
http-response set-header X-Content-Type-Options "nosniff"
http-response set-header Referrer-Policy "strict-origin-when-cross-origin"
http-response set-header Permissions-Policy "geolocation=(), microphone=(), camera=()"
# CSP basique - adaptez selon votre application
http-response set-header Content-Security-Policy "default-src 'self'; script-src 'self'; style-src 'self' 'unsafe-inline'; img-src 'self' data: https:; font-src 'self'; frame-ancestors 'self'"
default_backend web_backend

Le problème : vous identifiez des IPs qui attaquent votre site (brute force, scraping abusif, spam). Vous voulez les bloquer avant qu’elles n’atteignent vos backends.

La solution : créez une liste noire d’IPs dans un fichier externe. HAProxy consulte cette liste à chaque requête et rejette celles qui correspondent. Le fichier peut être mis à jour sans recharger HAProxy (avec reload).

Fenêtre de terminal
frontend http_front
bind *:80
# Liste noire d'IPs (fichier externe)
acl blocked_ips src -f /etc/haproxy/blocked_ips.txt
http-request deny if blocked_ips
default_backend web_backend

Contenu de /etc/haproxy/blocked_ips.txt :

192.168.1.100
10.0.0.0/8

Une infrastructure sans monitoring, c’est conduire de nuit sans phares. HAProxy offre plusieurs outils pour voir ce qui se passe en temps réel et diagnostiquer les problèmes.

Ce que vous voyez : la page de stats intégrée est un tableau de bord visuel qui montre l’état de votre infrastructure en un coup d’œil. Chaque backend est affiché avec un code couleur (vert = UP, rouge = DOWN, orange = en transition).

Informations disponibles :

  • Nombre de connexions actives et totales
  • Taux de requêtes par seconde
  • Temps de réponse moyen des backends
  • État de chaque serveur (UP/DOWN/DRAIN)
  • Historique des erreurs
Fenêtre de terminal
listen stats
bind 127.0.0.1:8404
stats enable
stats uri /stats
stats refresh 10s
stats show-legends
stats show-node
stats auth admin:MOT_DE_PASSE_SECURISE

Accédez à http://localhost:8404/stats via tunnel SSH pour voir :

  • L’état de chaque backend (UP/DOWN)
  • Le nombre de connexions actives
  • Les taux de requêtes
  • Les temps de réponse

Le problème : les logs texte traditionnels sont difficiles à parser et analyser à grande échelle. Chaque outil (grep, awk, Elasticsearch) doit “comprendre” le format.

La solution : HAProxy 3.2 permet de formater les logs directement en JSON. Chaque champ est clairement identifié, ce qui facilite l’ingestion dans des outils comme Elasticsearch, Loki ou Datadog.

Fenêtre de terminal
defaults
mode http
log-format "%{+json}o %(client_ip)ci %(status)ST %(bytes)B %(duration)Ta %(backend)b %(server)s"

Pourquoi Prometheus ? C’est le standard de facto pour le monitoring en environnement Kubernetes/cloud-native. HAProxy peut exposer ses métriques au format Prometheus, permettant de créer des dashboards Grafana et des alertes automatiques.

Ce que vous pouvez monitorer : connexions actives, requêtes par seconde, latence moyenne, erreurs 5xx, état des backends…

Fenêtre de terminal
frontend prometheus
bind *:8405
http-request use-service prometheus-exporter if { path /metrics }
stats enable
stats uri /stats

Configurez ensuite Prometheus pour scraper http://haproxy:8405/metrics.

Même avec une configuration soignée, des problèmes peuvent survenir. Cette section vous aide à diagnostiquer et résoudre les situations les plus fréquentes.

Comment lire ce tableau : identifiez le symptôme que vous observez, puis appliquez la solution correspondante.

SymptômeCause probableSolution
”bind: cannot bind socket”Port déjà utiliséVérifiez avec ss -tlnp | grep 80
Serveur DOWN dans les statsHealth check échoueVérifiez que l’endpoint /health répond 200
Pas de load balancingUn seul serveur UPVérifiez les health checks des autres serveurs
Erreur 503Tous les serveurs DOWNVérifiez la connectivité réseau aux backends
Cookie de session qui changeMauvaise config cookieVérifiez le paramètre cookie sur chaque server

Gardez cette section sous la main : ce sont les commandes que vous utiliserez le plus souvent en production. Copiez-les dans un wiki d’équipe ou un runbook Notion.

Fenêtre de terminal
# Validation complète de la configuration (avec warnings)
sudo haproxy -c -V -f /etc/haproxy/haproxy.cfg
# Recharger sans interruption (hitless reload avec seamless)
sudo systemctl reload haproxy
# Reload manuel avec socket master-worker (zero downtime)
echo "reload" | sudo socat stdio /run/haproxy/admin.sock
# Voir les logs en temps réel
sudo journalctl -u haproxy -f
# Vérifier les ports d'écoute
ss -tlnp | grep haproxy
# Tester une requête avec verbose
curl -v http://localhost/

Le problème : recharger HAProxy pour chaque petite modification (maintenance d’un serveur, debug) peut être lourd et risqué en production.

La solution : le socket d’administration permet d’interagir avec HAProxy en temps réel, sans toucher à la configuration ni recharger le service. C’est comme avoir une console d’administration cachée.

Fenêtre de terminal
# Activer le socket dans la section global
global
stats socket /run/haproxy/admin.sock mode 660 level admin
stats timeout 30s
# Exemples d'utilisation
# Voir l'état des backends
echo "show stat" | sudo socat stdio /run/haproxy/admin.sock
# Désactiver temporairement un serveur (maintenance)
echo "disable server web_backend/web1" | sudo socat stdio /run/haproxy/admin.sock
# Réactiver le serveur
echo "enable server web_backend/web1" | sudo socat stdio /run/haproxy/admin.sock
# Voir les sessions actives
echo "show sess" | sudo socat stdio /run/haproxy/admin.sock

Quand l’utiliser : votre configuration est valide (haproxy -c passe) mais quelque chose ne fonctionne pas comme prévu. Le mode diagnostic affiche des avertissements supplémentaires sur les directives suspectes ou obsolètes.

Fenêtre de terminal
haproxy -dD -f /etc/haproxy/haproxy.cfg

Cette option signale les directives problématiques sans empêcher le démarrage.

  1. HAProxy est un reverse proxy et load balancer qui répartit le trafic entre plusieurs serveurs pour assurer haute disponibilité et performance.

  2. Les blocs frontend/backend séparent la réception du trafic (frontend) de sa distribution (backend).

  3. Les health checks retirent automatiquement les serveurs défaillants du pool — toujours les activer avec check.

  4. Les sticky sessions (cookies) maintiennent l’affinité client-serveur pour les applications avec état.

  5. Le rate limiting protège vos backends contre les abus — configurez une stick-table avec des limites raisonnables.

  6. Validez toujours la configuration avec haproxy -c avant de recharger.

  7. La page de statistiques (port 8404) donne une vue temps réel de l’état de votre infrastructure.

Ce site vous est utile ?

Sachez que moins de 1% des lecteurs soutiennent ce site.

Je maintiens +700 guides gratuits, sans pub ni tracing. Aujourd'hui, ce site ne couvre même pas mes frais d'hébergement, d'électricité, de matériel, de logiciels, mais surtout de cafés.

Un soutien régulier, même symbolique, m'aide à garder ces ressources gratuites et à continuer de produire des guides de qualité. Merci pour votre appui.

Abonnez-vous et suivez mon actualité DevSecOps sur LinkedIn