#!/usr/bin/env python3 """ auto-renew.py: Renew SSL certificates with Let's Encrypt, written by GPT-4 with a bit of help from Sam Watkins. """ import re import sys import pexpect import argparse import logging from pexpect import pxssh logging.basicConfig(level=logging.INFO) def main(domain, use_wildcard): domain_arg = f'-d {domain}' if use_wildcard: domain_arg = f'-d *.{domain} {domain_arg}' logging.info(f"Starting certbot for domain: {domain} (use_wildcard={use_wildcard})") certbot_command = f'sudo certbot certonly --manual {domain_arg} --preferred-challenges dns-01 --server https://acme-v02.api.letsencrypt.org/directory' logging.info(f"certbot_command: {certbot_command}") certbot = pexpect.spawn(certbot_command, encoding='utf-8', logfile=sys.stderr) certbot.expect('Please deploy a DNS TXT record under the name') certbot.expect('value:\r\n\r\n(.+?)\r\n') key1 = certbot.match.group(1) logging.info(f"Key1: {key1}") certbot.expect('Press Enter to Continue') if use_wildcard: certbot.sendline('') certbot.expect('Please deploy a DNS TXT record under the name') certbot.expect('value:\r\n\r\n(.+?)\r\n') key2 = certbot.match.group(1) logging.info(f"Key2: {key2}") certbot.expect('Press Enter to Continue') else: key2 = "" logging.info(f"Running add-txt-records.sh for domain: {domain}") add_txt_records_script = f'./add-txt-records.sh {domain}' add_txt_records = pexpect.spawn(add_txt_records_script, encoding='utf-8', logfile=sys.stderr) add_txt_records.expect(f'enter the text values for {domain}') add_txt_records.sendline(key1) add_txt_records.sendline(key2) add_txt_records.expect(pexpect.EOF) logging.info(f"Finished running add-txt-records.sh for domain: {domain}") certbot.sendline('') certbot.expect(pexpect.EOF) logging.info(f"Finished certbot for domain: {domain}") if __name__ == '__main__': parser = argparse.ArgumentParser(description='Renew SSL certificates with Let\'s Encrypt.') parser.add_argument('domain', help='The domain to renew the certificate for.') parser.add_argument('--no-wildcard', dest='use_wildcard', action='store_false', help='Disable wildcard domain.') parser.set_defaults(use_wildcard=True) args = parser.parse_args() main(args.domain, args.use_wildcard)