Skip to content

Instantly share code, notes, and snippets.

@floreo
Last active March 12, 2017 20:11
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save floreo/8f73b99935b3755b7f776b2525568193 to your computer and use it in GitHub Desktop.
Save floreo/8f73b99935b3755b7f776b2525568193 to your computer and use it in GitHub Desktop.
bash script to generate Let's Encrypt certificates through Acme Tiny
#!/usr/bin/env bash
## README ##
#
# * Whats does it require ?
# To download or clone https://github.com/diafygi/acme-tiny inside _LE_ACME_DIR
#
# * How to write a correct conf file ?
# Write a file named myname.conf inside _LE_CONF_DIR
# hHre's the content:
# DIR="the documentroot of your website"
# DOMAIN="youdomainname another another"
#
## CONFIGURATION ##
_LE_ACME_DIR="/root/scripts/acme-tiny/"
_LE_ROOT_DIR="/root/LE/"
_LE_CONF_DIR="${_LE_ROOT_DIR}conf/"
_LE_KEY_DIR="${_LE_ROOT_DIR}key/"
_LE_CRT_DIR="${_LE_ROOT_DIR}crt/"
_LE_CSR_DIR="${_LE_ROOT_DIR}csr/"
_LE_PEM_DIR="${_LE_ROOT_DIR}pem/"
_LE_ACCOUNT_KEY="${_LE_CONF_DIR}account.key"
_LE_INTERMEDIATE_PEM="${_LE_CONF_DIR}intermediate.pem"
# time in seconds before expiration date to renew
_LE_RENEWAL_BEFORE="1296000"
# mail for error messages
_LE_MAILTO=""
# <empty>, apache2, nginx or haproxy
_LE_WEBSERVER="apache2"
## MAIN ##
mkdir -p ${_LE_ROOT_DIR} ${_LE_CONF_DIR} ${_LE_KEY_DIR} ${_LE_CRT_DIR} ${_LE_CSR_DIR} ${_LE_PEM_DIR}
# Get intermediate
if [ ! -s "${_LE_INTERMEDIATE_PEM}" ] ; then
wget -qO - "https://letsencrypt.org/certs/lets-encrypt-x3-cross-signed.pem" >"${_LE_INTERMEDIATE_PEM}"
fi
# Generate account key
if [ ! -s "${_LE_ACCOUNT_KEY}" ] ; then
openssl genrsa 4096 >"${_LE_ACCOUNT_KEY}" &>/dev/null
fi
# Loop through each configuration file
while read _conf
do
unset DIR DOMAIN
. ${_conf}
if [ -z "${DIR}" -o -z "${DOMAIN}" ] ; then
echo "No variables found for \"${_conf}\" ..."
continue
fi
DIR="${DIR}/.well-known/acme-challenge"
CN="$( echo "${DOMAIN}" | awk '{ print $1 }' )"
KEY="${_LE_KEY_DIR}${CN}.key"
CSR="${_LE_CSR_DIR}${CN}.csr"
PEM="${_LE_PEM_DIR}${CN}.pem"
CRT="${_LE_CRT_DIR}${CN}_$(date +'%F_%T').crt"
CRT_LINK="${_LE_CRT_DIR}${CN}.crt"
CRT_FULL="${_LE_CRT_DIR}${CN}-full.crt"
echo -n "Doing \"${CN}\" "
# Check for renewal
if [ -s "${CRT_LINK}" ] ; then
openssl x509 -checkend "${_LE_RENEWAL_BEFORE}" -noout -in "${CRT_LINK}"
if [ "$?" -eq 0 ] ; then
echo -e "... not needed ... \e[32mOK\e[39m"
continue
fi
fi
STATUS=0
ACME_ERROR_FILE="$(mktemp)"
WEBSERVER_ERROR_FILE="$(mktemp)"
mkdir -p "${DIR}"
# Generating key
if [ ! -s "${KEY}" ] ; then
openssl genrsa 4096 >${KEY} 2>/dev/null
fi
# Generating csr
if [ ! -s "${CSR}" ] ; then
if [ "$(echo "${DOMAIN}" | grep -o " " | wc -c)" -ge 2 ] ; then
SAN="$(echo "${DOMAIN}" | awk 'BEGIN{ ORS=""; print "[SAN]\nsubjectAltName="; ORS=","; }{ for(i = 1; i <= NF; i++) { if(i == NF){ ORS="" } print "DNS:"$i; } }')"
openssl req -new -sha256 -key ${KEY} -subj "/" -reqexts SAN -config <(cat /etc/ssl/openssl.cnf <(echo "${SAN}")) >${CSR} 2>/dev/null
unset SAN
else
openssl req -new -sha256 -key ${KEY} -subj "/CN=${DOMAIN}" >${CSR} 2>/dev/null
fi
fi
# Generating crt
python "${_LE_ACME_DIR}acme_tiny.py" \
--account-key "${_LE_ACCOUNT_KEY}" \
--csr "${CSR}" \
--acme-dir "${DIR}" \
> "${CRT}" 2>${ACME_ERROR_FILE}
if [ "$?" == 0 ] ; then
# Linking certificate
rm -f "${CRT_LINK}" && ln -s "${CRT}" "${CRT_LINK}"
# Doing full certificate (nginx)
cat "${CRT}" "${_LE_INTERMEDIATE_PEM}" >"${CRT_FULL}"
# Doing pem (haproxy)
cat "${CRT}" "${_LE_INTERMEDIATE_PEM}" "${KEY}">"${PEM}"
# Reload service
case "${_LE_WEBSERVER}" in
"apache2")
service apache2 reload &>/dev/null
;;
"nginx")
service nginx reload &>/dev/null
;;
"haproxy")
service haproxy reload &>/dev/null
;;
*)
echo "No webserver defined or service not known : \"${_LE_WEBSERVER}\""
;;
esac
# Check webserver
if [ "$?" != 0 ] ; then
STATUS=2
fi
else
STATUS=1
fi
if [ "${STATUS}" -eq 0 ] ; then
echo -e "\e[32mOK\e[39m"
else
echo -e "\e[31mNOK\e[39m"
cat "${ACME_ERROR_FILE}" "${WEBSERVER_ERROR_FILE}"
if [ -n "${_LE_MAILTO}" ] ; then
cat "${ACME_ERROR_FILE}" "${WEBSERVER_ERROR_FILE}" | mail -s "LE.sh --- error generating ${DOMAIN}" ${_LE_MAILTO}
fi
fi
# Cleaning
rm -- "${ACME_ERROR_FILE}" "${WEBSERVER_ERROR_FILE}"
find "${_LE_CRT_DIR}" -type f -empty -exec rm {} \;
done < <( ls ${_LE_CONF_DIR}/*.conf )
exit 0
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment