Overview
We’ll go through the steps how to install Let’s Encrypt SSL on HAProxy. Aside from installing and configuring haproxy with Let’s encrypt certbot and acquiring ssl, we are also going to cover how to renew the certificate automatically. The written instructions are performed on GNU/Linux servers(Debian in this case).
Prerequisites:
- HAProxy installed
- Cerbot installed
Note: HAProxy and Certbot are installed on the same server in this example.
If you need more information to understand how the HAProxy works, you can check this post where we explained how haproxy works and went through the example configuration, where we explained the configuration in detail.
Install Let’s Encrypt SSL on HAProxy
HAProxy SSL configuration
HAProxy needs to be configured in order to be able to acquire the SSL certificate, meaning to pass-through the Certbot requests and to enforce the HTTPS protocol.
One example of the configuration looks something like this:
frontend haproxy
#public IP address binded
bind 123.123.123.123:80
bind 123.123.123.123:443 ssl crt /etc/ssl/example.com.pem
# HTTPS redirect
redirect scheme https code 301 if !{ ssl_fc }
mode http
default_backend test_site
acl letsencrypt-acl path_beg /.well-known/acme-challenge/
use_backend letsencrypt-backend if letsencrypt-acl
backend test_site
mode http
server test_site1 10.0.51.11:80 check inter 5s rise 3 fall 2
server test_site2 10.0.51.12:80 check backup inter 5s rise 3 fall 2
backend letsencrypt-backend
server letsencrypt 123.123.123.123:80
And we will through the configuration and explain it.
First we defined the haproxy frontend:
frontend haproxy
#public IP address binded
bind 123.123.123.123:80
bind 123.123.123.123:443 ssl crt /etc/ssl/example.com.pem
For this example, on the frontend we binded the public IP address and the ports 80 and 443 for the HTTP and HTTPS. Private IP address can also be binded. We also defined
on 443 port bind where’s the ssl certificate located on our HAProxy server machine and the file name of the ssl certificate.
\# HTTPS redirect
redirect scheme https code 301 if !{ ssl_fc }
This command forces the https redirect all the time.
mode http
default_backend test_site
acl letsencrypt-acl path_beg /.well-known/acme-challenge/
use_backend letsencrypt-backend if letsencrypt-acl
Here we have defined a name for our backend servers and instructed Haproxy to use Let’s encrypt backend server, which is also defined, if it detects the acme challenge from Let’s encrypt for the domain name.
backend test_site
mode http
server test_site1 10.0.51.11:80 check inter 5s rise 3 fall 2
server test_site2 10.0.51.12:80 check backup inter 5s rise 3 fall 2
backend letsencrypt-backend
server letsencrypt 123.123.123.123:80
For the backend side, we defined two servers as an example which will act as web servers for our test site, which Haproxy can track and load balance traffic to.
Also, Let’s encrypt backend server is defined as well, which is the same server where we have installed Haproxy.
Acquiring the SSL certificate
To acquire the ssl certificate(haproxy ssl certificate) from Let’s encrypt while Haproxy is active, run one of these two commands on the server where the Haproxy and Certbot are installed:
sudo certbot certonly --standalone --preferred-challenges http --http-01-address 123.123.123.123 --http-01-port 80 -d example.com --non-interactive --agree-tos --email [email protected]
sudo certbot certonly --standalone --preferred-challenges http --http-01-port 80 -d example.com --non-interactive --agree-tos --email [email protected]
Essentially, both commands do the same and you can try any of them, we just added in the first command argument with the public IP address, if in some case the second command does not work. So, in the commands we declared which challenge to use, which port to listen, we specified the domain name for which certbot to requests an ssl, agreed to TOS and provided an email address.
When you run one of these commands, just replace the example.com with your domain you want the ssl certificate for, replace the 123. ip address with the IP from your server and provide a legit email in order to get the notifications from let’s encrypt.
Even though we acquired the ssl certificate and is valid, the Haproxy cannot use it. In order for Haproxy to use the ssl certificate from Let’s encrypt, the ssl certificate must be saved in a single file. Haproxy requires for ssl certificate to be in a single file.
The certificate from Let’s encrypt comes in three separate files - the fullchain, private key and cert file. For the Haproxy to use ssl and https, it’s enough to have full chain and private key in the single file. We can create a single ssl certificate file and later on configure Haproxy to use it. We can copy the contents from the certificate files and copy them in the single .pem file which will be our ssl certificate for Haproxy.
To achieve this, we can do it with a command like this:
sudo cat "/etc/letsencrypt/live/example.com/fullchain.pem" "/etc/letsencrypt/live/example.com/privkey.pem" > "/etc/ssl/example.com.pem"
The Let’s encrypt cert files are located in the let’s encrypt directory. Each ssl certificate is organized in a directory named as a domain name. This command takes the contents of the certificates and places them in a single file. Then we can tell and configure Haproxy to use this file, like in the configuration from above. Of course, replace example.com with your domain name and add in the Haproxy config the location of the ssl certificate file you just created like in the configuration at the beginning of the post.
After this and once added in the Haproxy config file the location of the SSL certificate to use, restart the Haproxy service:
sudo systemctl restart haproxy.service
HAProxy SSL certificate automatic renewal
One thing to consider when using this kind of setup for Haproxy to use the SSL certificate is that with this method we created a custom file to use certificate and with this method, the SSL certificate will not be renewed when it expires. Well, the certbot will renew the certificate from Let’s encrypt but then Haproxy will not be able to use the new certificate.
However, we can still create a setup with certbot and Haproxy to also renew the ssl ceftificate for Haproxy. For this, we’ll need to create a bash script and configure cerbot to use it and run it with a post-hook after the certbot has renewed the certificate from Let’s Encrypt. Let’s Encrypt certbot by default has automatic renewal enabled and it has configured a cron job when to run a renewal.
By default, Let’s Encrypt ssl lasts for 3 months and cerbot will renew the certificate before it expires. So, our setup for ssl renewal for Haproxy is, when the certbot renews the ssl certificate, it will run our post-hook bash script, which we created and placed it in the post-hook directory, so that Haproxy can use the new ssl certificate.
A bash script would look something like this:
#!/bin/bash
sudo cat "/etc/letsencrypt/live/example.com/fullchain.pem" "/etc/letsencrypt/live/example.com/privkey.pem" > "/etc/ssl/example.com.pem"
sudo systemctl restart haproxy.service
This is essentially the two commands from earlier we ran in order to make the custom ssl certificate file for Haproxy to use. We’ll place this script in the Let’s encrypt post-hook directory of our domain name configuration directory. Like in the picture bellow:
sudo touch /etc/letsencrypt/renewal-hooks/post/haproxy-ssl-renew.sh
sudo nano /etc/letsencrypt/renewal-hooks/post/haproxy-ssl-renew.sh
You can create the script and paste in the script with these commands.
Then, in the domain configuration file in Let’s Encrypt, add the post_hook parameter to run the bash script we created:
sudo nano /etc/letsencrypt/renewal/example.com.conf
Here you can notice that we used the sh tool to run our script. That’s one way to do it. But you can also make the script executable with sudo chmod +x and it will work as well. And this was the last step. We have done it.
Summary
We have covered the procedure on how to install Let’s Encrypt SSL on HAProxy and how to perform the auto renewal for haproxy with let’sencrypt cerbot as well and with this we enabled the haproxy ssl encrypted traffic.
Thank you very much for you time…