Last active
January 19, 2021 23:37
-
-
Save b0tting/aebc5e31a9267d287650cf60c675211c to your computer and use it in GitHub Desktop.
Script to solve "/etc/letsencrypt/live/.../cert.pem to be a symlink Renewal configuration file /etc/letsencrypt/renewal/...conf is broken. " certbot problem.
This file contains 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
""" | |
I'm not sure how and when, but certbot stopped updating my certificates because the cert files were expected but | |
turned out to be actual real files. No idea how this happened. | |
This caused the annoying error: | |
expected | |
/etc/letsencrypt/live/.../cert.pem to be a symlink Renewal configuration file /etc/letsencrypt/renewal/...conf is | |
broken. This scr… expected /etc/letsencrypt/live/.../cert.pem to be a symlink Renewal configuration file | |
/etc/letsencrypt/renewal/...conf is broken. Skipping. | |
As I didn't feel like deleting and linking dozens of directories I've written this script to help me. Run with | |
-x parameter to actually delete and link files where needed. | |
""" | |
import glob | |
import os | |
import sys | |
le_live_dir = "/etc/letsencrypt/live" | |
le_archive_dir = "/etc/letsencrypt/archive" | |
def find_archive_file(domain, file): | |
count = 1 | |
archive_file = os.path.join(le_archive_dir, domain, file).replace(".pem", str(count) + ".pem") | |
if not os.path.isfile(archive_file): | |
raise ValueError("Could not find " + archive_file + ". Expected to at least have one file for " + file + " in " + domain + " archive dir, quitting") | |
last_archive = False | |
while os.path.isfile(archive_file): | |
last_archive = archive_file | |
count += 1 | |
archive_file = os.path.join(le_archive_dir, domain, file).replace(".pem", str(count) + ".pem") | |
return last_archive | |
dry_run = len(sys.argv) < 2 or sys.argv[1] != "-x" | |
if dry_run: | |
print("This is a dry run, please start with the -x parameter to actually delete and replace with symlinks") | |
livedirs = glob.glob(le_live_dir + "/*/*") | |
expected_links = ["fullchain.pem", "chain.pem", "privkey.pem", "cert.pem"] | |
for file in livedirs: | |
basefile = os.path.basename(file) | |
domain = file.split("/")[-2] | |
if basefile in expected_links: | |
if os.path.islink(file): | |
print(basefile + " in domain " + domain + " is a symlink, as expected.") | |
else: | |
print(basefile + " in domain " + domain + " is a file, not a symlink.") | |
archive_filename = find_archive_file(domain, basefile) | |
print("Linking " + archive_filename + " there now") | |
if dry_run: | |
print("Dry run flag set: not deleting this file") | |
else: | |
try: | |
os.remove(file) | |
os.symlink(archive_filename, file) | |
print("Succesfully linked " + basefile + " from " + archive_filename) | |
except OSError as e: | |
print("Could not delete " + e.filename + ", got error " + e.strerror) | |
print("You probably need to run this script as the root user..") | |
sys.exit(1) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment