Skip to content

Instantly share code, notes, and snippets.

@jkraemer
Last active September 14, 2020 12:39
Show Gist options
  • Save jkraemer/b44971f671f499ffefe6cf5c252d7a54 to your computer and use it in GitHub Desktop.
Save jkraemer/b44971f671f499ffefe6cf5c252d7a54 to your computer and use it in GitHub Desktop.
Let's Encrypt certificate renewal with HAProxy
# Use a 4096 bit RSA key instead of 2048
rsa-key-size = 4096
# update to register with the specified e-mail address
email = [email protected]
# use a text interface instead of ncurses
text = True
non-interactive = True
agree-tos = True
# use the standalone authenticator
authenticator = standalone
preferred-challenges = http-01
# this is the same port as in the haproxy letsencrypt backend:
http-01-port = 54321
work-dir = /home/certbot
config-dir = /home/certbot/config
logs-dir = /home/certbot/logs
# just the relevant parts
frontend http
# ...
# direct all letsencrypt requests to a special backend
acl letsencrypt-acl path_beg /.well-known/acme-challenge/
use_backend letsencrypt-backend if letsencrypt-acl
# this backend will forward to the letsencrypt validation server
# that is fired up automatically during certificate creation / renewal
# in certbot's standalone mode
backend letsencrypt-backend
server letsencrypt 127.0.0.1:54321
#!/bin/bash
domain=$1
fullchain_file="/home/certbot/certs/$domain/fullchain.pem"
key="/home/certbot/certs/${domain}/${domain}.key"
combined_file="/etc/haproxy/ssl/${domain}.pem"
dhparam="/home/certbot/dhparam"
if [ ! -f $key ]; then
key="/home/certbot/letsencrypt.key"
fi
if [ -f $fullchain_file -a -f $key -a -f $dhparam ]
then
if [ -f $combined_file ]
then
cp $combined_file "${combined_file}.old"
fi
cat $fullchain_file $key $dhparam > $combined_file
chmod 0400 $combined_file
fi
#!/bin/bash
reload_required=false
# attempt to renew when less then 30 days remaining
exp_limit=30;
# returns 0 if no renewal needed, 1 otherwise
check_cert_still_valid () {
local cert_file=$1
local exp=$(date -d "`openssl x509 -in $cert_file -text -noout|grep "Not After"|cut -c 25-`" +%s)
local datenow=$(date -d "now" +%s)
local days_exp=$(echo \( $exp - $datenow \) / 86400 |bc)
echo "Checking expiration date for $domain..."
if [ "$days_exp" -gt "$exp_limit" ] ; then
echo "The certificate is up to date, no need for renewal ($days_exp days left)."
return 0
else
echo "The certificate $cert_file is about to expire soon. Starting renewal..."
return 1
fi
}
get_certificate() {
local domain=$1
local cert_file=$2
local key_file="/home/certbot/certs/${domain}/${domain}.key"
local csr_file="/home/certbot/certs/${domain}/${domain}.csr"
local chain_file="/home/certbot/certs/$domain/chain.pem"
local fullchain_file="/home/certbot/certs/$domain/fullchain.pem"
# Certbot refuses to overwrite existing files, so remove anything that
# might get in the way.
# The certificate used by haproxy is kept separately, so no harm is done by
# deleting these files:
rm -f $cert_file $chain_file $fullchain_file
certbot certonly --csr $csr_file --cert-path $cert_file --chain-path $chain_file --fullchain-path $fullchain_file
if [ $? -eq 0 ]; then
echo "Creating $combined_file with latest certs..."
sudo /usr/local/sbin/le-haproxy-bundle $domain
echo "Renewal process finished for domain $domain"
reload_required=true
else
echo "certbot failed, not replacing installed certificate for ${domain}"
fi
}
process_certificate() {
local domain=$1
local cert_file="/home/certbot/certs/$domain/${domain}.crt"
if [ -f $cert_file ]; then
check_cert_still_valid $cert_file
if [ ! $? -eq 0 ]; then
get_certificate $domain $cert_file
fi
else
echo "No certificate for domain $domain exists yet. Creating one..."
get_certificate $domain $cert_file
fi
}
domain=$1
# loop over all domains unless a domain is given
if [ "${domain}" = "" ]; then
for i in $( ls /home/certbot/certs ); do
process_certificate $i
done
else
process_certificate $domain
fi
if [ "$reload_required" = true ]; then
echo "Reloading haproxy"
sudo /usr/sbin/service haproxy reload
fi
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment