Introduction
Lorsqu'un seul serveur ne suffit plus pour encaisser la charge, on passe au load balancing : un proxy frontal distribue les requêtes vers plusieurs backends. HAProxy est le load balancer de référence open-source.
Cas d'usage :
- Site web → 3 serveurs Nginx en backend, basculement auto si l'un tombe
- API → distribution round-robin avec sticky sessions
- Base de données → load balancing read replicas MySQL/PostgreSQL
- Terminaison SSL centralisée + healthchecks avancés
Prérequis
- VPS Linux dédié au load balancer (Debian 12 / Ubuntu 22.04+)
- Au moins 2 serveurs backend déjà en place
- Un nom de domaine (optionnel mais recommandé)
Étape 1 : Installation
sudo apt update
sudo apt install -y haproxy
sudo systemctl enable --now haproxy
sudo systemctl status haproxy
Version recommandée : HAProxy 2.8+ (LTS).
Étape 2 : Architecture cible
┌──────────────┐
Clients ────────▶│ HAProxy │
│ (VPS LB) │
└──────┬───────┘
│
┌────────────┼────────────┐
▼ ▼ ▼
┌─────────┐ ┌─────────┐ ┌─────────┐
│ Web 1 │ │ Web 2 │ │ Web 3 │
│ 10.0.0.10│ │10.0.0.11│ │10.0.0.12│
└─────────┘ └─────────┘ └─────────┘
Les backends communiquent en privé (idéalement via un réseau privé entre VPS, ou via WireGuard).
Étape 3 : Config minimale (HTTP)
sudo nano /etc/haproxy/haproxy.cfg
global
log /dev/log local0
log /dev/log local1 notice
chroot /var/lib/haproxy
stats socket /run/haproxy/admin.sock mode 660 level admin
stats timeout 30s
user haproxy
group haproxy
daemon
maxconn 50000
# SSL moderne
ssl-default-bind-ciphers ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384
ssl-default-bind-options ssl-min-ver TLSv1.2 no-tls-tickets
defaults
log global
mode http
option httplog
option dontlognull
option http-keep-alive
option forwardfor
timeout connect 5s
timeout client 60s
timeout server 60s
timeout http-request 10s
timeout http-keep-alive 15s
maxconn 50000
# Stats UI (interne)
listen stats
bind 127.0.0.1:8404
stats enable
stats uri /
stats refresh 10s
stats auth admin:UnMotDePasseFort
# Frontend
frontend http_front
bind *:80
default_backend web_servers
# Backend
backend web_servers
balance roundrobin
option httpchk GET /health
http-check expect status 200
server web1 10.0.0.10:80 check inter 2000 rise 2 fall 3
server web2 10.0.0.11:80 check inter 2000 rise 2 fall 3
server web3 10.0.0.12:80 check inter 2000 rise 2 fall 3
Détails importants :
balance roundrobin: distribution équitable. Autres :leastconn(moins de connexions actives),source(sticky par IP)option httpchk GET /health: healthcheck sur/health(votre app doit répondre 200)check inter 2000 rise 2 fall 3: check toutes les 2s, considéré up après 2 succès, down après 3 échecs
Validez la config :
sudo haproxy -c -f /etc/haproxy/haproxy.cfg
Rechargez :
sudo systemctl reload haproxy
Étape 4 : Implémenter l'endpoint healthcheck côté backend
Sur chaque serveur backend, ajoutez un endpoint /health qui retourne 200 si l'app va bien :
Nginx
server {
location = /health {
access_log off;
return 200 "OK";
add_header Content-Type text/plain;
}
}
Node.js
app.get('/health', (req, res) => {
res.status(200).send('OK');
});
Plus avancé : vérifiez aussi MySQL et Redis dans le healthcheck pour ne pas router vers un backend dont la DB est down.
Étape 5 : Stats UI
Ouvrez http://127.0.0.1:8404 dans un tunnel SSH :
ssh -L 8404:127.0.0.1:8404 user@IP_DU_VPS_HAPROXY
Puis http://localhost:8404 dans votre navigateur. Identifiants : admin / UnMotDePasseFort.
Vous voyez :
- État des backends (UP/DOWN, en vert/rouge)
- Statistiques par serveur
- Charges en temps réel
Étape 6 : Ajouter le SSL (terminaison)
HAProxy peut terminer le SSL et discuter en HTTP avec les backends (architecture courante).
Préparer le certificat
Avec Let's Encrypt :
sudo apt install -y certbot
sudo systemctl stop haproxy
sudo certbot certonly --standalone -d votre-domaine.com
sudo systemctl start haproxy
Combinez le cert + key dans un seul fichier pour HAProxy :
sudo bash -c "cat /etc/letsencrypt/live/votre-domaine.com/fullchain.pem /etc/letsencrypt/live/votre-domaine.com/privkey.pem > /etc/ssl/haproxy.pem"
sudo chmod 600 /etc/ssl/haproxy.pem
Modifier la config
frontend https_front
bind *:80
bind *:443 ssl crt /etc/ssl/haproxy.pem alpn h2,http/1.1
# Force HTTPS
http-request redirect scheme https unless { ssl_fc }
# HSTS
http-response set-header Strict-Transport-Security "max-age=31536000; includeSubDomains"
default_backend web_servers
Rechargez :
sudo systemctl reload haproxy
Étape 7 : Renouvellement auto SSL avec hook
Pour que Let's Encrypt renouvelle sans casser HAProxy :
sudo nano /etc/letsencrypt/renewal-hooks/deploy/haproxy.sh
#!/bin/bash
DOMAIN=votre-domaine.com
cat /etc/letsencrypt/live/${DOMAIN}/fullchain.pem /etc/letsencrypt/live/${DOMAIN}/privkey.pem > /etc/ssl/haproxy.pem
chmod 600 /etc/ssl/haproxy.pem
systemctl reload haproxy
sudo chmod +x /etc/letsencrypt/renewal-hooks/deploy/haproxy.sh
Étape 8 : Algorithmes de load balancing
Selon votre cas :
backend web_servers
# Round-robin (par défaut)
balance roundrobin
# Least connections
balance leastconn
# Source IP hashing (sticky session naturelle)
balance source
# URI hashing (cache-friendly)
balance uri
# Sticky session via cookie
cookie SERVERID insert indirect nocache
server web1 10.0.0.10:80 cookie web1 check
server web2 10.0.0.11:80 cookie web2 check
Étape 9 : ACLs (routage avancé)
Routez par URL, header ou IP :
frontend https_front
bind *:443 ssl crt /etc/ssl/haproxy.pem
# Routage par path
acl is_api path_beg /api
acl is_admin path_beg /admin
# Routage par hostname
acl host_blog hdr(host) -i blog.votre-domaine.com
# Routage par IP (limiter /admin)
acl admin_whitelist src 82.26.157.10
# Apply
use_backend api_servers if is_api
use_backend admin_servers if is_admin admin_whitelist
use_backend blog_servers if host_blog
default_backend web_servers
Étape 10 : Load balancing TCP (MySQL, Redis, SSH)
HAProxy peut aussi load-balancer des protocoles TCP (mode tcp) :
frontend mysql_front
bind *:3306
mode tcp
default_backend mysql_servers
backend mysql_servers
mode tcp
balance leastconn
option mysql-check user haproxy_check
server db1 10.0.0.20:3306 check
server db2 10.0.0.21:3306 check backup # backup = utilisé si db1 down
Étape 11 : Limiter les connexions (anti-flood)
frontend https_front
bind *:443 ssl crt /etc/ssl/haproxy.pem
# Stick table (compteur par IP)
stick-table type ipv6 size 100k expire 30s store conn_rate(10s),http_req_rate(10s)
# Limites
http-request track-sc0 src
http-request reject if { sc_conn_rate(0) gt 50 } # > 50 connexions/10s = blocage
http-request reject if { sc_http_req_rate(0) gt 200 } # > 200 req/10s = blocage
Étape 12 : Logs et monitoring
# Logs en temps réel
sudo tail -f /var/log/haproxy.log
# Erreurs uniquement
sudo grep -i error /var/log/haproxy.log
# Top backends par requêtes
sudo awk '{print $7}' /var/log/haproxy.log | sort | uniq -c | sort -rn | head -10
Pour du monitoring continu : voir le tuto Prometheus + Grafana avec haproxy_exporter.
Dépannage
"no backend available"
Tous vos backends sont marqués DOWN. Vérifiez les healthchecks :
curl http://10.0.0.10/health
Doit retourner 200 OK.
"503 Service Unavailable"
Soit aucun backend disponible, soit timeout server trop court. Augmentez timeout server.
SSL handshake errors
Le fichier .pem est mal formé. Régénérez :
cat fullchain.pem privkey.pem > haproxy.pem
L'ordre compte : chain puis key.
Stats UI pas accessible
Vérifiez que le port 8404 n'est pas bloqué par UFW. Préférez tunneling SSH plutôt qu'exposer.
Commandes utiles
# Tester la config
sudo haproxy -c -f /etc/haproxy/haproxy.cfg
# Recharger (zero downtime)
sudo systemctl reload haproxy
# Voir les sockets actifs
sudo socat /run/haproxy/admin.sock - <<< "show info"
# Désactiver un serveur (maintenance)
sudo socat /run/haproxy/admin.sock - <<< "disable server web_servers/web1"
# Réactiver
sudo socat /run/haproxy/admin.sock - <<< "enable server web_servers/web1"
# Voir l'état des backends
sudo socat /run/haproxy/admin.sock - <<< "show servers state"
# Reset des stats
sudo socat /run/haproxy/admin.sock - <<< "clear counters"
Conclusion
Avec HAProxy en frontal :
- Votre infra tolère la panne d'un backend (failover auto)
- Vous distribuez la charge entre N serveurs
- Vous centralisez la terminaison SSL
- Vous protégez contre le flood applicatif
Pour aller plus loin :
- Mettez deux HAProxy en HA avec keepalived (failover de l'IP virtuelle)
- Utilisez HAProxy Data Plane API pour pilotage automatisé
- Migrez vers Traefik si vous voulez du service discovery Docker/Kubernetes natif
Ressources
- Site officiel : https://www.haproxy.org
- Documentation : https://docs.haproxy.org
- Configuration manual : https://docs.haproxy.org/2.8/configuration.html


















