Last updated: 2026-02-11
HAProxy TLS/SSL Configuration Guide
This guide provides recommended TLS/SSL settings for HAProxy, a widely used high-performance load balancer and reverse proxy. HAProxy handles TLS termination at the frontend, offloading encryption from backend servers.
Prerequisites
- HAProxy 2.0 or later (for TLS 1.3 support)
- OpenSSL 1.1.1 or later
- A valid SSL/TLS certificate (PEM format with certificate and key combined, or separate files)
HAProxy expects the certificate and private key in a single PEM file by default:
cat fullchain.pem privkey.pem > /etc/haproxy/certs/example.com.pem
chmod 600 /etc/haproxy/certs/example.com.pem
Global TLS Defaults
Set secure TLS defaults in the global section of your HAProxy configuration (/etc/haproxy/haproxy.cfg). These apply to all frontends unless overridden.
Protocol Versions
Set the minimum TLS version to 1.2 and disable session tickets:
global
ssl-default-bind-options ssl-min-ver TLSv1.2 no-tls-tickets
ssl-default-server-options ssl-min-ver TLSv1.2 no-tls-tickets
- ssl-default-bind-options applies to incoming client connections (frontends).
- ssl-default-server-options applies to outgoing connections to backend servers.
Cipher Suites
Configure strong cipher suites for TLS 1.2 and TLS 1.3:
global
ssl-default-bind-ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305
ssl-default-bind-ciphersuites TLS_AES_256_GCM_SHA384:TLS_CHACHA20_POLY1305_SHA256:TLS_AES_128_GCM_SHA256
ssl-default-server-ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305
ssl-default-server-ciphersuites TLS_AES_256_GCM_SHA384:TLS_CHACHA20_POLY1305_SHA256:TLS_AES_128_GCM_SHA256
- ssl-default-bind-ciphers sets TLS 1.2 cipher suites for client-facing connections.
- ssl-default-bind-ciphersuites sets TLS 1.3 cipher suites for client-facing connections. This directive requires HAProxy 1.9.1+.
Note: On HAProxy 1.8 (e.g. RHEL 8), ssl-min-ver, ssl-default-bind-ciphersuites, and ssl-default-server-ciphersuites are not available. Use the following instead to enforce TLS 1.2+ with ticket disabling: ssl-default-bind-options no-sslv3 no-tlsv10 no-tlsv11 no-tls-tickets and ssl-default-server-options no-sslv3 no-tlsv10 no-tlsv11 no-tls-tickets. Omit the ciphersuites lines entirely — TLS 1.3 cipher selection will use OpenSSL defaults.
Frontend Configuration
Configure your HTTPS frontend with the certificate and ALPN protocol negotiation:
frontend https
bind *:443 ssl crt /etc/haproxy/certs/example.com.pem alpn h2,http/1.1
mode http
# HSTS header
http-response set-header Strict-Transport-Security "max-age=63072000; includeSubDomains; preload"
default_backend servers
The alpn h2,http/1.1 parameter enables HTTP/2 and HTTP/1.1 negotiation via ALPN.
Using a Certificate Directory
If you serve multiple domains, point to a directory containing all certificate PEM files:
frontend https
bind *:443 ssl crt /etc/haproxy/certs/ alpn h2,http/1.1
HAProxy will automatically match certificates to hostnames via SNI.
HTTPS Redirect
Redirect all HTTP traffic to HTTPS:
frontend http
bind *:80
mode http
http-request redirect scheme https code 301
Backend TLS (Re-encryption)
If your backends also require TLS (end-to-end encryption), configure the backend with TLS verification:
backend servers
mode http
server web1 10.0.0.1:443 ssl verify required ca-file /etc/haproxy/ca.pem check
server web2 10.0.0.2:443 ssl verify required ca-file /etc/haproxy/ca.pem check
Use verify required with a ca-file to validate backend server certificates. Use verify none only if backends are on a fully trusted network.
OCSP Stapling
HAProxy supports OCSP stapling. Generate an OCSP response and reference it on the bind line:
frontend https
bind *:443 ssl crt /etc/haproxy/certs/example.com.pem crt-list /etc/haproxy/crt-list.cfg alpn h2,http/1.1
In the certificate list file (crt-list.cfg):
/etc/haproxy/certs/example.com.pem [ocsp-update on] example.com
Note: ocsp-update on requires HAProxy 2.8+. On older versions, use openssl ocsp to fetch responses manually and load them via the HAProxy runtime API.
Complete Configuration Example
global
# HAProxy 1.8 (RHEL 8): replace ssl-min-ver lines with no-sslv3 no-tlsv10 no-tlsv11
# and remove the ciphersuites lines (see note above)
ssl-default-bind-options ssl-min-ver TLSv1.2 no-tls-tickets
ssl-default-bind-ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305
ssl-default-bind-ciphersuites TLS_AES_256_GCM_SHA384:TLS_CHACHA20_POLY1305_SHA256:TLS_AES_128_GCM_SHA256
ssl-default-server-options ssl-min-ver TLSv1.2 no-tls-tickets
ssl-default-server-ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305
ssl-default-server-ciphersuites TLS_AES_256_GCM_SHA384:TLS_CHACHA20_POLY1305_SHA256:TLS_AES_128_GCM_SHA256
defaults
mode http
timeout connect 5s
timeout client 30s
timeout server 30s
frontend http
bind *:80
http-request redirect scheme https code 301
frontend https
bind *:443 ssl crt /etc/haproxy/certs/example.com.pem alpn h2,http/1.1
http-response set-header Strict-Transport-Security "max-age=63072000; includeSubDomains; preload"
default_backend servers
backend servers
server web1 10.0.0.1:8080 check
server web2 10.0.0.2:8080 check
Verification
Test your configuration before reloading:
haproxy -c -f /etc/haproxy/haproxy.cfg
systemctl reload haproxy
Check the active TLS settings:
echo | openssl s_client -connect example.com:443 -servername example.com 2>/dev/null | openssl x509 -noout -subject
Test your configuration externally using Qualys SSL Labs at https://www.ssllabs.com/ssltest/.