Lets Encrypt renewal the 105th

NethServer Version: 7.9. with 3 vhosts/domains

  • Thread shield disabled
  • IPS disabled
  • Firewall no blocking of port 80

There are a lot of postings here
But I can’t find any idea why my expired LE certificates (mydomain2.de and mydomain3.de) are not automatically renewed. The cert of mydomain1.de (the main domain) is still not expired.

I don’t get any error messages by mail.
#sh /etc/cron.daily/nethserver-check-uploaded-certificates
…tell me only that the 2 certs are expired.

# sh nethserver-letsencrypt-certs produces such log entries

# cat /var/log/letsencrypt/letsencrypt.log

2021-04-20 08:24:52,262:DEBUG:certbot._internal.main:certbot version: 1.11.0
2021-04-20 08:24:52,262:DEBUG:certbot._internal.main:Location of certbot entry point: /usr/bin/certbot
2021-04-20 08:24:52,262:DEBUG:certbot._internal.main:Arguments: [’–text’, ‘–non-interactive’, ‘–agree-tos’, ‘–email’, ‘admin@externalmail.com’, ‘–preferred-challenges’, ‘http’, ‘–webroot’, ‘–webroot-path’, ‘/var/www/html/’, ‘-d’, ‘mydomain1.de’, ‘-d’, ‘collabora.mydomain1.de’, ‘-d’, ‘imap.mydomain1.de’, ‘-d’, ‘mail.mydomain1.de’, ‘-d’, ‘nextcloud.mydomain1.de’, ‘-d’, ‘smtp.mydomain1.de’, ‘-d’, ‘wp.mydomain1.de’, ‘-d’, ‘www.mydomain1.de’, ‘-d’, ‘webtop.mydomain1.de’, ‘-d’, ‘ns-srv01.mydomain1.de’, ‘-d’, ‘status.mydomain1.de’, ‘–quiet’]
2021-04-20 08:24:52,262:DEBUG:certbot._internal.main:Discovered plugins: PluginsRegistry(PluginEntryPoint#manual,PluginEntryPoint#null,PluginEntryPoint#standalone,PluginEntryPoint#webroot)
2021-04-20 08:24:52,279:DEBUG:certbot._internal.log:Root logging level set at 30
2021-04-20 08:24:52,279:INFO:certbot._internal.log:Saving debug log to /var/log/letsencrypt/letsencrypt.log
2021-04-20 08:24:52,280:DEBUG:certbot._internal.plugins.selection:Requested authenticator webroot and installer None
2021-04-20 08:24:52,281:DEBUG:certbot._internal.plugins.selection:Single candidate plugin: * webroot
Description: Place files in webroot directory
Interfaces: IAuthenticator, IPlugin
Entry point: webroot = certbot._internal.plugins.webroot:Authenticator
Initialized: <certbot._internal.plugins.webroot.Authenticator object at 0x7f4d2e673a90>
Prep: True
2021-04-20 08:24:52,283:DEBUG:certbot._internal.plugins.selection:Selected authenticator <certbot._internal.plugins.webroot.Authenticator object at 0x7f4d2e673a90> and installer None
2021-04-20 08:24:52,283:INFO:certbot._internal.plugins.selection:Plugins selected: Authenticator webroot, Installer None
2021-04-20 08:24:52,308:DEBUG:certbot._internal.main:Picked account: <Account(RegistrationResource(body=Registration(status=None, terms_of_service_agreed=None, agreement=None, only_return_existing=None, contact=(), key=None, external_account_binding=None), uri=u’https://acme-v02.api.letsencrypt.org/acme/acct/98774805’, new_authzr_uri=None, terms_of_service=None), 4507e00e979072793c396c2a3ee407aa, Meta(creation_host=u’ns-srv01.mydomain1.de’, register_to_eff=None, creation_dt=datetime.datetime(2020, 10, 8, 22, 54, 4, tzinfo=)))>
2021-04-20 08:24:52,318:DEBUG:acme.client:Sending GET request to https://acme-v02.api.letsencrypt.org/directory.
2021-04-20 08:24:52,329:INFO:urllib3.connectionpool:Starting new HTTPS connection (1): acme-v02.api.letsencrypt.org
2021-04-20 08:24:52,874:DEBUG:urllib3.connectionpool:“GET /directory HTTP/1.1” 200 658
2021-04-20 08:24:52,874:DEBUG:acme.client:Received response:
HTTP 200
content-length: 658
strict-transport-security: max-age=604800
server: nginx
connection: keep-alive
cache-control: public, max-age=0, no-cache
date: Tue, 20 Apr 2021 06:24:52 GMT
x-frame-options: DENY
content-type: application/json

“keyChange”: “https://acme-v02.api.letsencrypt.org/acme/key-change”,
“meta”: {
“caaIdentities”: [
“termsOfService”: “https://letsencrypt.org/documents/LE-SA-v1.2-November-15-2017.pdf”,
“website”: “https://letsencrypt.org
“newAccount”: “https://acme-v02.api.letsencrypt.org/acme/new-acct”,
“newNonce”: “https://acme-v02.api.letsencrypt.org/acme/new-nonce”,
“newOrder”: “https://acme-v02.api.letsencrypt.org/acme/new-order”,
“revokeCert”: “https://acme-v02.api.letsencrypt.org/acme/revoke-cert”,
“vHIlDm_eqbU”: “https://community.letsencrypt.org/t/adding-random-entries-to-the-directory/33417
2021-04-20 08:24:52,899:DEBUG:certbot._internal.plugins.selection:Requested authenticator webroot and installer <certbot._internal.cli.cli_utils._Default object at 0x7f4d2ddd3410>
2021-04-20 08:24:52,915:DEBUG:certbot.ocsp:Querying OCSP for /etc/letsencrypt/archive/mydomain1.de/cert6.pem
2021-04-20 08:24:52,916:DEBUG:certbot.ocsp:openssl ocsp -no_nonce -issuer /etc/letsencrypt/archive/mydomain1.de/chain6.pem -cert /etc/letsencrypt/archive/mydomain1.de/cert6.pem -CAfile /etc/letsencrypt/archive/mydomain1.de/chain6.pem -verify_other /etc/letsencrypt/archive/mydomain1.de/chain6.pem -trust_other -timeout 10 -header Host r3.o.lencr.org -url http://r3.o.lencr.org
2021-04-20 08:24:52,948:INFO:certbot._internal.renewal:Cert not yet due for renewal
2021-04-20 08:24:52,949:INFO:certbot._internal.main:Keeping the existing certificate
2021-04-20 08:24:52,949:DEBUG:certbot.display.util:Notifying user: Certificate not yet due for renewal; no action taken.

That means, this script checks only mydomain1.de (not expired) and not my expired mydomain2.de and mydomain3.de

How can I start the autorenewal script correctly for all of my domains/vhosts?

Sincerely, MArko

O.K. I give up because I could not wait any longer and manually have renewed via Cockpit.

Set up a simple cron job:

Nethserver assumes you’re going to use one cert for everything, so rather than running a simple certbot renew on a regular basis, they’ve decided to write their own script (at /usr/libexec/nethserver/letsencrypt-certs) to renew only the one cert that they assume you’re using. I have no idea why they did it this way; it seems it only made it far more complicated than it needs to be.

But in any event, it’s easy enough for you to do what they should have done but didn’t–just set up the cron job discussed at the link above.


Thank you for the hint. If you know how to do it, it’s very simple.

@dev_team, why do it this way? You’ve got over 160 lines of code in that script to do what a simple certbot renew would have done–and not do it nearly as well. It seems this complicates things for no good reason.

Probably the best they had at the time and not payed much attention to it since; same items could be said for their certificate handling system wide. I’d expect NS 8 to rectify some of these issues.

Time for a PR on certbot renewal?

1 Like

Not sure how that could be the case. Certbot has had a “renew” option that’s worked the same way since its initial release (as letsencrypt), as has dehydrated (or whatever it was called previously), acme.sh, and pretty much every other major client. It’s really the way it’s designed to be used. Which had me hesitate a bit in doing the PR, since I figured there must be some reason they were going out of their way to complicate things–but I can’t see what it would be.

I hope so–they really need to get away from the mindset of “one cert to rule them all,” and there are a bunch of other ways certificate management could be greatly improved. But if NS8 is going to be heavily container-based (as EL8 is), that may correct itself.

1 Like

I’m the orignal author of that script and for sure it’s not the best script I’ve ever written :slight_smile: But it does a good job on thousands of machines since NS 6, so it’s working well for most usage scenarios since 5-6 years.
And no, it is not the same as a simple certbot --renew call.

When it was implemented, it was running with letsencrypt.sh (now named dehydrated) which had no support for hooks on certificare renewal. When we switched to certbot, it was not easy to rewrite the entire logic without regressions so I decided to keep the same script.

That script also:

  • implement LE validation for NethGUI
  • implement LE validation for Cockpit
  • reads the configuration from pki key, so without it, the UI will not work at all
  • execute the certificate-update event to notify all software when the certificate is renewed

So I’m going to close the current PR.
I’m willing to review a new one but it must implement all above and shouldn’t introduce regressions.


I’ll admit to being pretty weak with Perl, but I don’t see how it does anything unique for the old server-manager or for Cockpit. It requests a cert for specified domain names (or those in the config database), defaulting to http validation with a web root of /var/www/html. That validation method and web root are saved in certbot’s configuration, so certbot renew maintains them.

I’m afraid I don’t understand the last part here at all. I get that it reads stuff from the pki key, which is put there when you issue the cert through the GUI. But once the cert is issued, that’s all saved in the certbot configuration. When you run certbot renew, if a cert’s due for renewal, certbot reissues the cert with the same domain names as before, the same file paths as before, the same pre/post/renew hooks as before, etc. How does “the UI not work at all” in this case?

--post-hook "/sbin/e-smith/signal-event certificate-update"

1 Like

I also had the problem NS not renewing one of the Lets’ encrypt certificates ( Let's encrypt did not update automatically )

Why does NS not include all certificates in “config getprop pki LetsEncryptDomains”? Or is there any way to configure this with cockpit?

The whole thing should be indeed replace by:

certbot renew --post-hook “/sbin/e-smith/signal-event certificate-update”

Just move the discussion on the newest thread.