My domain is: not relevant
I ran this command: using certonly
for renewals but bootstrapping server with existing certificate because during initial deployments we test the server before making DNS change...so letsencrypt can't perform domain verification against new server. So we set everything up with a valid cert and then within X days of expiration (checked with openssl) we tell certbot to do a certonly so we get a new cert.
It produced this output: live directory exists for...
i.e. doesn't overwrite/replace default/bootstrap certificate and instead places the new cert in an alternative (non-standard) directory (numerical suffix).
Our provisioning sees the cert at the default location is still expiring within X days and so keeps attempting to generate a letsencrypt cert and of course runs into rate limits.
My web server is (include version): not relevant
The operating system my web server runs on is (include version): not relevant
My hosting provider, if applicable, is: not relevant
This caught my eye...
There is a way to create the entire /etc/letsencrypt structure with a dummy cert from the outset, but it’s not documented and requires a bit of manual work, so I don’t think I would suggest that.
Our provisioning/orchestration manages nginx configs and we don't want other utilities that we can't easily monitor making changes as this will result in the config flapping back and forth between what letsencrypt wants and what our provisioning wants.
So we use certonly
. When we can set DNS before deploying server then everything is fine because letsencrypt can generate the first certificate and successfully does domain verification.
However when moving a server we often want to test production configs before making the DNS change. This often means deploying the new server and setting record in hosts file to verify everything (including https) is working. Many apps depend on having base urls configured (https://f.q.d.n/p/a/t/h
) to function properly so we do this hosts file based test....but https needs to work and letsencrypt is not an option without domain verification.
So we deploy a bootstrap certificate that is valid for that domain in the letsencrypt location.
Our provisioning/orchestration periodically checks that cert for expiration (using openssl) and when it is within X days of expiration, asks letsencrypt to generate a new cert (ie the bootstrap cert gets replaced with new letsencrypt cert). So we really only run certbot once every 60 days or so. The bootstrap cert might be letsencrypt transferred from an existing production box or might be from a different CA.
We could put this bootstrap cert in a different directory and then manage switching around nginx configs (pointing at different cert paths) when we switch...but that makes the process a lot more complicated of course.
So....long story short.... wondering if there is some trick to how we are constructing our certbot directory with bootstrap cert so that when we run certbot it will overwrite the cert that is there (the bootstrap cert) without complaining live directory exists for example.com
and then places the cert in a non-standard directory.
What appears to be happening is that the cert is saved but to a non-standard path.
Debug Log
2021-06-26 00:13:01,022:INFO:certbot._internal.client:Non-standard path(s), might not work with crontab installed by your operating system package manager
2021-06-26 00:13:01,023:DEBUG:certbot._internal.storage:Creating directory /opt/certbot/archive/example.com-0001.
2021-06-26 00:13:01,023:DEBUG:certbot._internal.storage:Creating directory /opt/certbot/live/example.com-0001.
2021-06-26 00:13:01,023:DEBUG:certbot._internal.storage:Writing certificate to /opt/certbot/live/example.com-0001/cert.pem.
2021-06-26 00:13:01,023:DEBUG:certbot._internal.storage:Writing private key to /opt/certbot/live/example.com-0001/privkey.pem.
2021-06-26 00:13:01,023:DEBUG:certbot._internal.storage:Writing chain to /opt/certbot/live/example.com-0001/chain.pem.
2021-06-26 00:13:01,024:DEBUG:certbot._internal.storage:Writing full chain to /opt/certbot/live/example.com-0001/fullchain.pem.
2021-06-26 00:13:01,024:DEBUG:certbot._internal.storage:Writing README to /opt/certbot/live/example.com-0001/README.
2021-06-26 00:13:01,061:DEBUG:certbot._internal.plugins.selection:Requested authenticator webroot and installer <certbot._internal.cli.cli_utils._Default object at 0x7fb8ba5cd910>
2021-06-26 00:13:01,061:DEBUG:certbot._internal.cli:Var server=https://acme-v02.api.letsencrypt.org/directory (set by user).
2021-06-26 00:13:01,061:DEBUG:certbot._internal.cli:Var account={'server'} (set by user).
2021-06-26 00:13:01,061:DEBUG:certbot._internal.cli:Var rsa_key_size=2048 (set by user).
2021-06-26 00:13:01,061:DEBUG:certbot._internal.cli:Var key_type=rsa (set by user).
2021-06-26 00:13:01,061:DEBUG:certbot._internal.cli:Var config_dir=/opt/certbot (set by user).
2021-06-26 00:13:01,061:DEBUG:certbot._internal.cli:Var server=https://acme-v02.api.letsencrypt.org/directory (set by user).
2021-06-26 00:13:01,061:DEBUG:certbot._internal.cli:Var authenticator=webroot (set by user).
2021-06-26 00:13:01,061:DEBUG:certbot._internal.cli:Var webroot_path=/var/www/example.com (set by user).
2021-06-26 00:13:01,061:DEBUG:certbot._internal.cli:Var webroot_path=/var/www/example.com (set by user).
2021-06-26 00:13:01,061:DEBUG:certbot._internal.cli:Var webroot_map={'webroot_path'} (set by user).
2021-06-26 00:13:01,061:DEBUG:certbot._internal.storage:Writing new config /opt/certbot/renewal/example.com-0001.conf.
2021-06-26 00:13:01,063:DEBUG:certbot.display.util:Notifying user:
Successfully received certificate.
Certificate is saved at: /opt/certbot/live/example.com-0001/fullchain.pem
Key is saved at: /opt/certbot/live/example.com-0001/privkey.pem
This certificate expires on 2021-09-23.
These files will be updated when the certificate renews.
Certbot has set up a scheduled task to automatically renew this certificate in the background.
You can see we expect the cert to be located in /opt/certbot/live/example.com
but because of the existence of the bootstrap cert in that location, certbot places the new cert at /opt/certbot/live/example.com-0001
and subsequent attempts (because we still see the cert at /opt/certbot/live/example.com
is still expiring soon) end up at -0002
, -0003
, etc until we run into the rate limit.
root@some-server:~# ls -l /opt/certbot/live/
total 28
drwxr-xr-x 2 root root 4096 Apr 29 09:55 example.com
drwxr-xr-x 2 root root 4096 Jun 26 00:13 example.com-0001
drwxr-xr-x 2 root root 4096 Jun 26 00:18 example.com-0002
drwxr-xr-x 2 root root 4096 Jun 26 00:23 example.com-0003
drwxr-xr-x 2 root root 4096 Jun 26 00:28 example.com-0004
I suppose another way to "hack" this bootstrap is to check for the presence of the -0001
directory after requesting a cert and if it is there, replace the correct location with the -0001
directory.