HAProxy and Lets Encrypt

Secure HAProxy with Let’s Encrypt

I currently run Octoprint on a Raspberry Pi that is hooked up to be 3D printer. This setup uses HAProxy to provider the web front end for the user.  I am in the process of securing all my systems so they use SSL (https) and I this article documents how I added SSL to HSProxy using a Let’s Encrypt certificate. 

 

If you are not faliliar with Let’s Encrypt and use SSL certificates, you should check it out.  They provide free SSL certificates.  What’s the catch?  They just need to be automated so that the renewal can happen automatically.  Once you get it all setup. it is perfect.  You can renew your certificate when needed and have it installed all automatically.

My Octoprint system is running on a Raspberry Pi running Raspbian (Stretch Lite).  This version doesn’t come with NSUpdate installed by default.  We need to install it first.

# sudo apt-get update
# sudo apt-get install dnsutils

Next install the acme.sh client used Let’s Encrypt.  There are a lot of clients that will work with Let’s Encrypt.  I picked acme.sh because it is very portable and works on most systems and it supports the DNS-01 protocal that I use with Let’s Encrypt.

$ sudo -i
# cd /home/pi
# wget https://github.com/Neilpang/acme.sh/archive/master.tar.gz
# tar xvf master.tar.gz
# cd acme.sh-master/
# ./acme.sh --install --nocron --home /usr/local/share/acme.sh --accountemail "email@gmailcom"

Create the directory user HAProxy to hold the certificates 

$ sudo -i
# mkdir -p /etc/haproxy/certs
# chmod -R g-rw,o-rw /etc/haproxy/certs

Edit the HAProxy config file

$ sudo -i
# vi /etc/haproxy/haproxy.cfg

Add in the following lines into the correct sections

Add into the global section
      tune.ssl.default-dh-param 2048
All into the frontend public section 
     bind *:443 ssl crt /etc/haproxy/certs/haproxy.pem

HAProxy is a little odd in what it expects in the certificate file.  It wants all the certificates as well as the private key all in the same file.  Create the following script to generate the correct file and restart the service.  This script will be run right after a certificate is fetched or updated.

$ sudo -i
# cd /usr/local/share/acme.sh
# vi haproxyCert.sh

The haproxyCert.sh file should contain the following:

#!/bin/bash
DOMAIN="server.example.com"
cat /usr/local/share/acme.sh/${DOMAIN}/fullchain.cer /usr/local/share/acme.sh/${DOMAIN}/${DOMAIN}.key > /etc/haproxy/certs/haproxy.pem
service haproxy restart

If all goes good, you should be able to run the following command and it will fetch the new certificate and install it.

$ sudo -i
# /usr/local/share/acme.sh/acme.sh --issue --nocron --dns dns_nsupdate -d "server.example.com"  \
      --home /usr/local/share/acme.sh/  --reloadcmd /usr/local/share/acme.sh/haproxyCert.sh

New let’s make it happen automatically.  Edit the crontab and add in the following line at the bottom.  This line tell acme.sh to check the certificate every friday night at 3:10am.  If the certificate needs to be renewed, then it will.

10 3 * * 5 root /usr/local/share/acme.sh/acme.sh --cron --dns dns_nsupdate --home /usr/local/share/acme.sh/ --reloadcmd /usr/local/share/acme.sh/haproxyCert.sh

 

 

 

Leave a Comment

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