From 5c653a3cc2c3911ebbbe4b75b2aefdea236932db Mon Sep 17 00:00:00 2001 From: Noah Petherbridge Date: Thu, 31 Dec 2015 03:25:34 +0000 Subject: [PATCH] Add renew-certs script --- home/bin/renew-certs.py | 99 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 99 insertions(+) create mode 100755 home/bin/renew-certs.py diff --git a/home/bin/renew-certs.py b/home/bin/renew-certs.py new file mode 100755 index 0000000..ad9e0b7 --- /dev/null +++ b/home/bin/renew-certs.py @@ -0,0 +1,99 @@ +#!/usr/bin/env python3 + +# Cron script to renew LetsEncrypt certificates. +# +# --Kirsle +# https://sh.kirsle.net/ + +import os +import subprocess +import time + +################################################################################ +# Configuration Section Begins # +################################################################################ + +# Let's Encrypt directories +LE_APPDIR = "/opt/letsencrypt" # Where `letsencrypt-auto` lives +LE_CERTS = "/etc/letsencrypt/live" # Where live certificates go + +# Common arguments to letsencrypt-auto +COMMON = ["./letsencrypt-auto", "certonly", "--renew", + "--webroot", "-w", "/var/www/html"] + +# Domains and their subdomains; one array element per certificate, with each +# array element being a list of domains to include in the same cert. +CERTS = [ + [ "www.kirsle.net", "kirsle.net", "www.kirsle.com", "kirsle.com", + "www.kirsle.org", "kirsle.org", "sh.kirsle.net", "rpm.kirsle.net", + "minecraft.kirsle.net", "mc.kirsle.net", "rophako.kirsle.net" ], + [ "noah.is", "www.noah.is", "petherbridge.org", "www.petherbridge.org", + "noah.petherbridge.org", "noahpetherbridge.com", + "www.noahpetherbridge.com" ], + [ "rivescript.com", "www.rivescript.com", "static.rivescript.com" ], + [ "siikir.com", "www.siikir.com" ], + [ "collegegent.com", "www.collegegent.com" ], +] + +# Minimum lifetime for certificate before renewing it? +LIFETIME = 60*60*24*30 # Once a month. + +# Command to run after finishing if certs were renewed. +RESTART_COMMAND = ["service", "nginx", "reload"] + +################################################################################ +# End Configuration Section # +################################################################################ + +def main(): + os.chdir(LE_APPDIR) + + # If any certs were renewed, we'll schedule the restart command at the end. + any_renewed = False + + # See which certificates are ready to be renewed. + print("Checking SSL certificates for renewal") + for cert in CERTS: + ready = False # Ready to renew this one + primary = cert[0] + + # Find its existing live certificate file. + home = os.path.join(LE_CERTS, primary) + chain = os.path.join(home, "cert.pem") + + # When was it last modified? + if not os.path.isfile(chain): + print("NOTE: No existing cert file found for {} ({})".format( + primary, + chain, + )) + ready = True + else: + mtime = os.stat(chain).st_mtime + if time.time() - mtime > LIFETIME: + print("Cert for {} is old; scheduling it for renewal!"\ + .format(primary)) + ready = True + + # Proceed? + if ready: + print("Renewing certificate for {}...".format(primary)) + command = [] + command.extend(COMMON) + + # Add all the domains. + for domain in cert: + command.extend(["-d", domain]) + + print("Exec: {}".format(" ".join(command))) + subprocess.call(command) + any_renewed = True + + # If any certs were changed, restart the web server. + if any_renewed: + print("Restarting the web server: {}".format(" ".join(RESTART_COMMAND))) + subprocess.call(RESTART_COMMAND) + +if __name__ == "__main__": + main() +