Is this a stupid way of using systemd/python to automatically renew expiriging letsencrypt certificates


#1

My plan is to use systemd’s timers to monthly check expiring certs and renew them. Here are my files:

/etc/systemd/system/letsencrypt.timer:

[Unit]
Description=Check monthly for which certs are expiring and renew them

[Timer]
OnCalendar=monthly
Unit=letsencrypt.service

[Install]
WantedBy=timers.target

/etc/systemd/system/letsencrypt.service:

[Unit]
Description=Renew the Let's Encrypt TLS certificates for expiring domains

[Service]
Type=simple
ExecStart=/usr/local/bin/letsencrypt-renew

/usr/local/bin/letsencrypt-renew:

#!/usr/bin/env python3

import glob
from datetime import datetime
import re
from  subprocess import Popen, PIPE, STDOUT, call

restart = False
certs = glob.glob('/etc/letsencrypt/live/*/fullchain.pem')
now = datetime.now()
search = re.compile('DNS:([a-z\.]*)')
for cert in certs:
    expires = call(['openssl', 'x509', '-in', cert, '-checkend', '2592000'])
    if expires:
        p2 = Popen('openssl x509 -in ' + cert + ' -text -noout', shell=True, stdin=PIPE, stdout=PIPE, stderr=STDOUT, close_fds=True)
        certText = p2.stdout.read().decode("utf-8")
        domains = search.findall(certText)
        domainArgs = ''
        for domain in domains:
            domainArgs = domainArgs + ' -d ' + domain
        command = './letsencrypt-auto --renew certonly --agree-tos --server https://acme-v01.api.letsencrypt.org/directory --webroot --webroot-path=/etc/letsencrypt/webroot' + domainArgs
        success = call(command, shell=True)
        if success == 0:
            print('Certificates updated')
            restart = True
        else:
            print('Lets Encrypt was unsuccesful')
if restart == True:
    call(['systemctl', 'restart', 'nginx'])

I’m wondering if I can make the letsencrypt.service file restart nginx depending on the exit code of my python script? But systemd’s documentation seems spread across several sources.


#2

systemd’s stand here is that if you need more complex logic you should wrap it into a shellscript or similar. So just let your python script run systemctl reload nginx?

Btw Unit= is only needed when the name differs, foo.timer will start foo.service by default.


#3

So I should leave the restarting of nginx (if the certs have been updated) in the python script?


#4

Yes, sorry was editing my reply a bit to clarify that point