addons icon indicating copy to clipboard operation
addons copied to clipboard

LetsEncrypt Dynu DNS Challenge Broken after 5.4.4

Open pumrum opened this issue 6 months ago • 9 comments

Describe the issue you are experiencing

I've been running the Dynu challenge config since it dropped a while ago... has always worked perfect. Sometime after 5.4.4 it stopped working. Confirmed NOT WORKING in 5.4.9, confirmed WORKING in 5.4.4. Haven't tried any version in between, but the releases were pretty focused and tightly packed in there.

SYMPTOM: When the script creates the TXT record to do the DNS challenge, it is not including the entire FQDN, it's only including the domain and tld. So it's incorrectly creating "_acme-challenge.domain.com" instead of the proper "_acme-challenge.hostname.domain.com"

What type of installation are you running?

Home Assistant OS

Which operating system are you running on?

Home Assistant Operating System

Which add-on are you reporting an issue with?

Let's Encrypt

What is the version of the add-on?

5.4.9

Steps to reproduce the issue

  1. Configure Dynu DNS challenge to use a hostname.domain.com TXT challenge
  2. Note in your Dynu dashboard that "_acme-challenge.domain.com" gets incorrectly created
  3. Note in the HA LE log that it is correctly querying "_acme-challenge.hostname.domain.com"
  4. Roll back to LE add-on 5.4.4, repeat steps 1-3 and note that at step 3 it works fine

Configuration:

domains:
  - hostname.domain.com
email: [email protected]
keyfile: privkey.pem
certfile: fullchain.pem
challenge: dns
dns:
  provider: dns-dynu
  dynu_auth_token: asdfjklasdfjklasdfjkl
  propagation_seconds: 120

System Health information

System Information

version core-2025.2.5
installation_type Home Assistant OS
dev false
hassio true
docker true
user root
virtualenv false
python_version 3.13.1
os_name Linux
os_version 6.6.73-haos
arch x86_64
timezone redacted
config_dir /config
Home Assistant Community Store
GitHub API ok
GitHub Content ok
GitHub Web ok
GitHub API Calls Remaining 5000
Installed Version 1.34.0
Stage running
Available Repositories 1735
Downloaded Repositories 7
HACS Data ok
Home Assistant Cloud
logged_in false
can_reach_cert_server ok
can_reach_cloud_auth ok
can_reach_cloud ok
Home Assistant Supervisor
host_os Home Assistant OS 14.2
update_channel stable
supervisor_version supervisor-2025.05.1
agent_version 1.6.0
docker_version 27.2.0
disk_total 30.8 GB
disk_used 6.0 GB
healthy true
supported true
host_connectivity true
supervisor_connectivity true
ntp_synchronized true
virtualization kvm
board ova
supervisor_api ok
version_api ok
installed_addons File editor (5.8.0), Terminal & SSH (9.17.0), Let's Encrypt (5.4.4), Mosquitto broker (6.4.0), Z-Wave JS UI (3.21.0), Network UPS Tools (0.14.1)
Dashboards
dashboards 4
resources 6
views 6
mode storage
Network Configuration

redacted

Recorder
oldest_recorder_run February 27, 2025 at 01:09
current_recorder_run May 10, 2025 at 22:12
estimated_db_size 55.35 MiB
database_engine sqlite
database_version 3.47.1

Anything in the Supervisor logs that might be useful for us?


Anything in the add-on logs that might be useful for us?

****************
LE Add-On 5.4.9 (redacted for privacy):
****************
s6-rc: info: service s6rc-oneshot-runner: starting
s6-rc: info: service s6rc-oneshot-runner successfully started
s6-rc: info: service fix-attrs: starting
s6-rc: info: service fix-attrs successfully started
s6-rc: info: service legacy-cont-init: starting
cont-init: info: running /etc/cont-init.d/file-structure.sh
cont-init: info: /etc/cont-init.d/file-structure.sh exited 0
s6-rc: info: service legacy-cont-init successfully started
s6-rc: info: service legacy-services: starting
services-up: info: copying legacy longrun lets-encrypt (no readiness notification)
s6-rc: info: service legacy-services successfully started
[22:14:42] INFO: Selected DNS Provider: dns-dynu
[22:14:42] INFO: Use propagation seconds: 120
[22:14:42] INFO: Detecting existing certificate type for hostname.domain.com
Saving debug log to /var/log/letsencrypt/letsencrypt.log
[22:14:43] INFO: Existing certificate using 'ecdsa' key type.
Saving debug log to /var/log/letsencrypt/letsencrypt.log
Renewing an existing certificate for hostname.domain.com
Waiting 120 seconds for DNS changes to propagate
Certbot failed to authenticate some domains (authenticator: dns-dynu). The Certificate Authority reported these problems:
  Domain: hostname.domain.com
  Type:   unauthorized
  Detail: Incorrect TXT record "xTsdfaliwejflwijelfiwejflDo1zEqqPifn3FB8-tIM" found at _acme-challenge.hostname.domain.com
Hint: The Certificate Authority failed to verify the DNS TXT records created by --dns-dynu. Ensure the above domains are hosted by this DNS provider, or try increasing --dns-dynu-propagation-seconds (currently 120 seconds).
Some challenges have failed.
Ask for help or search for solutions at https://community.letsencrypt.org. See the logfile /var/log/letsencrypt/letsencrypt.log or re-run Certbot with -v for more details.
s6-rc: info: service legacy-services: stopping
s6-rc: info: service legacy-services successfully stopped
s6-rc: info: service legacy-cont-init: stopping
s6-rc: info: service legacy-cont-init successfully stopped
s6-rc: info: service fix-attrs: stopping
s6-rc: info: service fix-attrs successfully stopped
s6-rc: info: service s6rc-oneshot-runner: stopping
s6-rc: info: service s6rc-oneshot-runner successfully stopped
s6-rc: info: service s6rc-oneshot-runner: starting
s6-rc: info: service s6rc-oneshot-runner successfully started
s6-rc: info: service fix-attrs: starting
s6-rc: info: service fix-attrs successfully started
s6-rc: info: service legacy-cont-init: starting
cont-init: info: running /etc/cont-init.d/file-structure.sh
cont-init: info: /etc/cont-init.d/file-structure.sh exited 0
s6-rc: info: service legacy-cont-init successfully started
s6-rc: info: service legacy-services: starting
services-up: info: copying legacy longrun lets-encrypt (no readiness notification)
s6-rc: info: service legacy-services successfully started
[22:19:46] INFO: Selected DNS Provider: dns-dynu
[22:19:46] INFO: Use propagation seconds: 120
[22:19:46] INFO: Detecting existing certificate type for hostname.domain.com
Saving debug log to /var/log/letsencrypt/letsencrypt.log
[22:19:47] INFO: Existing certificate using 'ecdsa' key type.
Saving debug log to /var/log/letsencrypt/letsencrypt.log
Renewing an existing certificate for hostname.domain.com
Waiting 120 seconds for DNS changes to propagate
Certbot failed to authenticate some domains (authenticator: dns-dynu). The Certificate Authority reported these problems:
  Domain: hostname.domain.com
  Type:   dns
  Detail: DNS problem: NXDOMAIN looking up TXT for _acme-challenge.hostname.domain.com - check that a DNS record exists for this domain
Hint: The Certificate Authority failed to verify the DNS TXT records created by --dns-dynu. Ensure the above domains are hosted by this DNS provider, or try increasing --dns-dynu-propagation-seconds (currently 120 seconds).
Some challenges have failed.
Ask for help or search for solutions at https://community.letsencrypt.org. See the logfile /var/log/letsencrypt/letsencrypt.log or re-run Certbot with -v for more details.
s6-rc: info: service legacy-services: stopping
s6-rc: info: service legacy-services successfully stopped

>>check Dynu dashboard<<
_acme-challenge.domain.com = "asdfjkl;asdfjkl;asdfjkl;"
_acme-challenge.hostname.domain.com = <does not exist>


****************
LE Add-On 5.4.4 (redacted for privacy):
****************
s6-rc: info: service s6rc-oneshot-runner: starting
s6-rc: info: service s6rc-oneshot-runner successfully started
s6-rc: info: service fix-attrs: starting
s6-rc: info: service fix-attrs successfully started
s6-rc: info: service legacy-cont-init: starting
cont-init: info: running /etc/cont-init.d/file-structure.sh
cont-init: info: /etc/cont-init.d/file-structure.sh exited 0
s6-rc: info: service legacy-cont-init successfully started
s6-rc: info: service legacy-services: starting
services-up: info: copying legacy longrun lets-encrypt (no readiness notification)
s6-rc: info: service legacy-services successfully started
[20:28:51] INFO: Selected DNS Provider: dns-dynu
[20:28:51] INFO: Use propagation seconds: 120
[20:28:51] INFO: Detecting existing certificate type for hostname.domain.com
Saving debug log to /var/log/letsencrypt/letsencrypt.log
[20:28:53] INFO: Existing certificate using 'ecdsa' key type.
Saving debug log to /var/log/letsencrypt/letsencrypt.log
Renewing an existing certificate for hostname.domain.com
Waiting 120 seconds for DNS changes to propagate
Successfully received certificate.
Certificate is saved at: /data/letsencrypt/live/hostname.domain.com/fullchain.pem
Key is saved at:         /data/letsencrypt/live/hostname.domain.com/privkey.pem
This certificate expires on 2025-08-08.
These files will be updated when the certificate renews.
NEXT STEPS:
- The certificate will need to be renewed before it expires. Certbot can automatically renew the certificate in the background, but you may need to take steps to enable that functionality. See https://certbot.org/renewal-setup for instructions.
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
If you like Certbot, please consider supporting our work by:
 * Donating to ISRG / Let's Encrypt:   https://letsencrypt.org/donate
 * Donating to EFF:                    https://eff.org/donate-le
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
s6-rc: info: service legacy-services: stopping
s6-rc: info: service legacy-services successfully stopped
s6-rc: info: service legacy-cont-init: stopping
s6-rc: info: service legacy-cont-init successfully stopped
s6-rc: info: service fix-attrs: stopping
s6-rc: info: service fix-attrs successfully stopped
s6-rc: info: service s6rc-oneshot-runner: stopping
s6-rc: info: service s6rc-oneshot-runner successfully stopped

Additional information

No response

pumrum avatar May 14 '25 00:05 pumrum

Hey @pumrum,

Looking into the recent commits (since 5.4.4) touching the core business logic in the run Bash script, I don't see any changes that would directly impact the domain list or the DNS entries used for Let's Encrypt validation. Also, there's no specific Dynu DNS logic involved in those changes. Therefore, if something were broken here, we would expect it to affect any DNS challenge, but that doesn't appear to be happening.

Upon re-examining the unmodified sections, I noticed that the script passes domains to Certbot using an array index of 1:https://github.com/home-assistant/addons/blob/e2a8350ed33d022ace046966604f083e778f99e3/letsencrypt/rootfs/etc/services.d/lets-encrypt/run#L411 Considering that Bash arrays begin indexing at 0, the recent modification to the configuration schema — specifically the removal of a potentially confusing default empty option in the UI — is the only thing I can think of, which might alter how the domain configuration is being handled.

I'm planning a PR with this indexing fix and a few other tweaks. However, I'm not entirely convinced this is the root cause of the issue you're seeing. You mentioned the addon creating a TXT entry with _acme-challenge.domain.com, while Let's Encrypt expects the FQDN _acme-challenge.hostname.domain.com. Instead, the logs you shared indicate the Certificate Authority found an entry with the wrong value rather than a missing entry.

Incorrect TXT record "xTsdfaliwejflwijelfiwejflDo1zEqqPifn3FB8-tIM" found at _acme-challenge.hostname.domain.com

This makes me wonder if there might have been a temporary issue, like a lingering or concurrent TXT records present before the script ran.

I suggest to try again once a build with the 0-indexing change is out. However, could you double-check your addon configuration for any empty domain entries (empty "chips" in the UI or a dash with no value in the YAML) and your DNS records for any leftover ACME entries before you try to run the addon again.

83noit avatar May 14 '25 20:05 83noit

@83noit --

Thanks so much for the quick reply and thorough review. I did a lot more testing than I summarized in the original bug report to make sure I didn't fat finger anything. It's possible (likely) that part of my testing resulted in the creation of the correctly named TXT record -- or it may have been left over from a previous certificate renewal. I've noticed that certbot isn't 100% on cleaning up the old TXT records, but that's never impacted renewal before for this or any of my many many other cerrtbot implementations.

I do have a second nearly identical HA instance that I have running LE addon 5.4.9 that isn't quite ready for renewal yet - should be good in ~5 days (cert expires June 19). As soon as that's ready to renew I will clean up all TXT records from my domain and test with the latest available LE version and post the logs here.

pumrum avatar May 15 '25 00:05 pumrum

I tested 5.4.9 again with a clean slate and verified that the issue exists as originally described:

  1. Check Dynu dashboard and verify that no TXT records exist in the entire domain
  2. Start the LetEncrypt 5.4.9 add-on, monitor the log
  3. Renewal fails with "DNS problem: NXDOMAIN looking up TXT for _acme-challenge.hostname.domain.com - check that a DNS record exists for this domain"
  4. Check the Dynu dashboard and verify that a TXT record now exists, but it's "_acme-challenge.domain.com" (note: missing the hostname, should be _acme-challenge.hostname.domain.com)

Unfortunately I don't have a backup of the LE 5.4.4 add-on on this host so I will wait for your PR to post and see if that works. If I get into a pinch I may be able to migrate the backup of the 5.4.4 add-on from my other node or cobble something together.

Here is the full log of this clean test:

s6-rc: info: service s6rc-oneshot-runner successfully started
s6-rc: info: service fix-attrs: starting
s6-rc: info: service fix-attrs successfully started
s6-rc: info: service legacy-cont-init: starting
cont-init: info: running /etc/cont-init.d/file-structure.sh
cont-init: info: /etc/cont-init.d/file-structure.sh exited 0
s6-rc: info: service legacy-cont-init successfully started
s6-rc: info: service legacy-services: starting
services-up: info: copying legacy longrun lets-encrypt (no readiness notification)
s6-rc: info: service legacy-services successfully started
[20:36:21] INFO: Selected DNS Provider: dns-dynu
[20:36:21] INFO: Use propagation seconds: 120
[20:36:22] INFO: Detecting existing certificate type for hostname.domain.com
Saving debug log to /var/log/letsencrypt/letsencrypt.log
[20:36:23] INFO: Existing certificate using 'ecdsa' key type.
Saving debug log to /var/log/letsencrypt/letsencrypt.log
Renewing an existing certificate for hostname.domain.com
Waiting 120 seconds for DNS changes to propagate
Certbot failed to authenticate some domains (authenticator: dns-dynu). The Certificate Authority reported these problems:
  Domain: hostname.domain.com
  Type:   dns
  Detail: DNS problem: NXDOMAIN looking up TXT for _acme-challenge.hostname.domain.com - check that a DNS record exists for this domain
Hint: The Certificate Authority failed to verify the DNS TXT records created by --dns-dynu. Ensure the above domains are hosted by this DNS provider, or try increasing --dns-dynu-propagation-seconds (currently 120 seconds).
Some challenges have failed.
Ask for help or search for solutions at https://community.letsencrypt.org. See the logfile /var/log/letsencrypt/letsencrypt.log or re-run Certbot with -v for more details.
s6-rc: info: service legacy-services: stopping
s6-rc: info: service legacy-services successfully stopped
s6-rc: info: service legacy-cont-init: stopping
s6-rc: info: service legacy-cont-init successfully stopped
s6-rc: info: service fix-attrs: stopping
s6-rc: info: service fix-attrs successfully stopped
s6-rc: info: service s6rc-oneshot-runner: stopping
s6-rc: info: service s6rc-oneshot-runner successfully stopped

pumrum avatar May 21 '25 00:05 pumrum

I have the exact same issue on 5.4.9. To get round this (my certificate was going to expire in a few days) I set the domain to a wildcard entry (*.domainname) as this doesn't try to create a TXT record with hostname in it. Once the issue is fixed I will change my config to go back to hostname.

jim-downie avatar May 24 '25 10:05 jim-downie

I have the exact same issue on 5.4.9. To get round this (my certificate was going to expire in a few days) I set the domain to a wildcard entry (*.domainname) as this doesn't try to create a TXT record with hostname in it. Once the issue is fixed I will change my config to go back to hostname.

thanks for confirming I'm not the only one ... and for the workaround! are you using Dynu as well or are you using a different domain provider? if it's global across domains I'll remove 'dynu' from the issue title to be more accurate.

pumrum avatar May 25 '25 17:05 pumrum

Really curious to know if it’s limited to Dynu, as I cannot reproduce it with the providers I use.

I’ve opened a PR with various changes. The index of 1 mentioned in my previous comment was a red herring. So there’s only a minor hardening against empty element when constructing the domain list. I’d be pleasantly surprised if it solves your issue. If not, this will need more work to understand what is happening.

83noit avatar May 25 '25 22:05 83noit

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.

github-actions[bot] avatar Jun 24 '25 22:06 github-actions[bot]

Does the following suggest that the root cause lies upstream with the certbot or certbot-dns-dynu code, and not with the letsencrypt addon code?

bit of an interesting update ... I was working to generate a certificate for an Ubuntu LXC container completely unrelated to homeassistant -- and I ran into the same issue. I installed certbot using:

sudo apt install python3 python3-pip openssl -y
sudo pip3 install certbot certbot-dns-dynu

and then used the following to try to generate a staging certificate:

certbot certonly --staging --non-interactive --agree-tos --email [email protected] --authenticator dns-dynu --dns-dynu-credentials /etc/letsencrypt/dynu/dynu.ini -d yourdomain.example.com

when I ran the command it created _acme-challenge.example.com INCORRECTLY, but then it went looking for a TXT record at _acme-challenge.yourdomain.example.com CORRECTLY. I verified via the dynu dashboard that the TXT record was created with the wrong domain name (missing the subdomain) after verifying that no TXT records existed before I started.

pumrum avatar Jun 25 '25 00:06 pumrum

apologies for the double-update, but finally found some breadcrumbs worth following. including some links here in case someone lands here looking for a fix for the subdomain issue with letsencrypt certificates using dynu DNS authentication. If it's OK I'd like to leave this issue open until the upstream PR is merged and everything flows down to this LE add-on in HA and things go back to working properly.

This is the PR to address the root cause issue in the dns-lexicon library

This is the issue logged with the certbot-dns-dynu plugin for certbot that led me to the PR above

This is the same issue logged with the LetsEncrypt community that was never resolved and has since been closed, but which gave me the confirmation that this has nothing to do with HA..

pumrum avatar Jun 25 '25 00:06 pumrum

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.

github-actions[bot] avatar Jul 25 '25 00:07 github-actions[bot]

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.

github-actions[bot] avatar Aug 24 '25 04:08 github-actions[bot]

I can confirm the latest version available today is still failing with above issue on missing hostname as part of resolution.

lgp1985 avatar Sep 23 '25 17:09 lgp1985

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.

github-actions[bot] avatar Oct 23 '25 18:10 github-actions[bot]