Acme.sh certificate renewal (cron) for multiple acme validation methods

Hello. I've used http validation with the --stateless option to issue a certificate for example.net and dns validation to issue a wildcard certificate for *.example.com

I ran these commands to do so:
acme.sh --issue -d example.net --cert-home /etc/letsencrypt/live --stateless
acme.sh --issue --challenge-alias example.org --dns dns_cf -d *.example.com --cert-home /etc/letsencrypt/live

The certificates are issued successfully and are working with my nginx configuration, however, I'm having issues testing renewal both via cli and cron:

If I run renewal manually for example.net:
acme.sh --renew -d example.net
I receive:
Renew: 'example.net'
'example.net' is not an issued domain, skip.

So I figured I had to specify --home /etc/letsencrypt/live .
This works, however, when I add the --force option, it also generate a new thumbprint ID, which means I have to run renewals as --stateless too.

Now this is where my question comes in: Since I have domains validated via HTTP stateless and DNS validation - do I need to create separate cronjobs to take care of this?

The default cron doesn't seem to work at all:
30 2 * * * "/root/.acme.sh"/acme.sh --cron --home "/root/.acme.sh" --debug >> /root/test.acme.cron

Produces:


v2.8.8
[Tue Oct 6 16:24:01 CEST 2020] ===Starting cron===
[Tue Oct 6 16:24:02 CEST 2020] ===End cron===

... And nothing else... I would like to be able to renew all certificates via 1 cronjob regardless of which validation method was used so I dont have to specify --stateless or override my thumbprint ID.

Any ideas?

2 Likes

Hello Oliver :slightly_smiling_face:

While I'm not really familiar with the client process you are using, I did notice that you've mentioned example.net, example.com, and example.org in various places. Is this intentional?

My guess for the empty cron log is that your certificates were not yet due for renewal and thus acme.sh did nothing and had no output. Seems odd that it wouldn't tell you that though.

For the other part, hopefully someone who is familiar with your acme.sh setup (like @_az) will chime-in to help with that.

2 Likes

Hey Jonathan :slight_smile:

Thank you for your quick reply.
That is intentional, yes. I'm positive the actual domains have no relevance to my issue, so I've just used example domains to explain my setup.

Nice theory about the cron - I just tried testing my cron with the --force option to make sure renewals were due in any case and it produces the same output as before. So I believe something else is wrong, but debug clearly isn't catching it.

I hope @_az will chime-in when he has time :slight_smile: thanks for the suggestion, though.

2 Likes

Hi all,

Looks like the documentation:

--home "directory" Specifies the home dir for acme.sh.

... Confused me a little bit. It seems that the --home must be changed if you saved your certificates in a custom location like me.
'Final' cron looks like this: 30 2 * * * "/root/.acme.sh"/acme.sh --cron --home "/etc/letsencrypt/live" --debug >> /root/test.acme.cron

And this produce:

[Wed Oct  7 10:54:01 CEST 2020] Renew: '*.example.com'
[Wed Oct  7 10:54:01 CEST 2020] Skip, Next renewal time is: Sat Dec  5 11:42:14 UTC 2020
[Wed Oct  7 10:54:01 CEST 2020] Add '--force' to force to renew.
[Wed Oct  7 10:54:01 CEST 2020] Skipped *.example.com
[Wed Oct  7 10:54:01 CEST 2020] Renew: 'example.net'
[Wed Oct  7 10:54:01 CEST 2020] Skip, Next renewal time is: Sat Dec  5 14:17:13 UTC 2020
[Wed Oct  7 10:54:01 CEST 2020] Add '--force' to force to renew.
[Wed Oct  7 10:54:01 CEST 2020] Skipped example.net
[Wed Oct  7 10:54:01 CEST 2020] ===End cron===

After adding --force to the cron, example.net is successfully renewing and skipping http01 validation as expected because authorization was cached.
The DNS validated certificate for *.example.com is not renewing correctly, but that's a separate issue I will play around with.

2 Likes

I'm glad to see that you got things working to some extent. :slightly_smiling_face: _az has been very busy addressing several things today/tonight, so sorry for the delay there.

Something to keep in mind is that once an authorization is successful for a particular domain name associated with an ACME account, that success can be cached for 30 days for that account and thus any challenges presented for that domain name may automatically succeed for 30 days.

1 Like

Please mind your head with --force by the way. You can hit it on the rate limits all too soon.

1 Like

I don't really follow this thinking.

1 Like

Aha, that makes sense. Do you know if there's a convenient way to test without waiting the 30 days? It seems that the DNS validation was validating new records and creating a new CSR + conf files during renewal:

-rw-r--r-- 1 root root 1648 Oct  6 13:42 ca.cer
-rw-r--r-- 1 root root 3579 Oct  6 13:42 fullchain.cer
-rw-r--r-- 1 root root 1931 Oct  6 13:42 *.example.com.cer
-rw-r--r-- 1 root root  656 Oct  7 10:58 *.example.com.conf
-rw-r--r-- 1 root root 1001 Oct  7 10:58 *.example.com.csr
-rw-r--r-- 1 root root  219 Oct  7 10:58 *.example.com.csr.conf
-rw-r--r-- 1 root root 1675 Oct  6 13:41 *.example.com.key

It just didn't issue a new certificate and proceeded to the next one that wasn't a wildcard:

[Wed Oct  7 10:58:08 CEST 2020] Renew: '*.example.com'
[Wed Oct  7 10:58:09 CEST 2020] Using CA: https://acme-v02.api.letsencrypt.org/directory
[Wed Oct  7 10:58:09 CEST 2020] Single domain='*.example.com'
[Wed Oct  7 10:58:09 CEST 2020] Getting domain auth token for each domain
[Wed Oct  7 10:58:12 CEST 2020] Getting webroot for domain='*.example.com'
[Wed Oct  7 10:58:12 CEST 2020] Adding txt value: XXXXXXXXXXXXXXXXXXXXXX for domain:  _acme-challenge.example.org


[Wed Oct  7 10:58:13 CEST 2020] Renew: 'example.net'
1 Like

Well spotted. I've edited that comment. It was because the authorization was cached as @griffin mentioned.

1 Like

certbot uses --dry-run explicitly for testing.
acme.sh has a --test [but I have never used it, so I can't say for sure what that "means/does"]

Here is the page on acme.sh --stateless:

1 Like

There is a way to deauthorize challenges, but I'm not sure with your client what the mechanism would be.

Normally for most clients, CSR creation occurs after all challenges have succeeded right before finalizing the order. Seems odd to generate the CSR at all if the order failed (or there was no need to renew).

2 Likes

I agree. Since --force was used, it should've issued a new cert in my opinion, but perhaps wildcard certificates are treated differently.
I will try to investigate and hopefully find something.
Thank you for all your help.

2 Likes

I figured out the cron renewal solution in a separate thread: https://community.letsencrypt.org/t/acme-sh-cf-wildcard-certificates-error-when-testing-renewal/135465 with @rg305 after pinpointing the problem related specifically to DNS renewal.

My final cronjob looks like this and renews all certs successfully regardless of the validation method used:

30 2 * * * "/root/.acme.sh"/acme.sh --cron --home "/root/.acme.sh" --cert-home "/etc/letsencrypt/live" --reloadcmd "service nginx reload" > /dev/null
2 Likes

That's great, Oliver! :grinning:

1 Like