Let's encrypt add-on not renewing certificates correctly

The Let’s Encrypt add-on appears to not detect the certificate is due for renewal. Anyone else seeing this?

Starting the add-on…

[15:17:17] INFO: Selected DNS Provider: dns-cloudflare
[15:17:17] INFO: Use propagation seconds: 60
[15:17:18] INFO: Use CloudFlare token
Saving debug log to /var/log/letsencrypt/letsencrypt.log
Plugins selected: Authenticator dns-cloudflare, Installer None
Cert not yet due for renewal
Keeping the existing certificate

In Chrome;

image

Plus I am getting renewal warnings.

There is no way to force the renewal.

[edit]

Looking at https://crt.sh/?q=hassio.borpin.net it looks like the certificates renewed on the 8th.

Digging further, I found this folder with apparently the right date on the files.

$ sudo ls -la /usr/share/hassio/addons/data/core_letsencrypt/letsencrypt/live/hassio.borpin.net
total 12
drwxr-xr-x 2 root root 4096 Jul  8 13:03 .
drwx------ 3 root root 4096 Feb 18 22:33 ..
lrwxrwxrwx 1 root root   41 Jul  8 13:03 cert.pem -> ../../archive/hassio.borpin.net/cert3.pem
lrwxrwxrwx 1 root root   42 Jul  8 13:03 chain.pem -> ../../archive/hassio.borpin.net/chain3.pem
lrwxrwxrwx 1 root root   46 Jul  8 13:03 fullchain.pem -> ../../archive/hassio.borpin.net/fullchain3.pem
lrwxrwxrwx 1 root root   44 Jul  8 13:03 privkey.pem -> ../../archive/hassio.borpin.net/privkey3.pem
-rw-r--r-- 1 root root  692 Feb 18 22:33 README

Copied these certificates to the SSL folder.

sudo cp  /usr/share/hassio/addons/data/core_letsencrypt/letsencrypt/live/hassio.borpin.net/fullchain.pem /usr/share/hassio/ssl/
sudo cp  /usr/share/hassio/addons/data/core_letsencrypt/letsencrypt/live/hassio.borpin.net/privkey.pem /usr/share/hassio/ssl/

Restared - no luck - still report in the Chrome Padlock as the old certificate.

image

I had similar issues before when renewing certificates. I think the issue is that Google Chrome will cache the certificate, so it doesn’t need to download it every time. Since the old certificate has still not expired, Chrome will use the old cached version. Try clearing the browser cache, since I think this is where these are cached.
(You can check if this is the issue first by opening it in an Incognito window and see if the correct certificate is shown).

1 Like

I’ll say I tried that several times. I have just had to restore as AdGuard stopped playing nicely and the certificate error seems fixed.

Most odd, but thanks :grin:

Thank you, just saved me so much time!

I had marked this as the solution but it isn’t. You need to run the addon then restart HA.

What is really needed is a means of restarting the underlying webserver HA is using, as certbot does on a normal system.

I am at this again (it really annoys me).

BUT

Renew certificate
Restart NGINX addon (shows new cert in the browser padlock)
Restart HA (updated days remaining sensor).

What a faff!

I have solved this with an automation as discussed here LetsEncrypt not auto renewing certificates · Issue #1445 · home-assistant/addons · GitHub. It ran overnight :slight_smile:

First a sensor to determine how long is left

- platform: template
  sensors:
    s_cert_exiry_d:
      friendly_name: 'Cert Expiry'
      value_template: >
        {{ ((as_timestamp(states('sensor.cert_expiry_timestamp_yourdomain')) - as_timestamp(states.sensor.date.last_updated)) / 86400) | int }}
      unit_of_measurement: 'days'

The automation was done in the UI but generated this configuration

- id: '1613238259920'
  alias: Renew SSL Certificate
  description: ''
  trigger:
  - platform: time
    at: 03:00:05
  condition:
  - condition: numeric_state
    entity_id: sensor.s_cert_exiry_d
    below: '30'
  action:
  - service: hassio.addon_restart
    data:
      addon: core_letsencrypt
  - delay:
      hours: 0
      minutes: 5
      seconds: 0
      milliseconds: 0
  - service: hassio.addon_restart
    data:
      addon: core_nginx_proxy
  - delay:
      hours: 0
      minutes: 1
      seconds: 0
      milliseconds: 0
  - service: homeassistant.restart
    data: {}
  mode: single

[edit]
Removed quote as per comment from @pickerin

1 Like

Greatly appreciate the insight into how to build a sensor and automation for this, it’s bitten me a few times. Wanted to point out that there is an error in the value_template. An unmatched double-quote that passes a configuration check, but doesn’t work. The value_template should be:

value_template: >
        {{ ((as_timestamp(states('sensor.cert_expiry_timestamp_yourdomain')) - as_timestamp(states.sensor.date.last_updated)) / 86400) | int }}

Hope that helps someone else.

1 Like

Thanks, I’ve edited the above :slight_smile:

This isn’t working for me - I can’t manually call, call via automation or select in the the UI a core_nginx_proxy.

I also tried to set up the cert expiry integration but can’t get it to see the host; tried localhost, 127.0.0.1, the actual IP, the external IP, the DNS name, ports 80, 443, 8123.

Any ideas?

Thanks!

Are you using that add-on?

image

Doh. I’m using this one:

image

What’s the advantage of that one?!

Not sure I have the same problem now, but a host restart does fix it. Mine worked flawlessly (a good couple of years now) but started giving me trouble lately. I’m not sure if it’s always been an issue though as I’m less active now than I was. Could be that I just always happened to restart the host inside the 90 days so never noticed the problem.

@mrrodge If you aren’t using Nginx (I am not), you can just call service “Home Assistant Core Integration: Restart”, which will restart HA completely and achieve the result of presenting the new cert. I schedule this for the middle of the night and I am sure that all my MQTT devices us appropriate retain flags so that HA is always properly informed of state (never assume a reboot won’t happen).

One other update, I was having problems with the sensor template getting an actual value as the latter half of the value template wasn’t returning a numeric value (was returning None). Instead, I replaced to subtract current date/time from cert expiration, which yields the desired result (the number of days the cert has left).

Full sensor code from configuration.yaml is as follows:

sensor:
- platform: template
  sensors:
    s_cert_expiry_d:
      friendly_name: 'Cert Expiry'
      value_template: >
        {{ ((as_timestamp(states('sensor.cert_expiry_timestamp_your_domain')) - as_timestamp(now())) / 86400) | int }}
      unit_of_measurement: 'days'
1 Like