[GH-ISSUE #1459] Let's Encrypt DST Root CA X3 Expiration fix for APIs #1127

Closed
opened 2026-02-26 06:35:53 +03:00 by kerem · 7 comments
Owner

Originally created by @chackl1990 on GitHub (Oct 5, 2021).
Original GitHub issue: https://github.com/NginxProxyManager/nginx-proxy-manager/issues/1459

Is your feature request related to a problem? Please describe.
The DST Root Certificate of Let's Encrypt expired:
https://letsencrypt.org/docs/dst-root-ca-x3-expiration-september-2021/
NPM still does include the chain of trust for the DST Root CA X3
In my case all Android devices could not speak to the apis with SSL check - because the DST Root CA X3 expired.

Describe the solution you'd like
After some search i found that calling certbot with --preferred-chain "ISRG Root X1" will work
so i did ssh to the container an executed this:
certbot renew --preferred-chain "ISRG Root X1" --force-renewal

Describe alternatives you've considered
I think an alternative would be to set apis to untrusted SSL -> not a good solution.
also editing the cert-conf-files may work - but the renew is not forced then - so executing <certbot renew --preferred-chain "ISRG Root X1" --force-renewal> would work and also it edits the config files.

Additional context
I found the file "backend/internal/certificate.js"
here are built the commandline parametes for certbot - adding --preferred-chain "ISRG Root X1" to processExpiringHosts and requestLetsEncryptSsl might be fine - but i do not have the skills to test it - otherwise i would have made a pull request.
Could anyone test this?

Thank you and kind regards!

Originally created by @chackl1990 on GitHub (Oct 5, 2021). Original GitHub issue: https://github.com/NginxProxyManager/nginx-proxy-manager/issues/1459 **Is your feature request related to a problem? Please describe.** The DST Root Certificate of Let's Encrypt expired: https://letsencrypt.org/docs/dst-root-ca-x3-expiration-september-2021/ NPM still does include the chain of trust for the DST Root CA X3 In my case all Android devices could not speak to the apis with SSL check - because the DST Root CA X3 expired. **Describe the solution you'd like** After some search i found that calling certbot with --preferred-chain "ISRG Root X1" will work so i did ssh to the container an executed this: certbot renew --preferred-chain "ISRG Root X1" --force-renewal **Describe alternatives you've considered** I think an alternative would be to set apis to untrusted SSL -> not a good solution. also editing the cert-conf-files may work - but the renew is not forced then - so executing <certbot renew --preferred-chain "ISRG Root X1" --force-renewal> would work and also it edits the config files. **Additional context** I found the file "backend/internal/certificate.js" here are built the commandline parametes for certbot - adding --preferred-chain "ISRG Root X1" to processExpiringHosts and requestLetsEncryptSsl might be fine - but i do not have the skills to test it - otherwise i would have made a pull request. Could anyone test this? Thank you and kind regards!
kerem 2026-02-26 06:35:53 +03:00
Author
Owner

@chaptergy commented on GitHub (Oct 5, 2021):

Is this actually an NPM issue or rather a certbot issue? Shouldn't the letsencrypt servers skip the DST Root CA X3 instead of it having to be specified client side?
Adding the --preferred-chain would mainly be a workaround and should not be a permanent fix, certbot should know which chain to use. Maybe updating certbot would already fix this? Though I can't find anything about it in the changelog.

<!-- gh-comment-id:934552623 --> @chaptergy commented on GitHub (Oct 5, 2021): Is this actually an NPM issue or rather a certbot issue? Shouldn't the letsencrypt servers skip the DST Root CA X3 instead of it having to be specified client side? Adding the `--preferred-chain` would mainly be a workaround and should not be a permanent fix, certbot should know which chain to use. Maybe updating certbot would already fix this? Though I can't find anything about it in the changelog.
Author
Owner

@chackl1990 commented on GitHub (Oct 5, 2021):

I read something that they wanted to keep compatibility (before exp.) to old devices so they also include the DST Trust chain also - and in normal case this would be fine - but it seems that some android app apis seem to check every trust chain - finding an expired cert in one and saying that it is not vaild. As certbot just includes all trust chains possible (i think) without any parameter.

<!-- gh-comment-id:934798669 --> @chackl1990 commented on GitHub (Oct 5, 2021): I read something that they wanted to keep compatibility (before exp.) to old devices so they also include the DST Trust chain also - and in normal case this would be fine - but it seems that some android app apis seem to check every trust chain - finding an expired cert in one and saying that it is not vaild. As certbot just includes all trust chains possible (i think) without any parameter.
Author
Owner

@chaptergy commented on GitHub (Oct 5, 2021):

If this issue is specific to your apps used on the devices it might be sufficient for your to mount a custom /etc/letsencrypt.ini into your container with the additional line:

...
preferred-chain = ISRG Root X1

If more people have this issue, we should consider making this the default. I for one have not encountered this issue yet, all my letsencrypt certificates are signed by ISRG Root X1 without having to set anything.

<!-- gh-comment-id:934885833 --> @chaptergy commented on GitHub (Oct 5, 2021): If this issue is specific to your apps used on the devices it might be sufficient for your to mount a custom [`/etc/letsencrypt.ini`](https://github.com/jc21/nginx-proxy-manager/blob/develop/docker/rootfs/etc/letsencrypt.ini) into your container with the additional line: ```ini ... preferred-chain = ISRG Root X1 ``` If more people have this issue, we should consider making this the default. I for one have not encountered this issue yet, all my letsencrypt certificates are signed by ISRG Root X1 without having to set anything.
Author
Owner

@calne-ca commented on GitHub (Oct 6, 2021):

I have the exact same issue, but with python not npm. For some reason it's not an issue in any browser or java application, but a python application of mine stopped working after the DST cert expired. Setting the preferred-chain to ISRG Root X1 and re-newing my certs afterwards fixed the issue for me.

Just a wild guess, but I think the issue is not that the certs are not signed by the ISRG Root X1. They always get signed by ISRG Root X1 (through R3) even without setting the preferred chain. I think the issue is that if you don't set this as preferred chain, the full chain will contain the ISRG Root X1 which is signed by DST Root CA X3. Now even if ISRG Root X1 is a trusted CA, some applications, like python, apparently still validate all certs in the chain, meaning that it will also try to validate the DST Root CA X3 since it is the issuer of the ISRG Root X1. I guess if the chain does not contain the ISRG Root X1 it only validates ISRG Root X1 since it is the issuer of the R3 cert. But since the ISRG Root X1 cert is not in the chain itself it won't validate its issuer.

<!-- gh-comment-id:937225491 --> @calne-ca commented on GitHub (Oct 6, 2021): I have the exact same issue, but with python not npm. For some reason it's not an issue in any browser or java application, but a python application of mine stopped working after the DST cert expired. Setting the preferred-chain to ISRG Root X1 and re-newing my certs afterwards fixed the issue for me. Just a wild guess, but I think the issue is not that the certs are not signed by the ISRG Root X1. They always get signed by ISRG Root X1 (through R3) even without setting the preferred chain. I think the issue is that if you don't set this as preferred chain, the full chain will contain the ISRG Root X1 which is signed by DST Root CA X3. Now even if ISRG Root X1 is a trusted CA, some applications, like python, apparently still validate all certs in the chain, meaning that it will also try to validate the DST Root CA X3 since it is the issuer of the ISRG Root X1. I guess if the chain does not contain the ISRG Root X1 it only validates ISRG Root X1 since it is the issuer of the R3 cert. But since the ISRG Root X1 cert is not in the chain itself it won't validate its issuer.
Author
Owner

@psandgren commented on GitHub (Oct 12, 2021):

+1 Same problem here. Anoying for android development. I do blame LetsEncrypt for this one though.

<!-- gh-comment-id:940832224 --> @psandgren commented on GitHub (Oct 12, 2021): +1 Same problem here. Anoying for android development. I do blame LetsEncrypt for this one though.
Author
Owner

@chaptergy commented on GitHub (Oct 12, 2021):

Is adding

preferred-chain = ISRG Root X1

to the /etc/letsencrypt.ini working for you? Then I'll add it as a fix for everyone.

<!-- gh-comment-id:940842232 --> @chaptergy commented on GitHub (Oct 12, 2021): Is adding ```ini preferred-chain = ISRG Root X1 ``` to the `/etc/letsencrypt.ini` working for you? Then I'll add it as a fix for everyone.
Author
Owner

@psandgren commented on GitHub (Oct 12, 2021):

Yes. I can't say if it's needed, but I also removed all the certificates before renewing.

<!-- gh-comment-id:940923036 --> @psandgren commented on GitHub (Oct 12, 2021): Yes. I can't say if it's needed, but I also removed all the certificates before renewing.
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
starred/nginx-proxy-manager-NginxProxyManager#1127
No description provided.