100 lines
3.4 KiB
Python
100 lines
3.4 KiB
Python
|
#!/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()
|
||
|
|