Skip to Content

setup-ssl-for-haproxy-with-certbot

Here’s how to automatically setup SSL Certificates for HAProxy using certbot and Let’s Encrypt, without having to restart HAProxy.

This article assumes that you have certbot already installed and HAProxy already running.

Certbot command

As we are using HAProxy, we can’t just run sudo certbot –haproxy like for nginx because certbot doesn’t officially support HAProxy, yet. Instead we have to use the certonly command and the –standalone option to run a standalone webserver.

We also want to include the certbot command in a script later on, so we need to supply all further options via the command line. The basic certbot command we will use, looks like this (assume we use port 9785 for auth):

#!/bin/bash

# This script takes a list of domains as arguments
# and will setup a single certificate for all of them.

cert_name="www.example.com"
haproxy_cert_dir="/etc/haproxy/ssl-certs"
email="yourname@example.com"

domains=""
for domain in "$@"
do
  domains+="-d $domain "
done

certbot certonly --standalone --agree-tos --non-interactive \
-m $email --preferred-challenges http \
--http-01-port 9785 --cert-name $cert_name \
--renew-with-new-domains --keep-until-expiring $domains

mkdir -p $haproxy_cert_dir

# Combine the certificate chain and private key and put it
# into the correct HAProxy directory
cd /etc/letsencrypt/live/$cert_name
cat fullchain.pem privkey.pem > "$haproxy_cert_dir/cert.pem"

echo "Reloading haproxy"
sudo systemctl reload haproxy

The HAProxy configuration

Here we assume the backend app running at 127.0.0.1:9000

global
    log         127.0.0.1 local2

    chroot      /var/lib/haproxy
    pidfile     /var/run/haproxy.pid
    maxconn     4000
    user        haproxy
    group       haproxy
    daemon

    stats socket /var/lib/haproxy/stats

    tune.ssl.default-dh-param 2048

defaults
    mode                    http
    log                     global
    option                  httplog
    option                  dontlognull
    option http-server-close
    option forwardfor       except 127.0.0.0/8
    option                  redispatch
    retries                 3
    timeout http-request    10s
    timeout queue           1m
    timeout connect         10s
    timeout client          1m
    timeout server          1m
    timeout http-keep-alive 10s
    timeout check           10s
    maxconn                 3000


frontend  http-in
    mode http
    maxconn 4000
    bind :80
    log global
    option httplog
    bind *:443 ssl crt /etc/haproxy/ssl-certs/cert.pem
    reqadd X-Forwarded-Proto:\ https

    acl letsencrypt-req path_beg /.well-known/acme-challenge/
    use_backend letsencrypt if letsencrypt-req
    use_backend base-server

backend base-server
    mode http
    server      web01 127.0.0.1:9000 

backend letsencrypt
    mode http
    server letsencrypt 127.0.0.1:9785

Setup cronjob

Next, we will save the script at /root/cert_renew.sh and setup the cronjob, so that it runs twice per day:

37 11,22 * * * /root/cert_renew.sh www.example.com 2>&1 | /usr/bin/logger -t certbot

Sources:

This post builds on a few other blog posts which have been really helpful. These are:

Setting up SSL Certificates for HAProxy with certbot