Installing and updating HAProxy with HTTP/3 from source on Ubuntu

One of the tools that I use for my personal websites, including this blog, is haproxy. Here are some distilled instructions for installing it from source. I primarily use Ubuntu.

The center of all this is a series of shell scripts that I use to automate the build and install. At the following gitlab URL you will find all the scripts:

Clone the repo with https. If you want to use ssh, you will have to create an account on the gitlab server and I probably need to explicitly grant rights to your account. I use ~/git/haproxy-scripts as the working directory.

These scripts use sudo, so you can either run them as root or as a user with sudo rights.

There is a script included that will do all the prep tasks and install prerequisite packages. It has been tested on Ubuntu Server and AlmaLinux 8, but should work on any RHEL/Fedora clone and all distros derived from Debian, which includes Ubuntu, Mint, and of course Debian. If you have some other OS, you may need to examine the prep_source script and work out what to do for your OS. On Debian-derived systems, the prep_source script will make some carefully tested changes to the file /etc/apt/sources.list in order to add source repositories. That modification should be safe for all users of Debian-derived systems, but it can’t be 100% guaranteed. It will also install and start docker.

The first time you run through these instructions, you’ll need to do the commands below to prepare the source directory and install/activate the haproxy service in systemd. After the first time, you can skip to the wide horizontal line below to update or reinstall.

cd /path/to/cloned/git/repo
./install-haproxy-service git-haproxy-2.7

If your OS is using some form of sysvinit, The service installer script in the commands above will almost certainly fail to install the haproxy service. You’re on your own for getting that done. Consider switching to something better. Many modern POSIX operating systems are using systemd because it’s more robust than the old sysvinit. There are likely service install instructions for sysvinit that Google can find. The script will not start the service, as that gets handled later as part of the build.

With the git repos cloned, prerequisite packages installed, and the service installed, run the fullstack command. It will build/install the latest quictls openssl and the latest haproxy dev version, then restart haproxy.


If you haven’t created /etc/haproxy/haproxy.cfg with a good config before running fullstack, then starting the service will fail, and you’ll need to take care of installing a config before trying to start the service. Also be aware that if you ask haproxy to listen on ports that another process is already listening on, the service start will also fail. This can be a problem if you have a webserver like Apache or Nginx installed.

There is a VERY simple bare-bones haproxy config in the repo named ci-haproxy.cfg … it is definitely not complete enough for a full production config, but can be a good starting point. There are many posts around the Internet that offer info about creating an haproxy config.

Updates to quictls are infrequent, so most of the time you just need to upgrade haproxy. The fullstack script will compile and install both quictls and haproxy. If you use the new-haproxy script, only haproxy will be recompiled. Use a command like the following to do this:

./new-haproxy git-haproxy-master

This will restart the haproxy service if the build and install are successful.

Installing quictls with my script adds a “qssl” script to /usr/local/bin that will run the quictls variant of openssl that it installs. This is done so that it does not interfere with the stock openssl command.

I have haproxy listening on ports 80 and 443, and Apache listening on port 81 only. I also have backends for Plex, Gitlab, and and a few other things.

For the most part, I have disabled TLS on the back end services. I had to leave TLS enabled on the Plex backend. None of the backends other than Plex are reachable from the Internet, and Plex is only available because that’s what Plex requires to work properly, so they have taken steps to make it secure.

QUIC/HTTP3 will require both UDP and TCP traffic allowed on port 443. QUIC/HTTP3 is a UDP protocol, but the first time the browser makes contact, it will be over TCP.

The git repo includes a config file for gitlab that sets up a CI/CD pipeline. It requires a gitlab-runner configured for shell.

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.