1 24/05/2026 11 min

HAProxy su Ubuntu 22.04 è una scelta solida quando serve un bilanciatore L4/L7 leggero, prevedibile e facile da osservare. La differenza la fanno i dettagli: non basta installarlo, bisogna decidere dove termina il traffico, come si controlla lo stato dei backend, quali timeout usare e come evitare che un errore di configurazione trasformi il proxy nel punto singolo di guasto.

In pratica, HAProxy diventa utile in tre casi ricorrenti: distribuire richieste HTTP verso più web server, esporre in modo pulito applicazioni dietro reverse proxy, oppure fare load balancing TCP per servizi che non parlano HTTP. Su Ubuntu 22.04 il pacchetto è maturo, integrato con systemd e abbastanza stabile da poterlo gestire con configurazione testabile e rollback rapido.

Quando HAProxy è la scelta giusta

Se hai un singolo server web e nessun requisito di alta disponibilità, HAProxy è probabilmente overkill. Se invece devi mettere davanti due o più origin, separare traffico pubblico e interno, o introdurre health check seri, HAProxy ha senso subito. Non è solo un “dispatcher” di richieste: è un punto di controllo dove puoi normalizzare timeouts, retry, header e policy di accesso.

Un errore comune è pensare al bilanciatore come a una scatola da installare e dimenticare. In realtà è un componente di produzione che va trattato come codice: configurazione versionata, test sintattico prima del reload, metriche dopo la messa online e una strategia di fallback se un backend degrada.

Installazione su Ubuntu 22.04

L’installazione base è lineare. Aggiorna l’indice, installa il pacchetto e verifica che il servizio sia attivo. Su Ubuntu 22.04 il repository standard basta nella maggior parte dei casi.

sudo apt update
sudo apt install -y haproxy
systemctl status haproxy --no-pager

Il controllo da fare subito è semplice: il servizio deve risultare active (running) e la versione deve essere coerente con quella del pacchetto installato. Se il servizio parte ma poi si ferma, il problema è quasi sempre nella configurazione iniziale o in un bind su porta già occupata.

Per capire cosa ascolta sulla macchina, usa un controllo sul socket di rete. Questo evita di dare per scontato che la porta 80 o 443 siano davvero libere.

sudo ss -ltnp | grep -E ':(80|443|8404)\b'

Struttura della configurazione

Il file principale è /etc/haproxy/haproxy.cfg. La configurazione si divide in quattro blocchi concettuali: global, defaults, frontend e backend. È una struttura semplice, ma va usata con disciplina perché gli errori qui diventano errori di produzione.

Nel blocco global definisci parametri generali, log, utente di esecuzione e socket amministrativo. Nel blocco defaults imposti timeout e comportamenti comuni. Nel frontend accetti il traffico in ingresso. Nel backend specifichi i server reali verso cui instradare le richieste.

Prima di toccare il file, conviene salvare una copia. Su un server di produzione non si lavora mai senza una via di ritorno chiara.

sudo cp /etc/haproxy/haproxy.cfg /etc/haproxy/haproxy.cfg.bak.$(date +%F-%H%M)

Configurazione minima per HTTP reverse proxy

Questo è un esempio base ma già utile in produzione: riceve traffico su porta 80 e lo distribuisce su due backend web. È il punto di partenza più comune quando si vogliono bilanciare più origin Apache o Nginx.

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 ca-base /etc/ssl/certs crt-base /etc/ssl/private tune.ssl.default-dh-param 2048 defaults log global mode http option httplog option dontlognull timeout connect 5s timeout client 50s timeout server 50s timeout http-request 10s timeout queue 30s frontend fe_http bind *:80 default_backend be_web backend be_web balance roundrobin option httpchk GET /health http-check expect status 200 server web1 192.0.2.11:80 check server web2 192.0.2.12:80 check

La riga option httpchk è importante: non stai solo verificando che il TCP sia aperto, ma che l’app risponda davvero come previsto. Se un nodo è in piedi ma l’applicazione è rotta, HAProxy lo può togliere dal pool senza aspettare che gli utenti lo scoprano a colpi di 5xx.

Se non hai un endpoint /health, crealo lato applicazione. È meglio di qualunque check improvvisato sulla homepage, perché una pagina pubblica può essere cachata o servita in modo parziale anche quando il backend applicativo è degradato.

Creare un health check affidabile

L’health check deve essere veloce, deterministico e poco costoso. Non deve dipendere da query pesanti al database, né da servizi esterni non essenziali. Se il controllo è troppo complesso, rischi di far cadere backend sani o di introdurre falsi positivi.

Un endpoint semplice in PHP o in qualunque framework può limitarsi a restituire codice 200 e un payload minimo. L’idea è verificare il percorso base dell’applicazione, non misurare tutto lo stack a ogni richiesta.

<?php
http_response_code(200);
echo "OK";

Se vuoi un controllo un po’ più robusto, fai in modo che il backend restituisca 200 solo quando riesce a leggere una dipendenza critica, ma senza aprire la porta a timeout lunghi. Un health check che impiega troppo tempo è quasi peggio di nessun health check.

Passare da HTTP a HTTPS

In produzione quasi sempre vuoi terminare TLS su HAProxy. Questo semplifica la gestione dei certificati, centralizza la cifratura e permette di applicare policy coerenti sui client. Su Ubuntu 22.04 il punto delicato è il file PEM: certificato e chiave privata devono stare nel formato corretto e con permessi stretti.

Un esempio di terminazione TLS su porta 443:

frontend fe_https bind *:443 ssl crt /etc/haproxy/certs/example.com.pem alpn h2,http/1.1 http-request set-header X-Forwarded-Proto https default_backend be_web

Il file /etc/haproxy/certs/example.com.pem deve contenere certificato e chiave privata concatenati. I permessi vanno ridotti, tipicamente leggibili solo da root o dal gruppo necessario. Se la chiave privata è esposta in chiaro con permessi troppo larghi, hai un problema di sicurezza prima ancora che di configurazione.

Se il certificato è emesso da una CA pubblica o da Let’s Encrypt, ricordati di pianificare il rinnovo. HAProxy non rinnova nulla da solo: può caricare un nuovo file, ma il ciclo di emissione resta un compito esterno, ad esempio con certbot o con una pipeline interna che aggiorna i PEM e fa reload controllato.

Header utili dietro reverse proxy

Dietro HAProxy, l’applicazione deve sapere qual è l’IP reale del client e quale schema è stato usato. Senza questi header, i log diventano poco affidabili e alcune applicazioni generano URL sbagliati o redirect infiniti.

Gli header più comuni sono X-Forwarded-For, X-Forwarded-Proto e, se serve, X-Forwarded-Port. HAProxy può aggiungerli o sovrascriverli in modo consistente.

frontend fe_https bind *:443 ssl crt /etc/haproxy/certs/example.com.pem http-request set-header X-Forwarded-Proto https http-request add-header X-Forwarded-For %[src] default_backend be_web

Qui va fatta attenzione: in alcuni casi l’header X-Forwarded-For viene già inserito da un layer precedente, come un CDN o un altro proxy. Se ne hai più di uno, devi definire una policy chiara su chi è autorizzato a scrivere cosa, altrimenti i log lato applicazione diventano inconsistenti.

Session persistence e bilanciamento

Non tutte le applicazioni sono stateless. Se hai sessioni locali, carrelli non condivisi o login che dipendono da memoria applicativa, devi decidere se usare stickiness o se rendere l’app stateless. La soluzione migliore è quasi sempre la seconda, ma non sempre è disponibile subito.

Con HAProxy puoi usare cookie o source hashing. Il cookie è più flessibile per HTTP; l’hash sull’IP può essere sufficiente in scenari semplici, ma con NAT o utenze mobili può creare distribuzioni sbilanciate.

backend be_app_sticky balance roundrobin cookie SRV insert indirect nocache server app1 192.0.2.21:80 check cookie a server app2 192.0.2.22:80 check cookie b

Se usi stickiness, verifica come si comporta il failover. Una sessione bloccata su un nodo guasto è il classico problema che compare solo quando il traffico reale incontra un guasto reale. Per questo conviene sempre testare sia il funzionamento normale sia il comportamento con un backend spento.

Interfaccia di statistiche e osservabilità

HAProxy ha un valore enorme quando lo osservi bene. L’interfaccia di statistiche ti dice subito quali backend sono UP o DOWN, quante connessioni stanno passando e dove si accumulano i ritardi. Non è un optional, è il modo più rapido per capire se il bilanciamento funziona davvero.

listen stats bind *:8404 stats enable stats uri /stats stats refresh 10s stats auth admin:ChangeMeNow

La credenziale nell’esempio va cambiata subito e non va lasciata in chiaro in un file condiviso. Meglio ancora, limita l’accesso all’interfaccia con firewall o bind su IP amministrativi. Se la pagina statistiche è pubblica, stai regalando informazioni operative a chiunque la trovi.

Per integrare HAProxy con i log di sistema, controlla /var/log/syslog oppure il journal, in base alla configurazione di Ubuntu. I messaggi di errore durante il reload sono spesso più utili della pagina di stato, perché ti dicono esattamente quale direttiva non viene accettata.

Validazione prima del reload

Mai fare reload cieco. Prima valida la sintassi, poi ricarica. Su HAProxy questa disciplina evita downtime banali dovuti a una virgola fuori posto o a un backend scritto male.

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

L’output deve confermare che la configurazione è corretta. Se compare un errore, correggi prima di procedere. Una volta superato il check sintattico, puoi fare reload del servizio in modo pulito.

sudo systemctl reload haproxy
sudo systemctl status haproxy --no-pager

Il reload è preferibile al restart perché riduce l’impatto sulle connessioni esistenti. In ambienti con molto traffico, questo dettaglio fa la differenza tra un cambio invisibile e una breve interruzione percepita dagli utenti.

Firewall e esposizione delle porte

Un proxy ben configurato ma esposto male è comunque fragile. Su Ubuntu 22.04 il controllo di base passa da ufw o da regole firewall equivalenti. Devi decidere quali porte sono pubbliche e quali devono restare interne.

Se HAProxy espone HTTP e HTTPS, apri solo quelle porte verso l’esterno e tieni la porta statistiche su rete amministrativa. I backend, invece, non dovrebbero essere raggiungibili direttamente da Internet se il modello prevede l’accesso solo tramite il bilanciatore.

sudo ufw allow 80/tcp
sudo ufw allow 443/tcp
sudo ufw deny 8404/tcp

Se usi una security group cloud o un firewall upstream, la logica resta la stessa: il bilanciatore deve essere l’unico punto di ingresso, non un servizio in più esposto per errore.

Problemi tipici dopo l’installazione

Il primo problema tipico è il bind fallito: la porta è già occupata o il servizio non ha i permessi per ascoltare. Il secondo è il backend che risulta DOWN perché l’health check non corrisponde al comportamento reale dell’app. Il terzo è il TLS che non parte per un file PEM sbagliato o non leggibile.

Per isolare rapidamente il problema, conviene partire dal layer più basso: porta in ascolto, poi sintassi, poi reachability dei backend, poi risposta applicativa. È più veloce di qualsiasi ipotesi “a intuito”.

sudo journalctl -u haproxy -n 50 --no-pager
sudo haproxy -c -f /etc/haproxy/haproxy.cfg
curl -I http://127.0.0.1
curl -kI https://127.0.0.1

Se il test locale passa ma i client esterni no, il problema spesso non è HAProxy ma il firewall, il DNS o il layer davanti al proxy, come un CDN o un load balancer cloud. Se invece il test locale fallisce, il problema è quasi certamente nel servizio o nella configurazione del proxy.

Hardening essenziale

Per un uso serio, HAProxy va ridotto all’essenziale: niente permessi inutili, niente interfacce amministrative esposte senza controllo, niente chiavi private con accesso ampio. Anche il file di configurazione va trattato come materiale sensibile perché contiene indirizzi interni, policy di routing e spesso dettagli utili a un attaccante.

Se il bilanciatore termina TLS, tieni i certificati in /etc/haproxy/certs/ con permessi stretti e verifica che il servizio legga solo ciò che deve leggere. Se usi un account applicativo per i reload o per la generazione dei file, concedi il minimo necessario e niente di più.

Un audit minimo comprende: porte esposte, ownership dei file, presenza di credenziali in chiaro, stato degli health check e validità dei certificati. È poco glamour, ma evita molti problemi prima che diventino incidenti.

Schema operativo consigliato

Se devi mettere HAProxy in produzione da zero, il flusso ragionevole è questo: installa il pacchetto, prepara una configurazione minima, verifica la sintassi, testa il servizio localmente, apri solo le porte necessarie, poi abilita TLS e health check. Ogni passaggio va verificato prima di aggiungere il successivo.

  1. Installa haproxy con apt e controlla che il servizio parta.
  2. Prepara un backup di /etc/haproxy/haproxy.cfg prima di modificare la configurazione.
  3. Definisci un frontend e almeno un backend con health check.
  4. Valida la configurazione con haproxy -c -f /etc/haproxy/haproxy.cfg.
  5. Fai systemctl reload haproxy e osserva log e statistiche.
  6. Abilita TLS, poi verifica certificati, header e accesso esterno.

Questa sequenza riduce il rischio di introdurre più variabili del necessario. Se qualcosa non torna, sai con precisione dove guardare e non devi inseguire sintomi sovrapposti.

Conclusione operativa

HAProxy su Ubuntu 22.04 non è complicato, ma richiede metodo. La parte facile è installarlo; la parte che conta è costruire una configurazione pulita, testabile e osservabile. Se tieni separati frontend, backend, health check, TLS e hardening, ottieni un proxy che non solo distribuisce traffico, ma ti aiuta anche a diagnosticare i problemi quando qualcosa si rompe.

Assunzione: esempio pensato per un server Ubuntu 22.04 con HAProxy in reverse proxy HTTP/HTTPS, backend privati e accesso amministrativo limitato.