How To Secure HAProxy with Let's Encrypt

Combine fullchain.pem and privkey.pem

DOMAIN='example.com' ; sudo -E bash -c 'cat /usr/local/etc/letsencrypt/live/$DOMAIN/fullchain.pem /usr/local/etc/letsencrypt/live/$DOMAIN/privkey.pem > /usr/local/etc/haproxy/$DOMAIN.pem'

The first thing we want to add is a frontend to handle incoming HTTP connections, and send them to a default backend (which we’ll define later). At the end of the file, let’s add a frontend called www-http.

frontend www-http
   bind <haproxy_www_public_IP>:80
   reqadd X-Forwarded-Proto:\ http
   default_backend www-backend

Next, we will add a frontend to handle incoming HTTPS connections. At the end of the file, add a frontend called www-https - enabling HTTP/2 and alpn extensions also.

frontend www-https
   bind <haproxy_www_public_IP>:443 ssl crt /usr/local/etc/haproxy/$DOMAIN.pem alpn h2,http/1.1
   reqadd X-Forwarded-Proto:\ https
   acl letsencrypt-acl path_beg /.well-known/acme-challenge/
   use_backend letsencrypt-backend if letsencrypt-acl
   default_backend www-backend
backend www-backend
   redirect scheme https if !{ ssl_fc }
   server www-1 www_1_private_IP:80 check
   server www-2 www_2_private_IP:80 check
backend letsencrypt-backend
   server letsencrypt 127.0.0.1:54321
service haproxy restart

Then create /usr/local/bin/renew.sh script file:

#!/bin/sh

DOMAIN=example.com

# move to the correct let's encrypt directory
cd /usr/local/etc/letsencrypt/live/$DOMAIN

# cat files to make combined .pem for haproxy
cat fullchain.pem privkey.pem > /usr/local/etc/haproxy/$DOMAIN.pem

# reload haproxy
service haproxy reload
chmod u+x /usr/local/bin/renew.sh

Edit with your favorite text editor the file /usr/local/etc/letsencrypt/renewal/$DOMAIN.conf and add or change the line like following:

http01_port = 54321

Test the whole configuration executing:

certbot renew --dry-run

Then add the crontab entry like:

30 2 * * * /usr/local/bin/certbot renew --renew-hook "/usr/local/bin/renew.sh" > /dev/null

Source: digitalocean.com