Community Knowledge Base

Deploying HAProxy as a Load Balancer

This guide aims to guide an administrator in setting up an HAProxy installation as a load balancer for SmarterMail. This process can be adapted for both High Availability or non-HA SmarterMail installations simply by adjusting the number of nodes.

Install HAProxy

First, you’ll need a supported Linux environment capable of installing packages from an online repository. For this guide an Ubuntu 24 server was utilized as it includes support for all required prerequisites. To get started you can issue the following command to update the online repositories and install HAProxy:

sudo apt update && sudo apt install haproxy

Once the HAProxy installation has finished it needs configuring.

Configuring HAProxy

HAProxy configuration is relatively simple. It consists of setting up both a front end, which covers the incoming endpoint(s) for your environment (HTTP/HTTPS, IMAP, POP, SMTP, etc.), and back end, such as groupings of servers (nodes) that you want to pass that traffic to. As they work together, each front end will need a corresponding back end.

To get started we’ll begin by backing up the existing (default) haproxy.cfg file with the command below:

sudo cp /etc/haproxy/haproxy.cfg /etc/haproxy/haproxy.cfg.backup

Next, begin editing the HAProxy configuration file with this command:

sudo nano /etc/haproxy/haproxy.cfg

With the config file opened in an editor, add a simply SMTP front end section, like below:

frontend smtp-in
  bind *:25
  mode tcp
  timeout client 1m
  log global
  option tcplog
  default_backend backend_servers_smtp

This establishes a front end for SMTP (port 25) that forwards all SMTP (port 25) traffic to a back end called back end_servers_smtp. Right below that section we’ll add our back end section to match, modifying the IP addresses to match your SmarterMail install or nodes (depending on whether you’re using SmarterMail Professional or Enterprise, or SmarterMail HA):

backend backend_servers_smtp
  mode tcp
  log global
  timeout server 1m
  timeout connect 60s
  balance leastconn
  stick-table type ip size 1m expire 30m
  stick on src
  server node01 1.2.3.4:25 check send-proxy
  server node02 5.6.7.8:25 check send-proxy

In the back end configuration above, there are two SmarterMail nodes set up in an HA configuration, so traffic to SMTP port 25 could end up on either one of these nodes. For a single SmarterMail server you’d need a single SMTP back end, and the name used is arbitrary (i.e., “node01”). For a standalone installation, that could be “server your_mailserver_name 1.2.3.4:25”.

Some things to note on the configuration parameters as these will vary depending on the type of front end / back end pair you’re setting up:

  • The mode tcp parameter should only be used for TCP protocols like SMTP, IMAP, POP, etc.
  • The balance leastconn parameter instructs HAProxy to deliver traffic to the least busy node, and so this parameter won’t apply in single node environments. The stick on src parameter sticks a given client to whichever node they connected to initially.
  • The check parameter instructs HAProxy to monitor those nodes and remove them from the connection pool if they become unresponsive.
  • The send-proxy value allows HAProxy to proxy the SMTP session to the rightful node meaning those incoming sessions aren’t actually directly connected to the node at any time.

Some front end / back end sections can be more difficult to set up. For example, with HTTP/HTTPS front ends. In the example below, the HTTP front end / back end pairing simply redirects ALL HTTP traffic to the HTTPS front end instead:

frontend http-in
  bind *:80
  http-request redirect scheme https unless { ssl_fc }
  default_backend backend_servers_http
  option forwardfor

backend backend_servers_http
  balance leastconn
  stick-table type ip size 1m expire 30m
  stick on src
  server node01 1.2.3.4:80 check
  server node02 5.6.7.8:80 check

Then, on the HTTPS side of things we are configuring SSL-offloading, meaning HAProxy is doing the work of encrypting / decrypting HTTPS traffic and passing simple HTTP traffic back to the nodes:

frontend https-in
  bind *:443 ssl crt /share_server/hub_path/Certificates/ProxyPemCerts/
  mode http
  http-request set-header X-Forwarded-Proto https
  http-request set-header X-Forwarded-Host %[req.hdr(Host)]
  default_backend backend_servers_https
  option forwardfor

backend backend_servers_https
  mode http
  balance leastconn
  stick-table type ip size 1m expire 30m
  stick on src
  server node01 1.2.3.4:80 check
  server node02 5.6.7.8:80 check

The pathing noted above in the bind line is taken from an existing High Availability setup where the HAProxy server has been extended access to the hub’s share directory allowing it to access the ProxyPEMCerts folder directly facilitating the SSL offloading. It is also possible to let SmarterMail handle the HTTPS encryption/decryption with a standard TCP block as is setup for SMTP and others.

Validating Your Setup

When you’ve finished configuring your HAProxy front end / back end pairings you can first validate your changes with the following command:

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

Then, assuming there are no errors during validation, you can apply that configuration with minimal downtime using the command below:

sudo service haproxy reload

This command tells HAProxy to start up new sessions under the updated configuration, but complete existing sessions under the old one, allowing for a seamless transition to the new configuration.

Backing Up HAProxy

The configurations in this guide only apply to /etc/haproxy/haproxy.cfg, but it is recommended to backup the entire /etc/haproxy directory as there are other configuration HAProxy relies on in this directory. Feel free to name your backup directory as you see fit.

mkdir ~/haproxy_backup

sudo cp -r /etc/haproxy ~/haproxy_backup/