Setting Up and Configuring a Loadbalancer on Ubuntu server (HAProxy)

Emmanuel Fasogba
6 min readJan 27, 2023

--

Overview

A Load balancer distributes the work-load of your system to multiple individual systems, or group of systems to reduce the amount of load on any individual system, which in turn increases the reliability, efficiency and availability of your enterprise application or website.

It acts as the “traffic cop” sitting in front of your servers and routing client requests across all servers capable of fulfilling those requests in a manner that maximises speed and capacity utilisation and ensures that no one server is overworked, which could degrade performance.

If a single server goes down, the load balancer redirects traffic to the remaining online servers. When a new server is added to the server group, the load balancer automatically starts to send requests to it.

In summary, a load balancer;

  1. Distributes client requests or network load efficiently across multiple servers.
  2. Monitors servers state, health and downtime
  3. Ensures high availability and reliability by sending requests only to servers that are online.
  4. Provides the flexibility to add or subtract servers as demand dictates

Benefits of Load Balancing

The following are the advantages of load balancing your application:

  • Reduced the work-load on an individual server.
  • Large amount of work done in same time due to concurrency.
  • Increased performance of your application because of faster response.
  • No single point of failure. In a load balanced environment, if a server crashes the application is still up and served by the other servers in the cluster.
  • When appropriate load balancing algorithm is used, it brings optimal and efficient utilisation of the resources, as it eliminates the scenario of some server’s resources are getting used than others.
  • Scalability: We can increase or decrease the number of servers on the fly without bringing down the application
  • Load balancing increases the reliability of your enterprise application
  • Increased security as the physical servers and IPs are abstract in certain cases.

On a high level, there are two types of load balancers, which implements different types of scheduling algorithms and routing mechanisms.

  • Software load balancer
  • Hardware load balancer

Without further ado, I will go into the How’s of setting up HAProxy on an Ubuntu server.

What is HAProxy ?

HAProxy, which stands for High Availability Proxy, is a popular open source software TCP/HTTP Load Balancer and proxying solution which can be run on Linux, mac-OS, and FreeBSD.

Its most common use is to improve the performance and reliability of a server environment by distributing the workload across multiple servers (e.g. web, application, database). It is used in many high-profile environments, including: GitHub, Imgur, Instagram, and Twitter.

To install HAProxy, simply;

  • Run apt repository updates
$ sudo apt update
$ sudo apt-get install --no-install-recommends software-properties-common

To install dependencies

  • Add haproxy repo:
$ sudo add-apt-repository ppa:vbernat/haproxy-2.6

It is advisable to use LTS (Long Term Support) build version like 2.6

  • Finally, install haproxy
$ sudo apt-get install haproxy -y

After installation, verify that HAProxy is working:

haproxy -v

The server will respond with:

HAProxy version 2.6.8-1ppa1~focal 2023/01/24 - https://haproxy.org/
Status: long-term supported branch - will stop receiving fixes around Q2 2027.
Known bugs: http://www.haproxy.org/bugs/bugs-2.6.8.html
Running on: Linux 5.15.0-1021-aws #25~20.04.1-Ubuntu SMP Thu Sep 22 13:59:08 UTC 2022 x86_64

Configuring HAProxy as LoadBalancer

On installation, HAProxy automatically creates a default configuration file /etc/haproxy/haproxy.cfg which is the main configuration file.

The default `haproxy.cfg` file contains

global
log /dev/log local0
log /dev/log local1 notice
chroot /var/lib/haproxy
stats socket /run/haproxy/admin.sock mode 660 level admin
stats timeout 30s
user haproxy
group haproxy
daemon

# Default SSL material locations
ca-base /etc/ssl/certs
crt-base /etc/ssl/private

#https://ssl-config.mozilla.org/#server=haproxy&server-version=2.0.3&config=intermediate
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-ciphersuites TLS_AES_128_GCM_SHA256:TLS_AES_256_GCM_SHA384:TLS_CHACHA20_POLY1305_SHA256
ssl-default-bind-options ssl-min-ver TLSv1.2 no-tls-tickets

defaults
log global
mode http
option httplog
option dontlognull
timeout connect 5000
timeout client 50000
timeout server 50000
errorfile 400 /etc/haproxy/errors/400.http
errorfile 403 /etc/haproxy/errors/403.http
errorfile 408 /etc/haproxy/errors/408.http
errorfile 500 /etc/haproxy/errors/500.http
errorfile 502 /etc/haproxy/errors/502.http
errorfile 503 /etc/haproxy/errors/503.http
errorfile 504 /etc/haproxy/errors/504.http

At the bottom of the /etc/haproxy/haproxy.cfg file, below the configurations listed above, let’s add some new sections.

  • frontend: Defines a reverse proxy which will listen for incoming requests on a specific IP address and port.
  • backend: Defines a pool of servers that the frontend will forward requests to.
  • listen: A shorthand notation which combines frontend and backend features into a single command

Defining the frontend first, we will allow it to listen on port 80. Open /etc/haproxy/haproxy.cfg configuration file with your preffered editor:

sudo nano /etc/haproxy/haproxy.cfg

Creating a frontend is as simple as this:

frontend desired_frontend_name
bind *:80
default_backend desired_backend_name

You can use either an IP address or an asterisk *, which means any IP address configured on this machine. You can add as many bind directives to frontend as you want. With that in place, our frontend is set and ready to listen. Now let’s go ahead and define a backend for our frontend to send requests to:

backend desired_backend_name
balance roundrobin
server webserver1 webserver1-IP-addr:80 check
server webserver2 webserver2-IP-addr:80 check
option httpchk

The roundrobin load-balancing algorithm is the default if you don’t set the balance directive.

A balance directive can be set in a backend section or globally in the defaults section. If it’s set in the defaults section, it can be overridden within a backend to use a different algorithm.

webserver1 would get the first request. The second would go to webserver2. The third would go back to webserver1, etc. We can add as many server directives as we want to a single backend.

The check parameter added to the webserver1 and webserver2 servers directive instructs haproxy to monitor the health and status of the servers.

A disadvantage of enabling health checks with the check parameter is that success is measured only by the ability to make a TCP connection to the back-end servers IP address and port. So, even if the web servers begins responding with HTTP 500 Internal Server Error, the checks will still pass as long as a connection can be made.

The option httpchk directive tries to ensure that only successful HTTP responses counts and are sent to visitors.

Our final /etc/haproxy/haproxy.cfg configuration file looks like:

global
log /dev/log local0
log /dev/log local1 notice
chroot /var/lib/haproxy
stats socket /run/haproxy/admin.sock mode 660 level admin
stats timeout 30s
user haproxy
group haproxy
daemon

# Default SSL material locations
ca-base /etc/ssl/certs
crt-base /etc/ssl/private

#https://ssl-config.mozilla.org/#server=haproxy&server-version=2.0.3&config=intermediate
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-ciphersuites TLS_AES_128_GCM_SHA256:TLS_AES_256_GCM_SHA384:TLS_CHACHA20_POLY1305_SHA256
ssl-default-bind-options ssl-min-ver TLSv1.2 no-tls-tickets

defaults
log global
mode http
option httplog
option dontlognull
timeout connect 5000
timeout client 50000
timeout server 50000
errorfile 400 /etc/haproxy/errors/400.http
errorfile 403 /etc/haproxy/errors/403.http
errorfile 408 /etc/haproxy/errors/408.http
errorfile 500 /etc/haproxy/errors/500.http
errorfile 502 /etc/haproxy/errors/502.http
errorfile 503 /etc/haproxy/errors/503.http
errorfile 504 /etc/haproxy/errors/504.http

frontend desired_frontend_name
bind *:80
default_backend desired_backend_name

backend desired_backend_name
balance roundrobin
server webserver1 webserver1-IP-addr:80 check
server webserver2 webserver2-IP-addr:80 check
option httpchk

Alternatively, you can use a single listen section as an alternative to having a frontend and backend section.

global
log /dev/log local0
log /dev/log local1 notice
chroot /var/lib/haproxy
stats socket /run/haproxy/admin.sock mode 660 level admin
stats timeout 30s
user haproxy
group haproxy
daemon

# Default SSL material locations
ca-base /etc/ssl/certs
crt-base /etc/ssl/private

#https://ssl-config.mozilla.org/#server=haproxy&server-version=2.0.3&config=intermediate
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-ciphersuites TLS_AES_128_GCM_SHA256:TLS_AES_256_GCM_SHA384:TLS_CHACHA20_POLY1305_SHA256
ssl-default-bind-options ssl-min-ver TLSv1.2 no-tls-tickets

defaults
log global
mode http
option httplog
option dontlognull
timeout connect 5000
timeout client 50000
timeout server 50000
errorfile 400 /etc/haproxy/errors/400.http
errorfile 403 /etc/haproxy/errors/403.http
errorfile 408 /etc/haproxy/errors/408.http
errorfile 500 /etc/haproxy/errors/500.http
errorfile 502 /etc/haproxy/errors/502.http
errorfile 503 /etc/haproxy/errors/503.http
errorfile 504 /etc/haproxy/errors/504.http

listen desired_name
bind *:80
balance roundrobin
server webserver1 webserver1-IP-addr:80 check
server webserver2 webserver2-IP-addr:80 check
option httpchk

Verify if your configuration file is valid with this command

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

Now that all is set, restart the haproxy service:

sudo service haproxy restart

Note

1. It is advisable to ensure that no conflicting software (e.g. nginx or apache2) listens on 80 to avoid launch failures.

2. If you would like to monitor live traffic that passes through HAProxy, enable debugging with the -d flag.

haproxy -f /etc/haproxy/haproxy.cfg -d

--

--