Hello,
I am not really sure where to ask this question so I'll just do here.
I am trying to automate the certbot renew
process, so that
- if a webserver is running/port 80 is used, it should use the webroot method to renew
- if no webserver is running/port 80 is not used, it should use the standalone
I was reading about the reconfigure
subcommand and wrote a script that updates all renewal configurations depending on the "status" of port 80. When running it on the commandline, it worked how it should, but when I tested it in the renewal as the pre-hook, I just got the error that two instances of certbot are running at the same time, so I dropped that idea.
My next idea was to update the configurations directly in the pre-hook. I wrote the following script that also works outside of certbot:
#!/bin/bash
# Ansible managed
for cert in /etc/letsencrypt/renewal/*
do
# Check if port 80 is in use
if netstat -tln | grep -q :80; then
# Port 80 is in use, set the authenticator to "webroot"
authenticator="webroot"
if grep -q "^webroot_path" "$cert"; then
# If webroot_path exists, update it
sed -i "s|^webroot_path.*|webroot_path = /data/www/sites|" "$cert"
else
# If webroot_path doesn't exist, add it after the authenticator line
sed -i "\|^authenticator.*|a webroot_path = /data/www/sites" "$cert"
fi
else
# Port 80 is not in use, set the authenticator to "standalone"
authenticator="standalone"
fi
# Modify the renewal configuration file based on the authenticator
sed -i "s|^authenticator.*|authenticator = $authenticator|" "$cert"
echo -e "\nchanged certificate $cert conf to:"
cat "$cert"
done
Now I tested it by generating two certificates using the standalone method, so both configuration have these options:
# Options used in the renewal process
[renewalparams]
account = {account}
pref_challs = http-01,
authenticator = standalone
server = https://acme-v02.api.letsencrypt.org/directory
I expect it to work like this:
- Run pre-hook that updates the renewal configurations if necessary
- Load the first (updated) renewal configuration
- Run the challenge for that certificate
- Load the second (updated) renewal configuration
- Run the challenge for that certificate
When running certbot renew --dry-run
with not used port 80, there aren't any complications.
But when I start apache before running it, it seems certbot is loading the first renewal configuration before running the pre-hook (I printed the new configuration inside the pre-hook to make sure they are updated correctly) so that it tries to start its own standalone webserver but can't because of apache. The second configuration is loaded correctly because its not using the standalone method and finishing the challenge (which makes sense because the pre-hook already ran and updated the confs).
Saving debug log to /var/log/letsencrypt/letsencrypt.log
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Processing /etc/letsencrypt/renewal/ansible01.bitvision.de.conf
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Hook 'pre-hook' ran with output:
changed certificate /etc/letsencrypt/renewal/ansible01.bitvision.de.conf conf to:
# renew_before_expiry = 30 days
version = 1.12.0
archive_dir = /etc/letsencrypt/archive/ansible01.bitvision.de
cert = /etc/letsencrypt/live/ansible01.bitvision.de/cert.pem
privkey = /etc/letsencrypt/live/ansible01.bitvision.de/privkey.pem
chain = /etc/letsencrypt/live/ansible01.bitvision.de/chain.pem
fullchain = /etc/letsencrypt/live/ansible01.bitvision.de/fullchain.pem
# Options used in the renewal process
[renewalparams]
account = {account}
pref_challs = http-01
authenticator = webroot
webroot_path = /data/www/sites
server = https://acme-v02.api.letsencrypt.org/directory
changed certificate /etc/letsencrypt/renewal/ansible02.bitvision.de.conf conf to:
# renew_before_expiry = 30 days
version = 1.12.0
archive_dir = /etc/letsencrypt/archive/ansible02.bitvision.de
cert = /etc/letsencrypt/live/ansible02.bitvision.de/cert.pem
privkey = /etc/letsencrypt/live/ansible02.bitvision.de/privkey.pem
chain = /etc/letsencrypt/live/ansible02.bitvision.de/chain.pem
fullchain = /etc/letsencrypt/live/ansible01.bitvision.de/fullchain.pem
# Options used in the renewal process
[renewalparams]
account = {account}
pref_challs = http-01,
authenticator = webroot
webroot_path = /data/www/sites
server = https://acme-v02.api.letsencrypt.org/directory
Simulating renewal of an existing certificate for ansible01.bitvision.de and www.ansible01.bitvision.de
Failed to renew certificate ansible01.bitvision.de with error: Could not bind TCP port 80 because it is already in use by another process on this system (such as a web server). Please stop the program in question and then try again.
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Processing /etc/letsencrypt/renewal/ansible02.bitvision.de.conf
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Simulating renewal of an existing certificate for ansible02.bitvision.de
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
The following simulated renewals succeeded:
/etc/letsencrypt/live/ansible01.bitvision.de/fullchain.pem (success)
The following simulated renewals failed:
/etc/letsencrypt/live/ansible01.bitvision.de/fullchain.pem (failure)
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1 renew failure(s), 0 parse failure(s)
Ask for help or search for solutions at https://community.letsencrypt.org. See the logfile /var/log/letsencrypt/letsencrypt.log or re-run Certbot with -v for more details.
So i have some questions:
- Can the
reconfigure
subcommand somehow run in the pre-hook? - Is there a way to reload the renewal configuration inside the pre-hook?
- Can I maybe tell certbot directly from inside the pre-hook to use a certain method (e.g. through a variable like RENEWAL_METHOD)
- Is there maybe a different approach I can try or is there anything I did wrong in my approaches?
Let me know if more details are needed!