Skip to content

Instantly share code, notes, and snippets.

@ledil
Forked from tikenn/haproxy.cfg
Created January 30, 2017 12:51
Show Gist options
  • Save ledil/ac446be5876482de3cc4578e16c6ce50 to your computer and use it in GitHub Desktop.
Save ledil/ac446be5876482de3cc4578e16c6ce50 to your computer and use it in GitHub Desktop.
Let's Encrypt Auto-Renewal script for HAProxy
global
log /dev/log local0
log /dev/log local1 notice
chroot /var/lib/haproxy
stats socket /run/haproxy/admin.sock mode 660 level admin
stats timeout 30s
user haproxy
group haproxy
daemon
maxconn 2048
tune.ssl.default-dh-param 2048
# Default SSL material locations
ca-base /etc/ssl/certs
crt-base /etc/ssl/private
# Default ciphers to use on SSL-enabled listening sockets.
# For more information, see ciphers(1SSL). This list is from:
# https://hynek.me/articles/hardening-your-web-servers-ssl-ciphers/
ssl-default-bind-ciphers ECDH+AESGCM:DH+AESGCM:ECDH+AES256:DH+AES256:ECDH+AES128:DH+AES:ECDH+3DES:DH+3DES:RSA+AESGCM:RSA+AES:RSA+3DES:!aNULL:!MD5:!DSS
ssl-default-bind-options no-sslv3
defaults
log global
mode http
option httplog
option dontlognull
timeout connect 5000
timeout client 50000
timeout server 50000
errorfile 400 /etc/haproxy/errors/400.http
errorfile 403 /etc/haproxy/errors/403.http
errorfile 408 /etc/haproxy/errors/408.http
errorfile 500 /etc/haproxy/errors/500.http
errorfile 502 /etc/haproxy/errors/502.http
errorfile 503 /etc/haproxy/errors/503.http
errorfile 504 /etc/haproxy/errors/504.http
option forwardfor
option http-server-close
frontend www-http
bind haproxy_www_public_IP:80
reqadd X-Forwarded-Proto:\ http
default_backend www-backend
frontend www-https
bind haproxy_www_public_IP:443 ssl crt /etc/haproxy/certs/example.com.pem
reqadd X-Forwarded-Proto:\ https
acl letsencrypt-acl path_beg /.well-known/acme-challenge/
use_backend letsencrypt-backend if letsencrypt-acl
default_backend www-backend
backend www-backend
redirect scheme https if !{ ssl_fc }
server www-1 www_1_private_IP:80 check
server www-2 www_2_private_IP:80 check
backend letsencrypt-backend
server letsencrypt 127.0.0.1:54321
#!/bin/bash
#
# --------------------------------------------------------------------------------------------
# Letsencrypt Auto Renew Script
# --------------------------------------------------------------------------------------------
# This file automatically renews SSL certificates issued by a letsencrypt server installation
# Original author and idea credit
# - Mitchell Anicas: thisismith (https://github.com/thisismitch)
# - https://gist.github.com/thisismitch/7c91e9b2b63f837a0c4b
#
# --------------------------------------------------------------------------------------------
# Author Info
# --------------------------------------------------------------------------------------------
# Name :: Tim Kennell Jr. ~ tikenn
#
# --------------------------------------------------------------------------------------------
# Config
# --------------------------------------------------------------------------------------------
# WEB_SERVICE :: web service on computer (e.g. haproxy, nginx, etc.)
# CONFIG_DIR :: directory of config files for letsencrypt domains
# COMBINED_DIR :: directory to store combined ssl certificates for use be WEB_SERVICE
# RENEWAL_PORT :: port for letsencrypt to use for renewal (choose something other than 80 or 443)
# EXP_LIMIT :: days before ssl certificat expiration to renew
# LE_PATH :: path to letsencrypt binary file
# LOG_FILE :: file to log fatal errors
#
# --------------------------------------------------------------------------------------------
# Setting up crontab
# --------------------------------------------------------------------------------------------
# - Create a file in /etc/cron.d/
# - Suggested to run the file once a week
# - Example line (runs at midnight): "0 0 * * 1 /path/to/le-renew-haproxy"
#
# ~ tikenn
WEB_SERVICE="haproxy"
CONFIG_DIR="/usr/local/etc"
COMBINED_DIR="/etc/ssl/private"
RENEWAL_PORT='18181'
EXP_LIMIT=30
[email protected]
LE_PATH="/usr/bin"
LOG_FILE="/opt/le-auto-renew/le-renew.log"
# --------------------------------------------------------------------------------------------
# Core App
# --------------------------------------------------------------------------------------------
# Check for config file directory
if [ ! "$(ls -A "$CONFIG_DIR")" ] ; then
echo "[ERROR $(date -d "now" +"%Y-%m-%d %T")] no config files: $CONFIG_DIR" | tee -a "$LOG_FILE"
exit 1
fi
# Email errors if they occur
# param String $1 -- email addresses to mail to
# param String $2 -- email body to send
# param String $3 -- email attachment
email_errors() {
local mailto="$1"
local email_body="$2"
local attachment="$3"
echo -e "$email_body" |
mutt -e "set from=le-auto-renew@$HOSTNAME.server realname='$HOSTNAME'" \
-s "$HOSTNAME System Maintenance Errors" \
-a "$attachment" -- "$mailto"
}
# Email configuration parameters
email_body="Error renewing certificates for the following domains:\n"
error_flag=0
# Loop through each configuration file in config dir
for config_file in $(/bin/ls -1 "$CONFIG_DIR") ; do
domain=$(grep "^\s*domains" "$CONFIG_DIR/$config_file" | sed "s/^\s*domains\s*=\s*//" | sed 's/(\s*)\|,.*$//')
combined_file="$COMBINED_DIR/$domain.ssl-unified.pem"
cert_file="/etc/letsencrypt/live/$domain/fullchain.pem"
key_file="/etc/letsencrypt/live/$domain/privkey.pem"
if [ ! -f $cert_file ]; then
echo "[ERROR $(date -d "now" +"%Y-%m-%d %T")] certificate file not found for domain $domain." | tee -a "$LOG_FILE"
email_body+=" - $domain\n"
error_flag=1
continue
fi
exp=$(date -d "`openssl x509 -in $cert_file -text -noout|grep "Not After"|cut -c 25-`" +%s)
datenow=$(date -d "now" +%s)
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)."
email_body+=" - $domain\n"
error_flag=1
continue
else
echo "The certificate for $domain is about to expire soon. Starting Let's Encrypt (HAProxy:$RENEWAL_PORT) renewal script..."
$LE_PATH/letsencrypt certonly --agree-tos --renew-by-default --config "$CONFIG_DIR/$config_file" --http-01-port "$RENEWAL_PORT"
if [ "$?" -gt 0 ] ; then
echo "[ERROR $(date -d "now" +"%Y-%m-%d %T")] letsencrypt unable to renew certificate for domain $domain." | tee -a "$LOG_FILE"
email_body+=" - $domain\n"
error_flag=1
continue
fi
echo "Creating $combined_file with latest certs..."
sudo bash -c "cat /etc/letsencrypt/live/$domain/fullchain.pem /etc/letsencrypt/live/$domain/privkey.pem > $combined_file"
echo "Renewal process finished for domain $domain"
fi
done
echo "Reloading $WEB_SERVICE"
/bin/systemctl restart "$WEB_SERVICE"
# email regarding errors if setup
if which mutt > /dev/null && [ -n "$ADMIN_EMAIL" ] && [ "$error_flag" -eq 1 ] ; then
email_errors "$ADMIN_EMAIL" "$email_body" "$LOG_FILE"
fi
# ---------------------------------------------------------------------------------------------
# End of Core App
# ---------------------------------------------------------------------------------------------
# This is an example of the kind of things you can do in a configuration file.
# All flags used by the client can be configured here. Run Let's Encrypt with
# "--help" to learn more about the available options.
# Use a 4096 bit RSA key instead of 2048
rsa-key-size = 4096
# Uncomment and update to register with the specified e-mail address
email = [email protected]
# Uncomment and update to generate certificates for the specified
# domains.
domains = example.com, www.example.com
# Uncomment to use a text interface instead of ncurses
# text = True
# Uncomment to use the standalone authenticator on port 443
# authenticator = standalone
standalone-supported-challenges = http-01
# Uncomment to use the webroot authenticator. Replace webroot-path with the
# path to the public_html / webroot folder being served by your web server.
# authenticator = webroot
# webroot-path = /usr/share/nginx/html
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment