HAProxy

Release date: December 28th 2020

Welcome to my HAProxy section. As part of my VMware Unified Access Gateway and Workspace ONE Access set up, I saw the need for a load balancing mechanism in my lab. As I don’t have a high-end Load Balancer easily available in my lab, I did some googling and found a very good open- source alternative, HAProxy. Below I will describe how I installed and configured HAProxy on an Ubuntu 20.04 server. As I’m in no sense a Linux-expert, this has been planned for quite some while and I will be using Snapshots to ensure I have a fallback if anything goes wrong during the installation. My design will look like this:

The first thing I have to do is to create a virtual machine for this role. This I have documented here: HAProxy Virtual Machine Set Up

Next, I will install Ubuntu Server 20.04 in my virtual machine, documented here: HAProxy OS Installation

Finally, I can install and configure HAProxy with LetsEncrypt. First of all, I’m going to update the system packages:

sudo apt-get update

sudo apt-get upgrade

Next, I enable the PPA Repository for HAProxy and install it. For this set up I’m using the 2.1 version. The latest versions and builds are available here: HAProxy

sudo apt-get install software-properties-common

sudo add-apt-repository ppa:vbernat/haproxy-2.1

sudo apt-get update

sudo apt-get install haproxy=2.1.\*

As I mentioned to begin with, I’m no Linux expert. Therefore I prefer to take some snapshots during the setup, which gives me the opportunity to roll back if I run into problems further into the set up. I will document at what point I take the snapshots below. All snapshots are taken with the VM shutdown

SNAPSHOT: Post-HAProxy-Installation

Now that HAProxy is installed, I can continue with installing LetsEncrypt

sudo add-apt-repository -y ppa:certbot/certbot

sudo add-apt-repository -y ppa:certbot/certbot

sudo apt-get update

sudo apt-get install -y certbot

SNAPSHOT: Post-LetsEncrypt-Installation

Now I can request a new certificate for my HAProxy. Before I do this I make sure I have a public DNS pointer in place and the appropriate NAT/Port openings in my firewall. I will be using DNS challenge for my LetsEncrypt renewals, as I don’t want to open port 80 whenever I will do renewals.

sudo certbot -d desktop.frelab.net --manual --preferred-challenges dns certonly

When I run this command I will be represented with at text-string to put in a TXT-pointer in my public DNS Zone. Lets Encrypt now gives me a SSL Certificate in 2 files. As HAProxy requires 1 .pem file I have to merge the certificate-files using the following commands:

First I make a folder to store my certificate

sudo mkdir -p /etc/ssl/desktop.frelab.net

Next I merge the two files into my certificate “/etc/ssl/desktop.frelab.net/desktop.frelab.net.pem

sudo cat /etc/letsencrypt/live/desktop.frelab.net/fullchain.pem \
  /etc/letsencrypt/live/desktop.frelab.net/privkey.pem \
| sudo tee /etc/ssl/desktop.frelab.net/desktop.frelab.net.pem

As it is a tedious task to renew certificates, I will create a CRON-job which will automatically renew my certificate. First I will edit the CRON job LetsEncrypt created during installation.

sudo nano /etc/cron.d/certbot

I will run a script on the first day of every month. I replace the current content with the following line

0 0 1 * * root bash /opt/update-certs.sh

Now I need to create the script that I specified in the CRON job above.This script will basically run all the commands needed to renew the certificate and merge it to one PEM-file.

sudo nano /opt/update-certs.sh

I add the following lines to the script

#!/usr/bin/env bash
certbot renew --force-renewal --tls-sni-01-port=8888 (This will renew the certificate)
bash -c "cat /etc/letsencrypt/live/desktop.frelab.net/fullchain.pem /etc/letsencrypt/live/desktop.frelab.net/privkey.pem > /etc/ssl/desktop.frelab.net/desktop.frelab.net.pem" (This will merge the certificate-files to one PEM-file)

SNAPSHOT: Post-LetsEncrypt-Certificate

Finally I configure my haproxy.cfg file to be using the LetsEncrypt certificate. This is my complete haproxy config: haproxy.cfg

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
ca-base /etc/ssl/certs
crt-base /etc/ssl/private
ssl-default-bind-ciphers ECDH+AESGCM:DH+AESGCM:ECDH+AES256:DH+AES256:ECDH+AES128:DH+AES:RSA+AESGCM:RSA+AES:!aNULL:!MD5$
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

frontend ssl
bind 10.0.100.10:443 ssl crt /etc/ssl/desktop.frelab.net/desktop.frelab.net.pem
acl letsencrypt-acl path_beg /.well-known/acme-challenge/
use_backend letsencrypt-backend if letsencrypt-acl
redirect scheme https code 301 if !{ ssl_fc }
mode http
default_backend ssl

backend ssl
mode http
balance source        (IT IS IMPORTANT TO SET SOURCE AS UAG WON'T WORK WITH ROUND ROBIN)
option forwardfor
server hz-uag-01 10.0.100.11:443 check ssl verify none
server hz-uag-02 10.0.100.12:443 check ssl verify none

backend letsencrypt-backend
server letsencrypt 127.0.0.1:8888

listen stats
bind 10.0.100.10:1936
stats enable
stats hide-version
stats refresh 30s
stats show-node
stats auth stats:password
stats uri /stats

Now that have made all necessary changes in my HAProxy set up, I will verify my set up before restarting the HAProxy service

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

sudo service haproxy restart

This completes my HAProxy set up. I have now tested and verified that everything works as per my design. I can now delete my snapshots and add the new server to my backup jobs. As an Open Source Load Balancer this more than delivers on my requirements. I’m aware that I’m not even close to using all of the potential of HAProxy, but it works like a charm in my lab.

Recommended reading:

koromicha’s post at kifarunix.com: Install and Setup HAProxy on Ubuntu 20.04

Dean Longstaff’s post: HAProxy as Reverse Proxy + SSL Termination

Rahul’s post at techadmin.net: How to Setup HAProxy Load Balancer on Ubuntu 18.04 & 16.04

HAProxy Home Page

Disclaimer: Every tips/tricks/posting I have published here, is tried and tested in different it-solutions. It is not guaranteed to work everywhere, but is meant as a tip for other users out there. Remember, Google is your friend and don’t be afraid to steal with pride! Feel free to comment below as needed.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

%d bloggers like this: