Configuring HAProxy as Reverse Proxy (HTTP/HTTPS)
🌐 Overview
This guide shows how to configure HAProxy as an HTTP/HTTPS reverse proxy, with support for Let's Encrypt, load balancing, and sticky sessions. The configuration below is based on the standard SaveinCloud installation.
🧱 Configuration Structure
🔹 Global
global
log 127.0.0.1 local0
user haproxy
group haproxy
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:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384
ssl-default-bind-options no-sslv3 no-tlsv10 no-tlsv11 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:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384
ssl-default-server-options no-sslv3 no-tlsv10 no-tlsv11 no-tls-tickets
ssl-dh-param-file /etc/haproxy/dhparam.pem
tune.ssl.default-dh-param 2048
pidfile /var/run/haproxy.pid
maxconn 10000
daemon
Explanation:
log: defines the log destination.ssl-default-*: sets default security policies for SSL connections.dhparam.pem: sets the Diffie-Hellman parameter for secure SSL (2048 bits).maxconn: maximum number of simultaneous connections.daemon: runs HAProxy as a background service.
🔸 Defaults
defaults
mode http
log global
option httplog
option dontlognull
option http-server-close
option redispatch
retries 3
timeout http-request 10s
timeout queue 1m
timeout connect 10s
timeout client 1m
timeout http-keep-alive 10s
timeout check 10s
maxconn 10000
Explanation:
mode http: sets HTTP mode as default.option httplog: enables detailed HTTP format logging.timeout *: sets limits to avoid stuck connections.redispatch: tries another backend if the current one fails.
📡 Frontend: Receiving Connections
frontend ft_http
bind :::80 v4v6
bind :::443 v4v6 ssl crt /var/lib/jelastic/SSL/jelastic.pem alpn h2,http/1.1
mode http
acl host_app1 hdr(host) -i app1.exemplo.com
acl host_app2 hdr(host) -i app2.exemplo.com
use_backend bk_app1 if host_app1
use_backend bk_app2 if host_app2
stats enable
stats auth admin:<senha>
stats refresh 30s
stats uri /haproxy_adm_panel
stats show-node
stats admin if TRUE
option forwardfor
http-request set-header X-Forwarded-Proto https if { ssl_fc }
http-request set-header HTTPS on if { ssl_fc }
http-request set-header Ssl-Offloaded 1 if { ssl_fc }
default_backend bk_http
Explanation:
bind :::80/:::443: listens on all IPv4/IPv6 interfaces on ports 80 (HTTP) and 443 (HTTPS).ssl crt ...: uses certificate automatically generated by Let's Encrypt.alpn: enables HTTP/2 support.acl hdr(host): creates rules based on the accessed domain.use_backend: routes traffic based on the corresponding ACL.default_backend: used if no ACL is matched.stats *: enables admin panel via/haproxy_adm_panel.set-header: adds useful headers for backend (such as real HTTPS via proxy).
🧩 Default Backend (example with load balancing)
backend bk_http
mode http
cookie SRVNAME insert
balance roundrobin
server webserver1 10.100.75.251:${BACKEND_PORT} check cookie S1
Explanation:
-
mode http: explicit HTTP mode. -
cookie SRVNAME insert: enables sticky sessions via cookie (client is kept on the same backend). -
balance roundrobin: distributes requests evenly among servers. -
server: defines the backend server.check: enables health check.cookie S1: value to be inserted in the cookie for sticky session.
🧩 Backend by Domain (Example with ACLs)
backend bk_app1
server app1_backend 10.0.0.101:80 check
backend bk_app2
server app2_backend 10.0.0.102:80 check
Explanation:
- Allows separating traffic from different domains to distinct destinations.
- Can be expanded with
mode http, load balancing, and cookies as needed.
🔄 balance: Load Balancing Strategies
Defines how requests are distributed among backend servers.
balance roundrobin
| Mode | Description |
|---|---|
roundrobin | Default. Distributes requests sequentially. |
leastconn | Goes to the server with the fewest active connections. |
source | Uses client IP as basis for persistence. |
uri | Uses URL path to distribute requests. |
hdr(name) | Uses the value of an HTTP header (e.g., User-Agent). |
rdp-cookie | Specific for balancing RDP sessions. |
🍪 cookie: Sticky Sessions with Cookies
cookie SRVNAME insert
| Option | Description |
|---|---|
insert | Automatically inserts the cookie in the response. |
rewrite | Uses cookie received from the client. |
prefix | Adds server name at the beginning of the cookie. |
indirect | Does not resend cookie if already present. |
nocache | Prevents caching of the cookie by intermediate proxies. |
Each server must have a cookie identifier:
server app1 10.0.0.1:80 cookie A1 check
🌍 mode: Communication Types
Defines the type of protocol inspected on frontend/backend.
mode http
| Mode | Description |
|---|---|
http | Default mode. Allows inspecting and manipulating HTTP headers. |
tcp | Raw mode. Ideal for protocols like MySQL, PostgreSQL, SMTP, etc. |
health | Used only for health checks. |
🛑 Default Backend (fallback)
backend default
mode http
errorfile 503 /etc/haproxy/welcome.http
Explanation:
- Used as fallback when no valid backends are available.
- Serves a static 503 error file with a custom message.
🎯 Tips and Best Practices
- Use
maxconnto avoid overload on HAProxy. - The panel at
/haproxy_adm_panelrequires basic authentication — change the default password! - The Let's Encrypt certificate is automatically updated by the platform.
- To redirect HTTP to HTTPS, you can use:
redirect scheme https if !{ ssl_fc }
Place this at the beginning of frontend ft_http if you want to enforce HTTPS.