Forked from andygock/renew-letsencrypt-certificates.sh
Created
October 3, 2020 15:31
-
-
Save iguy0/f18791eb375b306cd91f3a9a37a44b2d to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/bin/bash | |
# | |
# renew-letsencrypt-certificates.sh DOMAIN [EMAIL] | |
# | |
# Copy Let's Encrypt SSL certs from a remote public facing web server to local filesystem | |
# Look for changes, if any change, restarts the web service | |
# Useful for using Let's Encrypt with local internal servers, with custom DNS. | |
# Working "mail" command needed for email alerts | |
# | |
if [ -z $1 ]; then | |
echo "Syntax error, use:" | |
echo " renew-letsencrypt-certificates.sh DOMAIN [EMAIL]" | |
exit 1 | |
fi | |
DOMAIN=$1 | |
# send email message here when a renewal occurs, or on error | |
EMAIL=$2 | |
# Get SOA DNS server | |
DNS=$(dig soa $DOMAIN | grep -v ^\; | grep SOA | sed -r 's/^(.*)SOA\t//' | cut -d " " -f 1 | sed -r 's/\.$//') | |
# Get remote public facing web server IP address | |
IP_REMOTE=$(dig @$DNS +short $DOMAIN A) | |
if [[ -z $IP_REMOTE ]]; then | |
echo "Can not determine remote IP for $DOMAIN" | |
exit 1 | |
fi | |
# .pem certificates will be saved here. You must have write permissions here | |
# and your Apache or nginx .conf files should refer to this path | |
# Actual cert files will be in a subdir e.g $CERT_PATH/$DOMAIN/*.pem | |
CERT_PATH=/etc/letsencrypt/live | |
CERT_PATH_DOMAIN="$CERT_PATH/$DOMAIN" | |
# e.g httpd, nginx - if certificates are updated, then will invoke "service $WEB_SERVER restart" | |
WEB_SERVER=nginx | |
DIR=$(dirname $0) | |
CERT_TARBALL_REMOTE=/root/certs_${DOMAIN}.tar.gz | |
CERT_TARBALL_LOCAL=/root/certs_${DOMAIN}.tar.gz | |
# this flag is used by this script, leave this alone! | |
certs_updated=0 | |
restart_www () { | |
if [[ "$WEB_SERVER" == "nginx" ]]; then | |
nginx -s reload | |
else | |
service $WEB_SERVER restart | |
fi | |
} | |
# return 0 if renewed, 1 if not renewed for whatever reason | |
refresh_certificates () { | |
# create tarball on public server of current letsencrypt certs for desired domain | |
echo "Create \"$CERT_TARBALL_REMOTE\" on remote..." | |
ssh root@$IP_REMOTE "rm -f \"$CERT_TARBALL_REMOTE\"; tar -zchf \"$CERT_TARBALL_REMOTE\" -C \"$CERT_PATH\" $DOMAIN" | |
# copy tarball from public to internal server | |
echo "Copy remote \"$CERT_TARBALL_REMOTE\" to local \"$CERT_TARBALL_LOCAL\"..." | |
scp root@$IP_REMOTE:"$CERT_TARBALL_REMOTE" "$CERT_TARBALL_LOCAL" > /dev/null | |
# create cert path if we need to | |
[[ -d "$CERT_PATH_DOMAIN" ]] || mkdir -p "$CERT_PATH_DOMAIN" | |
# check local tarball is persent | |
if [[ ! -f "$CERT_TARBALL_LOCAL" ]]; then | |
echo "Error: Local \"$CERT_TARBALL_LOCAL\" is missing. The copy or write operation above has failed." | |
exit 1 | |
fi | |
echo "Extracting certificates to local \"$CERT_PATH_DOMAIN\"..." | |
tar -zxvf "$CERT_TARBALL_REMOTE" -C "$CERT_PATH_DOMAIN" --strip-components=1 > /dev/null | |
echo "Delete remote \"$CERT_TARBALL_REMOTE\"..." | |
ssh root@$IP_REMOTE "rm -f '$CERT_TARBALL_REMOTE'" | |
# Restart web server only if certs changed since last run of this script | |
# Although it's probably fine if we just restarted it each time anyway | |
# Create a CHECKSUMS file in $CERT_PATH_DOMAIN, verify against this in the future to detect changes | |
pushd . &> /dev/null | |
cd "$CERT_PATH_DOMAIN" | |
if [[ -f CHECKSUMS ]]; then | |
echo -n "Checking whether certificates have changed... " | |
sha256sum --status -c CHECKSUMS | |
if [[ $? -ne 0 ]]; then | |
# checksum is different, certificate has changed, restart web server and reclaculate checksums | |
echo "Change found. Certificates updated. Restarting or reloading $WEB_SERVER ..." | |
restart_www | |
sha256sum *.pem > CHECKSUMS | |
return 0 | |
else | |
# No update performed, certficates the same as previous | |
echo "Certificates not changed." | |
return 1 | |
fi | |
else | |
# no checksum performed yet | |
echo "Certificates updated. Restarting or reloading $WEB_SERVER ..." | |
restart_www | |
sha256sum *.pem > CHECKSUMS | |
return 0 | |
fi | |
popd > /dev/null | |
} | |
# | |
# Script starts here | |
# | |
cert_stats () { | |
echo | openssl s_client -showcerts -connect $1:443 2> /dev/null | openssl x509 -noout -dates | |
} | |
# we need to copy those certs to this machine at regular machine | |
refresh_certificates | |
if [[ $? -eq 0 ]]; then | |
# updated, both cron and interactive mode | |
echo "SSL cert was updated. New certificate validity dates:" | |
if [[ ! -z $EMAIL ]]; then | |
cert_stats $DOMAIN | tee mail -s "SSL cert updated" $EMAIL | |
else | |
cert_stats $DOMAIN | |
fi | |
elif [[ -t 0 ]]; then | |
# not updated - interactive mode | |
echo "SSL cert does not need updating. Current certificate validity dates:" | |
cert_stats $DOMAIN | |
fi | |
exit 0 |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment