How to install and configure haproxy on Linux Ubuntu Debian

haproxy is one of the best known and widely used Open Source load balancers out there and a strong competitor to nginx.  

haproxy is used by many large sites per Wikipedia:

HAProxy is used by a number of high-profile websites including GoDaddy, GitHub, Bitbucket,[6] Stack Overflow,[7] Reddit, Slack,[8] Speedtest.net, Tumblr, Twitter[9][10] and Tuenti[11] and is used in the OpsWorks product from Amazon Web Services.[12]

 

According to some stats data haproxy is even more popular than the AWS Elastic Load Balancer:

 

Step 1 - Install

apt install haproxy
Reading package lists... Done
Building dependency tree       
Reading state information... Done
The following packages were automatically installed and are no longer required:
  acl ebtables galera-3 git git-man iproute2 less libatm1 libconfig-inifiles-perl libdbd-mysql-perl libdbi-perl liberror-perl libjemalloc1 liblzo2-2 libuv1 lsof
  mariadb-common netcat netcat-traditional patch pigz runc socat squashfs-tools ubuntu-fan xdelta3
Use 'apt autoremove' to remove them.
Suggested packages:
  vim-haproxy haproxy-doc
The following NEW packages will be installed:
  haproxy
0 upgraded, 1 newly installed, 0 to remove and 34 not upgraded.
Need to get 1116 kB of archives.
After this operation, 2374 kB of additional disk space will be used.
Get:1 http://archive.ubuntu.com/ubuntu bionic-updates/main amd64 haproxy amd64 1.8.8-1ubuntu0.13 [1116 kB]
Fetched 1116 kB in 2s (657 kB/s)  
perl: warning: Setting locale failed.
perl: warning: Please check that your locale settings:
    LANGUAGE = (unset),
    LC_ALL = (unset),
    LANG = "C.UTF-8"
    are supported and installed on your system.
perl: warning: Falling back to the standard locale ("C").
locale: Cannot set LC_CTYPE to default locale: No such file or directory
locale: Cannot set LC_MESSAGES to default locale: No such file or directory
locale: Cannot set LC_ALL to default locale: No such file or directory
Selecting previously unselected package haproxy.
(Reading database ... 20143 files and directories currently installed.)
Preparing to unpack .../haproxy_1.8.8-1ubuntu0.13_amd64.deb ...
Unpacking haproxy (1.8.8-1ubuntu0.13) ...
Setting up haproxy (1.8.8-1ubuntu0.13) ...
Created symlink /etc/systemd/system/multi-user.target.wants/haproxy.service → /lib/systemd/system/haproxy.service.
invoke-rc.d: could not determine current runlevel
invoke-rc.d: WARNING: No init system and policy-rc.d missing! Defaulting to block.
Processing triggers for systemd (237-3ubuntu10.57) ...

 

Step 2 - Configure haproxy.cfg file


vi /etc/haproxy/haproxy.cfg

Here is how the defaults of haproxy.cfg look:

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

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

        # Default ciphers to use on SSL-enabled listening sockets.
        # For more information, see ciphers(1SSL). This list is from:
        #  https://hynek.me/articles/hardening-your-web-servers-ssl-ciphers/
        # An alternative list with additional directives can be obtained from
        #  https://mozilla.github.io/server-side-tls/ssl-config-generator/?server=haproxy
        ssl-default-bind-ciphers ECDH+AESGCM:DH+AESGCM:ECDH+AES256:DH+AES256:ECDH+AES128:DH+AES:RSA+AESGCM:RSA+AES:!aNULL:!MD5:!DSS
        ssl-default-bind-options no-sslv3

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

 

More info about configuring haproxy from the authors.

 

Let's add a frontend and backend

At the moment the load balancer does nothing and essentially has no usable configuration.  We're going to add a frontend that listens on localhost and is bound to port 8080.

The frontend itself is just the entry point for the user, the frontend is configured on a certain IP and port that we define and the next step is that we'll have to define a "backend" that is the actual source server (eg. our Apache running PHP or another application)

Add this frontend and backend config to the end of haproxy.cfg

frontend rttfrontend
  bind 0.0.0.0:8080
  default_backend rttbackendservers

backend rttbackendservers
  server backendserver01 127.0.0.1:80

 cache rttcache
   # Total size of the cache in MB
   total-max-size 500

   # Max size of any single item in bytes
   max-object-size 100000

   # Time to live for each item in seconds
   # This can be overridden with a Cache-Control header
   max-age 3000

This config allows you to scale out as much as you need, for example you could add dozens or hundreds of backend servers with different IPs and ports.

You may also want to add the "check" option after each server so requests won't be sent to dead or overloaded servers:

server rttbackendserver01 server.com:9000 check

We can make it more like a CDN by enabling cache, so the backend servers don't need to be contacted if we have a cache hit:

cache rttcache
   # Total size of the cache in MB
   total-max-size 500

   # Max size of any single item in bytes
   max-object-size 10000

   # Time to live for each item in seconds
   # This can be overridden with a Cache-Control header
   max-age 3000

 

In older versions like 1.8, the max-object-size option does not exist.

You'll find the cache doesn't work unless you set this option in your global config:

tune.bufsize 9999999

Here is an example of how much performance can be gained by using a caching frontend haproxy server:

In our first example below the page in question has not been cached and has a TTFB of 0.486955 seconds and total load time of .677587 seconds.

curl -k -o /dev/null -w "Connect: %{time_connect} TTFB: %{time_starttransfer} Total time: %{time_total} \n" $site
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100 16413  100 16413    0     0  24243      0 --:--:-- --:--:-- --:--:-- 24207
Connect: 0.047765 TTFB: 0.486955 Total time: 0.677587

Now after we loaded the site and it is in the cache notice the difference in performance:

TTFB is now 0.090424 and total load time of .135752

TTFB is now 5.38X faster and load time was 4.99X faster!

curl -k -o /dev/null -w "Connect: %{time_connect} TTFB: %{time_starttransfer} Total time: %{time_total} \n" $site
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100 16413  100 16413    0     0   118k      0 --:--:-- --:--:-- --:--:--  118k
Connect: 0.044437 TTFB: 0.090424 Total time: 0.135752

 

How To enable Stats
 

By enabling stats we can check on things like how our cache is doing:

Add this to the globa section:

    stats socket ipv4@127.0.0.1:9999 level admin
    stats socket /var/run/hapee-lb.sock mode 666 level admin

 

You can echo commands via socat to see the status of things like you cache:

echo "show cache" | socat stdio /var/run/hapee-lb.sock
0x7f5f1ef9503a: rtt (shctx:0x7f5f1ef95000, available blocks:512000)
0x7f5f1ef950ac hash:3598866029 size:16657 (17 blocks), refcount:0, expire:25695

 

Here is a list of commands that can be sent:

echo "help" | socat stdio /var/run/hapee-lb.sock
Unknown command. Please enter one of the following commands only :
  help           : this message
  prompt         : toggle interactive mode with prompt
  quit           : disconnect
  show tls-keys [id|*]: show tls keys references or dump tls ticket keys when id specified
  set ssl tls-key [id|keyfile] : set the next TLS key for the or listener to
  show errors    : report last request and response errors for each proxy
  disable agent  : disable agent checks (use 'set server' instead)
  disable health : disable health checks (use 'set server' instead)
  disable server : disable a server for maintenance (use 'set server' instead)
  enable agent   : enable agent checks (use 'set server' instead)
  enable health  : enable health checks (use 'set server' instead)
  enable server  : enable a disabled server (use 'set server' instead)
  set maxconn server : change a server's maxconn setting
  set server     : change a server's state, weight or address
  get weight     : report a server's current weight
  set weight     : change a server's weight (deprecated)
  show sess [id] : report the list of current sessions or dump this session
  shutdown session : kill a specific session
  shutdown sessions server : kill sessions on a server
  clear table    : remove an entry from a table
  set table [id] : update or create a table entry's data
  show table [id]: report table usage stats or dump this table's contents
  clear counters : clear max statistics counters (add 'all' for all counters)
  show info      : report information about the running process
  show stat      : report counters for each proxy and server
  show schema json : report schema used for stats
  show startup-logs : report logs emitted during HAProxy startup
  show resolvers [id]: dumps counters from all resolvers section and
                     associated name servers
  set maxconn global : change the per-process maxconn setting
  set rate-limit : change a rate limiting value
  set severity-output [none|number|string] : set presence of severity level in feedback information
  set timeout    : change a timeout setting
  show env [var] : dump environment variables known to the process
  show cli sockets : dump list of cli sockets
  show fd [num] : dump list of file descriptors in use
  show activity : show per-thread activity stats (for support/developers)
  disable frontend : temporarily disable specific frontend
  enable frontend : re-enable specific frontend
  set maxconn frontend : change a frontend's maxconn setting
  show servers state [id]: dump volatile server information (for backend )
  show backend   : list backends in the current running config
  shutdown frontend : stop a specific frontend
  set dynamic-cookie-key backend : change a backend secret key for dynamic cookies
  enable dynamic-cookie backend : enable dynamic cookies on a specific backend
  disable dynamic-cookie backend : disable dynamic cookies on a specific backend
  show cache     : show cache status
  add acl        : add acl entry
  clear acl : clear the content of this acl
  del acl        : delete acl entry
  get acl        : report the patterns matching a sample for an ACL
  show acl [id]  : report available acls or dump an acl's contents
  add map        : add map entry
  clear map : clear the content of this map
  del map        : delete map entry
  get map        : report the keys and values matching a sample for a map
  set map        : modify map entry
  show map [id]  : report available maps or dump a map's contents
  show pools     : report information about the memory pools usage


Tags:

install, configure, haproxy, linux, ubuntu, debianhaproxy, widely, balancers, competitor, nginx, aws, balancer, apt, lists, dependency, packages, automatically, installed, acl, ebtables, galera, git, iproute, libatm, libconfig, inifiles, perl, libdbd, mysql, libdbi, liberror, libjemalloc, liblzo, libuv, lsof, mariadb, netcat, pigz, runc, socat, squashfs, xdelta, autoremove, vim, upgraded, newly, kb, archives, additional, disk, http, archive, bionic, updates, amd, fetched, locale, settings, unset, lc_all, lang, quot, utf, supported, lc_ctype, default, directory, lc_messages, selecting, previously, unselected, database, directories, currently, preparing, unpack, haproxy_, _amd, deb, unpacking, symlink, etc, systemd, multi, user, rarr, lib, invoke, rc, determine, runlevel, init, defaulting, processing, triggers, cfg, vi, defaults, global, dev, chroot, var, stats, socket, admin, mode, fd, listeners, timeout, daemon, ssl, locations, ca, certs, crt, ciphers, enabled, sockets, https, hynek, articles, hardening, servers, directives, obtained, mozilla, github, io, server, tls, config, generator, bind, ecdh, aesgcm, dh, aes, rsa, anull, md, dss, sslv, httplog, dontlognull, errorfile, errors, info, configuring, authors, frontend, backend, essentially, usable, configuration, listens, localhost, entry, configured, ip, define, ll, eg, apache, php, rttfrontend, default_backend, rttbackendservers, backendserver, allows, dozens, ips, ports, cdn, enabling, cache, contacted, rttcache, mb, bytes, overridden, header,

Latest Articles

  • FreePBX 17 How To Add a Trunk
  • Docker Container Onboot Policy - How to make sure a container is always running
  • FreePBX 17 How To Add Phones / Extensions and Register
  • Warning: The driver descriptor says the physical block size is 2048 bytes, but Linux says it is 512 bytes. solution
  • Cisco How To Use a Third Party SIP Phone (eg. Avaya, 3CX)
  • Cisco Unified Communication Manager (CUCM) - How To Add Phones
  • pptp / pptpd not working in DD-WRT iptables / router
  • systemd-journald high memory usage solution
  • How to Install FreePBX 17 in Linux Debian Ubuntu Mint Guide
  • How To Install Cisco's CUCM (Cisco Unified Communication Manager) 12 Guide
  • Linux Ubuntu Redhat How To Extract Images from PDF
  • Linux and Windows Dual Boot Issue NIC Won't work After Booting Windows
  • Cisco CME How To Enable ACD hunt groups
  • How to install gns3 on Linux Ubuntu Mint
  • How to convert audio for Asterisk .wav format
  • Using Cisco CME Router with Asterisk as a dial-peer
  • Cisco CME How To Configure SIP Trunk VOIP
  • Virtualbox host Only Network Error Failed to save host network interface parameter - Cannot change gateway IP of host only network
  • Cisco CME and C7200 Router Testing and Learning Environment on Ubuntu 20+ Setup Tutorial Guide
  • Abusive IP ranges blacklist