Skip to content

Instantly share code, notes, and snippets.

@remyd1
Last active February 15, 2022 10:41
Show Gist options
  • Save remyd1/35fdbcb740fa4fdec1a15727ad7e743c to your computer and use it in GitHub Desktop.
Save remyd1/35fdbcb740fa4fdec1a15727ad7e743c to your computer and use it in GitHub Desktop.
Package agnostic let's encrypt certificate renew bash script
#! /bin/bash
# Bash script to manage the letsencrypt renewals or the initial request.
# To insert into a ~cron for renewals (with no args)
# 0. Check if this is already managed through docker
# 1. check the web service
# 2. check if the host is hosting a gitlab service
# 3. check if certbot is installed
# 4. otherwise check if certbot has been installed from source (if so, you need to modify DIRS_TO_CHECK bellow)
# 5. update the certs
# 6. reload the web service
# for debug
#set -x
# consts
usage="$0 [initial|multidomains|help|renew]"
MAIL="{{ MAIL }}"
SITES_STATUS="site*-enabled"
# these configuration are needed if you used certbot installation from source
DIRS_TO_CHECK=("/root/certbot" "/root/letsencrypt")
FILES_TO_CHECK=("certbot-auto" "letsencrypt-auto")
# init var
webserver=""
SERVICE=`command -v service`
DOCKER=`command -v docker`
LSOF=`command -v lsof`
le_vhosts=""
le_webroots=""
if [ -z "${LSOF}" ]; then
echo "to use this program, 'lsof' utility is required"
exit 1
fi
# checking if it is managed directly through docker
if [ -n "${DOCKER}" ]; then
certbox_ct=`${DOCKER} ps |grep certbot`
if [ -n "${certbox_ct}" ]; then
exit 1
fi
fi
#listening_process=`${LSOF} -i :80 -a -i :443 | awk '/LISTEN/ {print $1}'|uniq`
listening_process=`${LSOF} -i :443 | awk '/LISTEN/ {print $1}'|uniq`
for webservice in gitlab apache2 nginx lighttpd
do
if `ps aux|grep -Ev "grep|gitlab-runner"|grep -q $webservice`; then
webserver=$webservice
break
fi
done
if [ "$webserver" != "$listening_process" ]; then
if [ "$webserver" == "gitlab" ]; then
GITLAB=`command -v gitlab-ctl`
if [ -n "$GITLAB" ];then
gitlab-ctl renew-le-certs
gitlab-ctl restart nginx
exit 0
fi
else
# ok, we need to check the right service
if [ -n "${SERVICE}" ]; then
test_listening_server=`service $listening_process status |grep running`
else
test_listening_server=`/bin/systemctl status $listening_process|grep running`
fi
if [ -n "${test_listening_server}" ]; then
webserver=$listening_process
fi
# otherwise, we keep the webserver variable as it is
fi
fi
function get_vhosts() {
#get possible vhosts
case "${webserver}" in
"nginx")
vhosts=`grep -E "^(\s)*server_name" /etc/nginx/${SITES_STATUS}/* |awk '{if ($1 !~ "\s*^#") {$1="";print;} }' 2>/dev/null`
vhosts=`for vhost in $(echo $vhosts |tr -d ";"); do echo $vhost|grep -v server_name; done |sort |uniq`
le_vhosts=`for vhost in $vhosts; do if [[ ! "$vhost" =~ '*' ]] && [[ ! "$vhost" =~ '^' ]]; then echo -n " -d $vhost"; fi; done`
;;
"apache2")
#vhosts=`grep -E "NameVirtualHost|ServerName|ServerAlias" /etc/apache2//${SITES_STATUS}/*|awk '{if ($2 !~ "\s*^#") {print $NF} }' 2>/dev/null|tr -d ";"|sort|uniq`
vhosts=`grep -E "NameVirtualHost|ServerName|ServerAlias" /etc/apache2/${SITES_STATUS}/*|awk '{if (($2 !~ "\s*^#") && ($3 !~ "The|redirection|www.example.com")) {$1="";print;} }' 2>/dev/null|tr -d ";"|sort|uniq`
le_vhosts=`for vhost in $vhosts; do if [[ ! "$vhost" =~ '*' ]] && [[ ! "$vhost" =~ '^' ]] && [[ ! "$vhost" == "ServerName" ]] && [[ ! "$vhost" == "ServerAlias" ]]; then echo -n " -d $vhost"; fi; done`
;;
*)
;;
esac
}
function get_webroot() {
#get possible webroots
case "${webserver}" in
"nginx")
le_webroots=`awk '{ if ( ( $1 ~ "^root" ) && ($1 !~ "\s*^#") ) {print $2} }' /etc/nginx/${SITES_STATUS}/* 2>/dev/null|cut -d';' -f1 |head -1`
;;
"apache2")
le_webroots=`awk '/DocumentRoot/ {if ($2 !~ "\s*^#") {print $2} }' /etc/apache2/${SITES_STATUS}/*ssl* 2>/dev/null |head -1`
;;
*)
;;
esac
if [ -z "${le_webroots}" ];then
if [ -d /var/www/html/ ]; then
le_webroots=/var/www/html/
elif [ -d /var/www/ ]; then
le_webroots=/var/www/
else
echo 'No webroots found ! Please insert a <root/DocumentRoot> in your webserver configuration.'
exit 1
fi
fi
}
if [ -z $1 ] || [ $1 == "renew" ]; then
certcommand="renew"
get_webroot
end_of_command="${certcommand} --webroot --webroot-path ${le_webroots} -m ${MAIL}"
elif [[ "$1" == "initial" ]]; then
certcommand="certonly"
get_vhosts
get_webroot
end_of_command="${certcommand} --agree-tos --non-interactive --rsa-key-size 4096 ${le_vhosts} --webroot --webroot-path ${le_webroots} -m ${MAIL}"
elif [[ "$1" == "multidomains" ]] ;then
certcommand="certonly"
get_vhosts
get_webroot
end_of_command="${certcommand} --agree-tos --non-interactive --rsa-key-size 4096 --webroot --webroot-path ${le_webroots} --renew-with-new-domains --expand ${le_vhosts} -m ${MAIL}"
else
echo $usage
fi
THE_DIR=""
THE_FILE=""
certbot=`command -v certbot`
if [ $certbot ]; then
certbot ${end_of_command}
else
for dir in "${DIRS_TO_CHECK[@]}"
do
if [ -d ${dir} ]; then
THE_DIR=${dir}
break
fi
done
for file in "${FILES_TO_CHECK[@]}"
do
if [ -f ${THE_DIR}/${file} ]; then
THE_FILE=${THE_DIR}/${file}
break
fi
done
if [ -n ${THE_FILE} ]; then
${THE_FILE} ${end_of_command}
else
echo " No certbot / letsencrypt found.
Please edit this script to provide the right directories
Or install certbot: eg. 'apt-get install certbot'"
fi
fi
if [ -n "${SERVICE}" ]; then
service $webserver reload
else
/bin/systemctl reload $webserver
fi
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment