HAProxy & Rocky Linux 9 — Configuration complète

BTS SIO SISR · Atelier de professionnalisation — Épreuves pratiques
Rocky Linux 9 — commandes de baseRocky Linux 9 — Firewall & SELinuxHAProxy — installation & structureHAProxy — section global & defaultsHAProxy — frontends (points d'entrée)HAProxy — backends & algorithmes d'équilibrageHAProxy — page de statistiques & socket adminHaute disponibilité HAProxy + Keepalived (VRRP)HAProxy — exemple de config complèteDépannage & vérification HAProxy
Rocky Linux 9 — commandes de base

Gestion des paquets (DNF)

dnf install haproxy keepalived -y    # Installer des paquets
dnf update -y                         # Mettre à jour le système
dnf list installed | grep haproxy    # Vérifier l'installation
dnf info haproxy                      # Informations sur un paquet

Gestion des services (systemctl)

systemctl start haproxy              # Démarrer
systemctl stop haproxy               # Arrêter
systemctl restart haproxy            # Redémarrer (coupure brève)
systemctl reload haproxy             # Recharger la config SANS coupure
systemctl enable haproxy             # Démarrer au boot
systemctl disable haproxy            # Ne plus démarrer au boot
systemctl status haproxy             # Statut et dernières lignes de log
systemctl is-active haproxy          # active / inactive

Réseau (Rocky Linux 9 / NetworkManager)

ip addr show                         # Interfaces et adresses IP
ip route show                         # Table de routage
nmcli connection show                 # Connexions réseau
nmcli device status                   # État des interfaces
nmcli con mod ens192 ipv4.addresses 192.168.1.10/24
nmcli con mod ens192 ipv4.gateway 192.168.1.1
nmcli con mod ens192 ipv4.dns "8.8.8.8 1.1.1.1"
nmcli con mod ens192 ipv4.method manual
nmcli con up ens192

Logs

journalctl -u haproxy -f             # Logs HAProxy en temps réel
journalctl -u haproxy --since today  # Logs du jour
journalctl -xe                        # Dernières erreurs système
tail -f /var/log/haproxy.log         # Log HAProxy (si configuré)
Rocky Linux 9 — Firewall & SELinux

Firewalld (pare-feu par défaut)

firewall-cmd --state                 # Statut du pare-feu
firewall-cmd --list-all              # Règles actives

# Ouvrir des ports/services
firewall-cmd --permanent --add-service=http
firewall-cmd --permanent --add-service=https
firewall-cmd --permanent --add-port=8080/tcp    # Stats HAProxy
firewall-cmd --permanent --add-port=8404/tcp    # Prometheus metrics
firewall-cmd --permanent --add-port=112/tcp     # VRRP Keepalived

# Supprimer une règle
firewall-cmd --permanent --remove-port=8080/tcp

# IMPORTANT : appliquer les changements permanents
firewall-cmd --reload

firewall-cmd --list-ports            # Ports ouverts
firewall-cmd --list-services         # Services autorisés

SELinux (Security-Enhanced Linux)

getenforce                           # Enforcing / Permissive / Disabled
sestatus                             # Statut détaillé SELinux

# Autoriser HAProxy à se connecter aux backends
setsebool -P haproxy_connect_any 1

# Vérifier les booléens HAProxy
getsebool -a | grep haproxy

# Si HAProxy écoute sur un port non standard
semanage port -a -t http_port_t -p tcp 8080
semanage port -l | grep http

# Voir les refus SELinux récents
ausearch -m avc -ts recent
# Ou :
cat /var/log/audit/audit.log | grep denied | grep haproxy
Ne jamais désactiver SELinux ! Utiliser les booléens et les contextes appropriés.
HAProxy — installation & structure
# Installation
dnf install haproxy -y
systemctl enable haproxy

# Fichier de configuration principal
/etc/haproxy/haproxy.cfg

# Tester la configuration avant de recharger (INDISPENSABLE)
haproxy -c -f /etc/haproxy/haproxy.cfg

# Recharger sans coupure de service
systemctl reload haproxy

Structure du fichier haproxy.cfg

global      # Paramètres globaux du processus HAProxy
defaults    # Valeurs par défaut pour les frontends/backends
frontend    # Point d'entrée (écoute les connexions clients)
backend     # Groupe de serveurs qui traite les requêtes
listen      # Combinaison frontend + backend (ex: stats)
HAProxy — section global & defaults
global
    log /dev/log    local0
    log /dev/log    local1 notice
    chroot /var/lib/haproxy
    stats socket /run/haproxy/admin.sock mode 660 level admin expose-fd listeners
    stats timeout 30s
    user haproxy
    group haproxy
    daemon

    # Performances
    maxconn 50000
    nbthread 4                       # Nombre de threads (= nb de CPUs)

    # Sécurité SSL/TLS
    ssl-default-bind-ciphers ECDH+AESGCM:DH+AESGCM:ECDH+AES256:DH+AES256
    ssl-default-bind-options ssl-min-ver TLSv1.2 no-tls-tickets

defaults
    log     global
    mode    http                     # http ou tcp
    option  httplog                  # Format de log HTTP détaillé
    option  dontlognull              # Ne pas loguer les connexions vides
    option  http-server-close        # Fermer la connexion côté serveur
    option  forwardfor               # Ajouter X-Forwarded-For (IP client)
    option  redispatch               # Redistribuer si serveur indisponible

    timeout connect  5s
    timeout client   30s
    timeout server   30s
    timeout http-request 10s
    timeout http-keep-alive 2s
    timeout queue   30s

    retries 3
    maxconn 10000
HAProxy — frontends (points d'entrée)

Frontend HTTP simple

frontend http_in
    bind *:80
    default_backend web_servers      # Backend par défaut

Frontend HTTPS avec terminaison SSL

frontend https_in
    bind *:443 ssl crt /etc/haproxy/certs/monsite.pem
    # Le fichier PEM doit contenir : clé privée + certificat + chaîne CA
    # Créer le PEM : cat monsite.key monsite.crt ca-bundle.crt > monsite.pem

    default_backend web_servers

Frontend avec redirection HTTP → HTTPS

frontend http_in
    bind *:80
    redirect scheme https code 301 if !{ ssl_fc }
    # ssl_fc = la connexion est déjà en SSL/TLS

Frontend avec ACL (routage conditionnel)

frontend http_in
    bind *:80

    # Définir des ACL
    acl is_api        path_beg /api/
    acl is_admin      path_beg /admin
    acl internal_net  src 192.168.0.0/16
    acl host_www      hdr(host) -i www.monsite.fr
    acl host_api      hdr(host) -i api.monsite.fr

    # Bloquer l'accès admin depuis l'extérieur
    http-request deny if is_admin !internal_net

    # Routage selon les conditions
    use_backend api_servers  if is_api
    use_backend api_servers  if host_api
    default_backend          web_servers
HAProxy — backends & algorithmes d'équilibrage

Backend avec Round Robin (défaut)

backend web_servers
    balance roundrobin               # Chaque serveur à tour de rôle

    # Vérification de santé HTTP
    option httpchk GET /health HTTP/1.1
Host:\ localhost

    server web1 192.168.1.10:80 check
    server web2 192.168.1.11:80 check
    server web3 192.168.1.12:80 check
    server web4 192.168.1.13:80 check backup  # Utilisé seulement si les autres sont DOWN

Algorithmes d'équilibrage

balance roundrobin    # Tour à tour (défaut, stateless)
balance leastconn     # Vers le serveur avec le moins de connexions actives
balance source        # Hachage de l'IP source (sessions persistantes)
balance uri           # Hachage de l'URI (utile pour cache)
balance random        # Aléatoire
balance first         # 1er serveur disponible jusqu'à maxconn

Options des serveurs backend

server web1 192.168.1.10:80 check inter 2s rise 2 fall 3 weight 2 maxconn 500
#                                   |          |    |     |        |       |
#                                   vérifier   |    |     |        |       connexions max
#                                   fréquence  |    |     |        poids (RR pondéré)
#                                              |    |     checs avant DOWN
#                                              |    succès avant UP
#                                              intervalle de check

Sessions persistantes (sticky sessions)

backend web_servers
    balance roundrobin
    cookie SERVERID insert indirect nocache  # Insérer un cookie de session
    server web1 192.168.1.10:80 check cookie web1
    server web2 192.168.1.11:80 check cookie web2
    # Ou avec source IP :
    # balance source

Backend TCP (mode layer 4)

backend mysql_servers
    mode tcp
    balance leastconn
    server db1 192.168.1.20:3306 check
    server db2 192.168.1.21:3306 check
HAProxy — page de statistiques & socket admin

Page de statistiques web

listen stats
    bind *:8404
    stats enable
    stats uri /stats                 # URL : http://IP:8404/stats
    stats realm HAProxy\ Statistics
    stats auth admin:MotDePasse123   # Authentification HTTP Basic
    stats refresh 10s               # Rafraîchissement automatique
    stats show-legends              # Légendes sur les graphiques
    stats show-node                 # Nom du nœud HAProxy
    stats admin if TRUE             # Activer les boutons admin (enable/disable)
Ouvrir http://192.168.1.10:8404/stats dans le navigateur après avoir ouvert le port dans le firewall.

Socket admin (gestion en ligne de commande)

# Voir le statut général
echo "show info" | socat stdio /run/haproxy/admin.sock

# Voir les statistiques de tous les backends
echo "show stat" | socat stdio /run/haproxy/admin.sock

# Désactiver un serveur backend (maintenance)
echo "disable server web_servers/web1" | socat stdio /run/haproxy/admin.sock

# Réactiver un serveur
echo "enable server web_servers/web1" | socat stdio /run/haproxy/admin.sock

# Voir les sessions actives
echo "show sess" | socat stdio /run/haproxy/admin.sock
Haute disponibilité HAProxy + Keepalived (VRRP)

Architecture

CLIENT
  |
  v
[VIP : 192.168.1.100]  <-- IP virtuelle flottante
  |
  +-- HAProxy MASTER (192.168.1.10)   PRIO 101
  +-- HAProxy BACKUP (192.168.1.11)   PRIO 100

Si le MASTER tombe, Keepalived bascule la VIP sur le BACKUP automatiquement.

Installation de Keepalived

dnf install keepalived -y
systemctl enable keepalived

Configuration Keepalived — MASTER (/etc/keepalived/keepalived.conf)

vrrp_script chk_haproxy {
    script "systemctl is-active haproxy"   # Vérifier que HAProxy tourne
    interval 2                              # Toutes les 2 secondes
    weight   -10                           # Baisser la priorité de 10 si KO
}

vrrp_instance VI_1 {
    state MASTER                           # MASTER sur ce nœud
    interface ens192                        # Interface réseau à surveiller
    virtual_router_id 51                   # Identifiant VRRP (0-255, unique par groupe)
    priority 101                           # Priorité (plus élevé = MASTER)
    advert_int 1                           # Envoi de VRRP advertisement toutes les 1s
    preempt                                # Reprend le rôle MASTER quand dispo

    authentication {
        auth_type PASS
        auth_pass KeepSecret2024           # Mot de passe partagé
    }

    virtual_ipaddress {
        192.168.1.100/24                   # VIP (adresse virtuelle flottante)
    }

    track_script {
        chk_haproxy                        # Suivre l'état de HAProxy
    }
}

Configuration Keepalived — BACKUP

# Même fichier mais modifier :
state BACKUP                               # BACKUP sur ce nœud
priority 100                               # Priorité inférieure au MASTER

Vérification

systemctl start keepalived
systemctl status keepalived

# Sur le MASTER : la VIP doit être présente
ip addr show ens192 | grep 192.168.1.100

# Tester le basculement
systemctl stop haproxy                     # Sur le MASTER
# La VIP doit basculer sur le BACKUP
ip addr show ens192                        # Sur le BACKUP : la VIP doit apparaître

journalctl -u keepalived -f               # Logs Keepalived
S'assurer que le port 112 (VRRP) est ouvert dans firewalld sur les deux nœuds !
HAProxy — exemple de config complète
#---------------------------------------------------------
# /etc/haproxy/haproxy.cfg  — Exemple complet
#---------------------------------------------------------

global
    log /dev/log local0
    chroot /var/lib/haproxy
    stats socket /run/haproxy/admin.sock mode 660 level admin
    maxconn 50000
    user haproxy
    group haproxy
    daemon

defaults
    log     global
    mode    http
    option  httplog
    option  dontlognull
    option  forwardfor
    option  http-server-close
    timeout connect 5s
    timeout client  30s
    timeout server  30s
    retries 3

#--- Frontend HTTP : redirection vers HTTPS
frontend http_in
    bind *:80
    redirect scheme https code 301

#--- Frontend HTTPS : terminaison SSL
frontend https_in
    bind *:443 ssl crt /etc/haproxy/certs/monsite.pem

    # ACL basée sur l'hostname
    acl host_api hdr(host) -i api.monsite.fr
    acl is_admin path_beg /admin
    acl internal  src 192.168.0.0/16

    # Bloquer /admin depuis l'extérieur
    http-request deny if is_admin !internal

    use_backend api_back if host_api
    default_backend web_back

#--- Backend serveurs web
backend web_back
    balance roundrobin
    option httpchk GET /health
    server web1 192.168.1.10:80 check inter 2s rise 2 fall 3
    server web2 192.168.1.11:80 check inter 2s rise 2 fall 3
    server web3 192.168.1.12:80 check inter 2s rise 2 fall 3 backup

#--- Backend API
backend api_back
    balance leastconn
    option httpchk GET /api/health
    server api1 192.168.1.20:8080 check
    server api2 192.168.1.21:8080 check

#--- Page de statistiques
listen stats
    bind *:8404
    stats enable
    stats uri /stats
    stats auth admin:MonMDP2024
    stats refresh 10s
    stats admin if TRUE
# Toujours tester avant de recharger !
haproxy -c -f /etc/haproxy/haproxy.cfg && systemctl reload haproxy
Dépannage & vérification HAProxy

Checklist en cas de problème

# 1. Tester la syntaxe du fichier de config
haproxy -c -f /etc/haproxy/haproxy.cfg

# 2. Vérifier que HAProxy écoute bien
ss -tlnp | grep haproxy              # Ports en écoute
netstat -tlnp | grep haproxy         # Alternative

# 3. Voir les logs en temps réel
journalctl -u haproxy -f

# 4. Vérifier l'état des backends via le socket
echo "show stat" | socat stdio /run/haproxy/admin.sock | cut -d',' -f1,2,18

# 5. Vérifier SELinux
ausearch -m avc -ts recent | grep haproxy

# 6. Vérifier le pare-feu
firewall-cmd --list-all

Codes d'état des serveurs (show stat)

UP      = Serveur opérationnel
DOWN    = Serveur hors service (health check échoué)
NOLB    = Maintenance manuelle (désactivé via socket/interface)
MAINT   = En maintenance
DRAIN   = Accepte plus de nouvelles connexions (vidage progressif)

Erreurs fréquentes

ErreurCause probableSolution
no serversTous les backends DOWNVérifier health checks, connectivité
502 Bad GatewayBackend ne répond pasVérifier que le service tourne sur le backend
503 Service UnavailablePlus de serveur disponibleVérifier les serveurs backend
Permission denied (socket)SELinux ou droits socketsetsebool -P haproxy_connect_any 1
Port déjà utiliséAutre service sur le portss -tlnp | grep :80