HAProxy is a versatile piece of software that can simplify some common web service headaches and it compiles down to a single binary file. Best of all, it’s free to use! In this post I’ll talk about what HAProxy is generally used for, my use case for it, and how to build and install it yourself.

What is this?

HAProxy is a software load balancer - meaning that it distributes network traffic between different servers. It can operate at L4 or L7 of the network stack offering great flexibility for web applications. While it is similar it is not exactly a web server. HAProxy is not made to do things like directly run dynamic webpages the way Apache and Nginx can, but it can work in tandem with these applications.

What do I need with HAProxy?

I run a few different web services from home. There’s nothing fancy or critical among them but they do all use ports 80 and/or 443. Like most of the world, at home I am on a private network which uses non-routeable IP addresses. A router handles NAT with my ISP and the outside world. If you have ever dealt with port forwarding on a consumer router you may see my problem. I can normally only forward ports 80 and 443 to a single IP address on the internal network. This means keeping web services on non-standard ports or creating multiple virtualhost configurations with reverse proxy definitions on one of the web servers to route services around. Especially because of the prevalence of SSL this created some complicated definitions for me to keep track of and just added complexity to the maintenance of these few simple services I like to maintain for some family and friends. Before I show you how HAProxy solved this problem for me, let’s look at how to install it on Ubuntu 18.04 (though it will be largely the same on 20.04 and other releases).

Installing HAProxy

I will be explaining how to build HAProxy from source on Ubuntu 18.04 because this will give us the most control and latest features, but if you would prefer to use apt there is a guide on the Ubuntu Community Wiki.

First you’ll need to get the HAProxy source, which they keep a mirror of on GitHub. The instructions for building are contained in the INSTALL file there, but I’ll walk through the steps I took.

As with all source builds you’ll need to get your libraries and headers installed - I’m sure I’ll make a more in-depth post on this later but for now these are the commands you’ll want to run to get everything ready:

sudo apt update
sudo apt install build-essential git libssl-dev liblua5.3-dev libsystemd-dev libpcre3-dev zlib1g-dev

These two commands will update your apt package lists and install the packages required for the parameters we’re going to build with (plus git in case you don’t have it). Next you’ll need the source code itself, and I’d recommend working on the latest release branch or tag. At the time of this writing v2.2 is still in dev, so I am using v2.1.0 as the tag to checkout.

git clone https://github.com/haproxy/haproxy.git
cd haproxy
git checkout v2.1.0

Update May 5, 2021

In the year since I wrote this article I’ve worked a lot more with HAProxy in production. In looking at how to update and redeploy specific versions I’ve learned that the HAProxy team does not track minor stable release updates in their GitHub mirror. I recommend grabbing their latest stable tarball and installing from that if you’re going to use HAProxy in production. This will make sure you have their latest security fixes. Here’s how that looks compared to the above for version 2.3.10, the latest as of today:

wget https://www.haproxy.org/download/2.3/src/haproxy-2.3.10.tar.gz
tar xzf haproxy-2.3.10.tar.gz
cd haproxy

I’ll be updating the No Fluff guide to reflect this method and I talk a little bit more about this in my recent update.

At this point you have everything you need to build the software, I used the following command:

make -j2 TARGET=linux-glibc USE_TFO=1 USE_OPENSSL=1 USE_ZLIB=1 USE_LUA=1 USE_PCRE=1 USE_SYSTEMD=1

For details on each of the flags chosen please look at the INSTALL file I linked above, but for the highlights:

  • -j2 specifies two threads for compiling, this is optional. You can use larger values of j if you have spare processing cores available, but this will take result in more memory usage and obviously more CPU utilization while the software builds.

  • USE_TFO enables TCP Fast Open

  • USE_OPENSSL enables TLS/SSL support

  • USE_SYSTEMD provides better integration with systemd and I run this as a systemd service

Once it is done compiling you will find the haproxy binary in the directory, ready to execute with ./haproxy and any parameters you provide. If you want to experiment with the application this is a great time and place to do so, because you still have not installed it to the system. If you complete the installation it will add the documentation to your man pages, so I recommend it:

sudo make install

At this point, you’ll find haproxy is in your path (/usr/local/bin with the params we used above) and you can run it simply by typing haproxy.

What’s next?

The program still requires a configuration file and for it to start on boot you’ll want to define a systemd unit. I’ll go over all that and explain how this has simplified my web services configuration at home in Part 2.