HAProxy serves as an exceptional load balancer and reverse proxy. If you only run a couple of backend servers on a couple of domains, managing your certificates and domains is easy. However, as the number of services behind HAProxy grows, each associated with different base domains, managing multiple certificates can become cumbersome, especially if they're not subdomains and you're not using a wildcard certificate.
This is an easy-to-use script for your public HAProxy server. It provides easy registration of a new domain and concatenation of the fresh certificate into the appropriate directory (assuming "/etc/ssl")
This script assumes a few things:
- Port 80 is open and not being used by HAProxy, or any other service on the server, and you have certbot installed.
- Your new domain has a proper DNS record pointing to HAProxy
- You have a backend for certbot in HAProxy (shown below)
To start, it is essential to ensure that port 80 is open on your server. You can refer to the appropriate instructions specific to your distribution for the right steps. Once port 80 is open, you will need to define a host record ACL and a backend for Certbot within your HAProxy configuration.
Certbot Backend
Open your HAProxy configuration file, typically located at "/etc/haproxy/haproxy.cfg" and add this ACL.
# LetsEncrypt
acl letsencrypt-acl path_beg /.well-known/acme-challenge/
use_backend letsencrypt-backend if letsencrypt-acl
Next, add the corresponding backend.
# LetsEncrypt-Backend
backend letsencrypt-backend
server letsencrypt 127.0.0.1:80
Restart HAProxy:
sudo systemctl restart haproxy.service
The Script
Log in as the server's root user, and copy this script. I prefer to keep it in the root user's home directory.
#!/bin/bash
# Ask the user for the domain
read -p "Enter the domain you would like to register a certificate for: " domain
echo "You entered: $domain"
# Ask the user to verify the entered domain
read -p "Please verify that the entered domain is correct (y/n): " verify_domain
if [ "$verify_domain" != "y" ] && [ "$verify_domain" != "Y" ]; then
echo "Domain verification failed. Exiting script."
exit 1
fi
# Run certbot command
echo "Running certbot command..."
certbot_output=$(certbot certonly --standalone --preferred-challenges http --http-01-address x.x.x.x --http-01-port 80 -d "$domain" --non-interactive --agree-tos --email youremail@emaildomain.com)
echo "$certbot_output"
# Check if certbot command was successful
certbot_exit_code=$?
if [ $certbot_exit_code -eq 0 ]; then
echo "Certbot command executed successfully."
else
echo "Certbot command failed. Exiting script."
exit 1
fi
# Concatenate certificate files
echo "Concatenating certificate files..."
cat_output=$(cat "/etc/letsencrypt/live/$domain/fullchain.pem" "/etc/letsencrypt/live/$domain/privkey.pem" > "/etc/ssl/$domain" 2>&1)
cat_exit_code=$?
if [ $cat_exit_code -eq 0 ]; then
echo "Certificate files were successfully concatenated."
else
echo "Failed to concatenate certificate files."
echo "Error message: $cat_output"
fi
Locate the following line:
certbot_output=$(certbot certonly --standalone --preferred-challenges http --http-01-address x.x.x.x --http-01-port 80 -d "$domain" --non-interactive --agree-tos --email youremail@emaildomain.com)
The email and IP address can be modified to be a variable that can ask for new values each time you run the script, however as this script is meant to be used on the same server each time you run it, the static settings are faster.
Next, you will need to make a few edits
- Replace "x.x.x.x" with the public IP address of your HAProxy server. This ensures that certbot will reach the right IP.
- Substitute "youremail@emaildomain" with the desired email address that you want to register the domain to. This email will be associated with the domain during the registration process.
- If needed, modify the directory where the script will save the certificate. You can specify the desired directory path in the script. I prefer /etc/ssl , so that is what you will see in the examples.
After making these changes, save the modified script, and mark it as an executable.
chmod +x newdomain.sh
You can now run the script. The script will prompt you for the domain you want to register, then to verify that it's correct. Once confirmed, it will obtain the certificate, and concatenate the certificate into a single file located at /etc/ssl, unless you changed this directory earlier. Here is the output you should see:
[root@hostname ~]# ./newdomain.sh
Enter the domain you would like to register a certificate for: yourdomain.com
You entered: yourdomain.com
Please verify that the entered domain is correct (y/n): y
Running certbot command...
Saving debug log to /var/log/letsencrypt/letsencrypt.log
Requesting a certificate for yourdomain.com
Successfully received certificate.
Certificate is saved at: /etc/letsencrypt/live/yourdomain.com/fullchain.pem
Key is saved at: /etc/letsencrypt/live/yourdomain.com/privkey.pem
This certificate expires on 2023-09-22.
These files will be updated when the certificate renews.
Certbot has set up a scheduled task to automatically renew this certificate in the background.
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
If you like Certbot, please consider supporting our work by:
* Donating to ISRG / Let's Encrypt: https://letsencrypt.org/donate
* Donating to EFF: https://eff.org/donate-le
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Certbot command executed successfully.
Concatenating certificate files...
Certificate files were successfully concatenated.
[root@hostname ~]#
If you received an error, please make sure that port 80 is available for certbot to use, and that your domain points to the correct IP address.
Restart HAProxy for the certificate to be loaded.
sudo systemctl restart haproxy.service
You can now create a record and backend for your new domain. If you would like to learn how to route based on URL, please visit the official documentation here: https://www.haproxy.com/blog/how-to-map-domain-names-to-backend-server-pools-with-haproxy