Publié le : 05/12/2024 à 10:00 Mis à jour le : 19/06/2026 à 18:43 Vues : 566

Comprendre la structure d'un fichier haproxy.cfg : sections Global, Defaults, Frontend et Backend, ainsi que la gestion des inclusions et du rechargement à chaud.

1. Les blocs de configuration

Le fichier haproxy.cfg est structuré en plusieurs sections (Global, Defaults, Frontend, Backend, Listen, Program) qui définissent le comportement global et le flux du trafic.

Section Global

La section global définit des paramètres au niveau du processus système (sécurité, performance, logs). Elle s'applique à l'ensemble de l'instance HAProxy.

global
    log /dev/log local0
    maxconn 4096
    user haproxy
    group haproxy
    daemon

Section Defaults

La section defaults permet d'éviter les répétitions. Les paramètres définis ici (mode, timeouts, logs) sont hérités par toutes les sections frontend et backend qui suivent.

defaults
    log global
    mode http
    timeout connect 5s
    timeout client 50s
    timeout server 50s

Section Frontend

Le frontend définit comment HAProxy reçoit les requêtes. On y précise l'adresse IP et le port d'écoute (bind), ainsi que les règles de routage (ACL) vers les backends.

frontend http-in
    bind *:80
    acl is_static path_beg /static
    use_backend static_servers if is_static
    default_backend app_servers
L'importance du default_backend : Cette directive définit le backend par défaut vers lequel HAProxy envoie les requêtes qui ne correspondent à aucune règle d'ACL (use_backend). Il est fortement recommandé d'en définir un systématiquement pour éviter que HAProxy ne rejette des requêtes avec une erreur 503 si aucune condition de routage n'est satisfaite.

Section Backend

Le backend définit le pool de serveurs de destination. La syntaxe commence par le mot-clé backend suivi d'un nom unique. Pour déclarer plusieurs backends (par exemple pour séparer le trafic API du trafic Web), il suffit de définir plusieurs blocs avec des noms distincts.

backend app_servers
    balance roundrobin
    server web1 10.0.0.1:80 check

backend api_servers
    balance leastconn
    server api1 10.0.0.10:80 check

Section Listen

La section listen est un raccourci qui combine les fonctionnalités d'un frontend et d'un backend dans un seul bloc. C'est idéal pour les services simples comme l'exposition des statistiques ou le proxying TCP pur.

Note : Bien que pratique, ce rôle combiné n'est pas idéal pour les applications complexes composées de multiples domaines web et pools de serveurs. Dans ces cas, fusionner les fonctions peut complexifier inutilement la configuration. Nous recommandons alors de définir des sections frontend et backend séparées.
listen stats
    bind *:8404
    stats enable
    stats uri /monitor
    stats refresh 5s

Section Program

La section program permet à HAProxy de lancer et de surveiller des processus externes (disponible depuis la v2.2).

Note de dépréciation : La fonctionnalité program est dépréciée depuis HAProxy 3.1 et sera supprimée en version 3.3. D'ici là, son comportement change lors des rechargements : le processus maître démarre le programme, mais c'est un processus travailleur (worker) qui l'exécute. Il est désormais recommandé d'utiliser des gestionnaires de processus dédiés comme Systemd, SysVinit, Supervisord ou s6-overlays.
program my-agent
    command /usr/local/bin/agent-script.sh
    user haproxy
    group haproxy

2. Simplifier avec les inclusions

Comment organiser une configuration complexe en plusieurs fichiers.

Utilisation de dossiers de configuration

Plutôt que d'avoir un fichier unique de plusieurs milliers de lignes, HAProxy permet de charger un répertoire entier. Cela est particulièrement utile dans les environnements automatisés (Ansible, Puppet) où chaque application peut avoir son propre fichier de configuration.

Lors du lancement du service, on utilise l'argument -f pointant vers un dossier. HAProxy concatène les fichiers trouvés par ordre alphabétique.

haproxy -f /etc/haproxy/haproxy.cfg -f /etc/haproxy/conf.d/

Exemple d'organisation en production

Dans une production avec de nombreux services, on adopte souvent une nomenclature numérique pour contrôler l'ordre de chargement :

/etc/haproxy/
├── haproxy.cfg       # Global & Defaults
└── conf.d/
    ├── 10-frontend-http.cfg
    ├── 11-frontend-https.cfg
    ├── 20-backend-ecommerce.cfg
    ├── 21-backend-blog.cfg
    └── 99-stats.cfg

Cette structure permet d'ajouter ou supprimer une application simplement en gérant un fichier dans conf.d/, facilitant ainsi l'automatisation via CI/CD.

3. Mise à jour et Rechargement à chaud

Modifier la configuration sans interrompre le trafic.

Zéro Down-time Reload

HAProxy est conçu pour la haute disponibilité. Lorsque vous modifiez la configuration, vous pouvez recharger le service sans perdre de connexions actives. Le nouveau processus prend le relais sur les nouveaux sockets tandis que l'ancien termine de traiter les requêtes en cours.

# Vérifier la syntaxe avant de recharger
haproxy -c -f /etc/haproxy/haproxy.cfg

# Rechargement via systemd
systemctl reload haproxy

Rechargement sous Docker (SIGHUP)

Dans un environnement Docker, utiliser docker restart provoque une coupure nette car il tue le processus. Pour effectuer un rechargement 'hitless' (sans coupure) après avoir modifié votre fichier de configuration, envoyez le signal SIGHUP au conteneur. Le processus maître d'HAProxy créera un nouveau processus avec la nouvelle configuration tout en laissant l'ancien terminer les requêtes en cours.

# Recharger la configuration sans redémarrer le conteneur
docker kill -s HUP my-running-haproxy

La Runtime API

Pour des modifications ultra-dynamiques (comme changer le poids d'un backend ou passer un serveur en maintenance) sans même recharger le fichier, HAProxy propose une Runtime API accessible via une socket Unix. Des outils comme socat ou l'utilitaire haproxy-cli permettent d'interagir avec cette API.

# Exemple : désactiver un serveur via la socket
echo "disable server app_servers/web1" | socat stdio /var/run/haproxy.stat

# Exemple : ajouter un nouveau serveur à chaud avec haproxy-cli
haproxy-cli exec "add server app_servers/web3 10.0.0.3:80 check"

4. Sécurité : DoS, Filtrage IP et WAF

HAProxy est souvent la première ligne de défense de votre infrastructure. Il permet de filtrer le trafic et d'analyser sa dangerosité avant qu'il n'atteigne vos serveurs applicatifs.

Protection contre les attaques DoS

Grâce aux stick-tables, HAProxy peut suivre le comportement des IPs en temps réel pour bloquer les abus (trop de connexions simultanées).

frontend http-in
    bind *:80
    # Table de suivi : 100k entrées, expire après 30s d'inactivité
    stick-table type ip size 100k expire 30s store conn_cur
    # On suit l'IP source
    tcp-request connection track-sc0 src
    # On rejette si l'IP dépasse 15 connexions simultanées
    tcp-request connection reject if { sc0_conn_cur gt 15 }

Sécurité IP : Whitelisting et Blacklisting

Le filtrage IP permet de restreindre l'accès à des ressources sensibles ou de bloquer des attaquants connus.

  • Whitelisting (Liste blanche) : On bloque tout sauf les IPs autorisées (stratégie Default Deny).
  • Blacklisting (Liste noire) : On autorise tout sauf les IPs malveillantes.
# Exemple de Whitelisting pour les stats
acl network_allowed src 127.0.0.1 172.20.0.5
http-request deny if !network_allowed

# Exemple de Blacklisting via un fichier externe
acl bad_guys src -f /etc/haproxy/blacklist.lst
http-request deny if bad_guys

Web Application Firewall (WAF)

Le WAF inspecte le contenu des requêtes (headers, body, paramètres) pour bloquer les attaques de type Injection SQL ou XSS (OWASP Top 10). HAProxy peut intégrer un WAF nativement ou déléguer l'analyse via le mécanisme SPOE (Stream Processing Offload Engine) à un moteur comme ModSecurity.

frontend http-in
    # On délègue l'analyse à l'agent ModSecurity via SPOE
    filter spoe engine modsecurity config /etc/haproxy/modsec.conf
    
    # On bloque la requête (403) si l'agent identifie une menace
    http-request deny deny_status 403 if { var(txn.modsec.code) -m int gt 0 }
Le fichier modsec.conf : Attention, ce fichier n'est pas celui qui contient vos règles de sécurité (WAF). C'est la configuration du SPOE agent. Il définit comment HAProxy communique avec le service externe : quels messages envoyer (headers, IP, etc.), les timeouts de réponse, et quel backend utiliser pour joindre l'agent ModSecurity.

5. Les ACL (Access Control Lists)

Les ACL sont le cœur de l'intelligence de HAProxy. Elles permettent de tester des conditions (URL, headers, IP) pour prendre des décisions de routage.

Syntaxe et Routage

Une ACL se définit par un nom, une méthode de test (fetch) et une valeur.

frontend http-in
    # Teste si le chemin commence par /api
    acl is_api path_beg /api
    # Teste si le header Host contient 'admin'
    acl is_admin hdr_dom(host) admin.mondomaine.com

    # Actions basées sur les ACLs
    use_backend api-servers if is_api
    http-request deny if is_admin !network_allowed

6. Observabilité et Supervision

HAProxy offre une visibilité native sur l'état de santé du trafic et des serveurs.

Dashboard de Statistiques

L'interface web intégrée permet de visualiser l'état des backends et le débit en temps réel.

listen stats
    bind *:8404
    stats enable
    stats uri /stats
    stats refresh 5s
    stats auth admin:password # Optionnel : authentification

Exposition Prometheus

HAProxy peut exposer ses métriques nativement pour être collectées par un serveur Prometheus.

frontend stats_and_metrics
    bind *:8404
    # On expose les métriques sur l'URI /metrics
    http-request use-service prometheus-exporter if { path /metrics }

Support OpenTelemetry (OTel)

Depuis la version 3.4, HAProxy peut envoyer des traces directement vers un collecteur OpenTelemetry pour un tracing distribué complet.

global
    otel-exporter my-collector
        endpoint otel-collector:4317

frontend http-in
    # Envoi de la trace au collecteur
    http-request otel-send-trace

7. resolvers (DNS dynamique)

La directive resolvers permet à HAProxy de résoudre dynamiquement les noms DNS et de suivre leurs changements (scaling, Kubernetes, Docker, service discovery).

Structure de base

La section resolvers définit un serveur DNS utilisé par HAProxy pour résoudre les noms d'hôtes dynamiques.

resolvers dns
    nameserver dns1 127.0.0.11:53
    resolve_retries 3
    timeout resolve 1s
    timeout retry 1s
    hold valid 10s

Utilisation avec un backend

Les resolvers permettent à HAProxy de résoudre dynamiquement des noms DNS et de les combiner avec server-template pour gérer automatiquement le scaling.

Pourquoi server-template ? Contrairement à une déclaration statique, server-template génère automatiquement plusieurs instances backend (web-1, web-2, web-3) sans configuration manuelle, indispensable en Docker/Kubernetes.

resolvers docker_dns
    nameserver docker 127.0.0.11:53
    hold valid 5s

backend app
    server-template app 1-5 app.local:80 check resolvers docker_dns resolve-prefer ipv4

Docker / Service Discovery

Dans Docker, le DNS interne (127.0.0.11) permet de résoudre dynamiquement les conteneurs créés par scaling.

Pourquoi server-template ? Docker ne garantit ni IP fixe ni nom stable. server-template permet à HAProxy de suivre automatiquement les conteneurs sans modifier la configuration.

resolvers docker
    nameserver docker 127.0.0.11:53
    hold valid 10s

backend app
    server-template web 1-10 web.local:80 check resolvers docker resolve-prefer ipv4

Kubernetes / Microservices

Dans Kubernetes, les pods changent dynamiquement selon le scaling du cluster.

Pourquoi server-template ? Les endpoints évoluent en permanence. server-template permet d’adapter automatiquement HAProxy sans reload ni configuration manuelle.

resolvers kube_dns
    nameserver kube 10.96.0.10:53
    hold valid 10s

backend api
    server-template api 1-20 api.default.svc.cluster.local:80 check resolvers kube_dns resolve-prefer ipv4

Comportement de cache DNS

Les directives hold permettent de contrôler la durée de mise en cache des réponses DNS.

  • hold valid : durée de validité d'une résolution réussie
  • hold nx : durée pour les réponses NXDOMAIN
  • hold refused : durée pour les refus DNS
resolvers dns
    nameserver dns1 8.8.8.8:53
    hold valid 30s
    hold nx 5s
    hold refused 5s

Conclusion

La puissance par la modularité.

Une structure robuste

Maîtriser l'anatomie de la configuration HAProxy est la première étape pour construire des infrastructures résilientes. La séparation nette entre l'écoute (frontend) et le traitement (backend) offre une flexibilité que peu d'autres solutions égalent.

Lien copié dans le presse-papiers !