Skip to content

duckdns: Proper Support for Single-TXT Domains & Fix Let's Encrypt Rate-Limit#4126

Merged
agners merged 1 commit intohome-assistant:masterfrom
Xebozone:DuckDNS_ImprovedDehydratedScript
Aug 18, 2025
Merged

duckdns: Proper Support for Single-TXT Domains & Fix Let's Encrypt Rate-Limit#4126
agners merged 1 commit intohome-assistant:masterfrom
Xebozone:DuckDNS_ImprovedDehydratedScript

Conversation

@Xebozone
Copy link
Contributor

@Xebozone Xebozone commented Aug 16, 2025

  • Use Xebozone fork of Dehydrated with support for Single-TXT domains (such as DuckDNS)
  • Revise run to use the new parameters for dehydrated
  • Version bump
  • Updated Changelogs

Summary by CodeRabbit

  • New Features

    • Added support for single-TXT DNS validation domains.
    • Improved certificate renewal by processing all domains in a single run for better reliability and speed.
  • Chores

    • Updated underlying certificate tooling to a newer fork/version for enhanced compatibility.
  • Documentation

    • Added changelog entry for version 1.26.0.

… (such as DuckDNS)

- Revise run to use the new parameters for dehydrated
- Version bump
- Updated Changelogs
@Xebozone Xebozone changed the title Proper Support for Single-TXT Domains Fix Let's Encrypt Rate-Limit Resolution duckDns: Proper Support for Single-TXT Domains Fix Let's Encrypt Rate-Limit Resolution Aug 16, 2025
@Xebozone Xebozone changed the title duckDns: Proper Support for Single-TXT Domains Fix Let's Encrypt Rate-Limit Resolution duckDns: Proper Support for Single-TXT Domains & Fix Let's Encrypt Rate-Limit Aug 16, 2025
@coderabbitai
Copy link
Contributor

coderabbitai bot commented Aug 16, 2025

📝 Walkthrough

Walkthrough

Updates dehydrated source and version, bumps add-on version to 1.26.0, and revises the renewal script to invoke dehydrated once with aggregated domain arguments instead of per-domain passes and a final combine. Documentation (CHANGELOG) updated accordingly. No public interfaces changed.

Changes

Cohort / File(s) Summary
Documentation
duckdns/CHANGELOG.md
Added 1.26.0 entry noting updated dehydrated fork and new parameters; no code changes.
Versioning/Metadata
duckdns/config.yaml
Bumped add-on version from 1.25.0 to 1.26.0.
Build/Dependencies
duckdns/build.yaml, duckdns/Dockerfile
Updated DEHYDRATED_VERSION from 0.7.1 to 0.8.0; switched download URL to Xebozone/dehydrated and removed leading “v” in version path.
Runtime Renewal Flow
duckdns/rootfs/.../duckdns/run
Replaced per-domain dehydrated calls and combine step with a single dehydrated run using aggregated domain args and --separate-challenges; function signatures unchanged.

Sequence Diagram(s)

sequenceDiagram
    participant s6 as s6 service
    participant run as duckdns/run
    participant dehydrated as dehydrated
    participant LE as Let's Encrypt ACME

    s6->>run: start
    run->>run: Build domain_args from domains + aliases
    run->>dehydrated: --cron --separate-challenges ${domain_args}
    dehydrated->>LE: Perform ACME challenges/renewals
    LE-->>dehydrated: Challenge results/certificates
    dehydrated-->>run: Exit status
    run-->>s6: Complete (update timestamp if renewed)
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Tip

🔌 Remote MCP (Model Context Protocol) integration is now available!

Pro plan users can now connect to remote MCP servers from the Integrations page. Connect with popular remote MCPs such as Notion and Linear to add more context to your reviews and chats.

✨ Finishing Touches
🧪 Generate unit tests
  • Create PR with unit tests
  • Post copyable unit tests in a comment

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.

Support

Need help? Create a ticket on our support page for assistance with any issues or questions.

CodeRabbit Commands (Invoked using PR/Issue comments)

Type @coderabbitai help to get the list of available commands.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai or @coderabbitai title anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Status, Documentation and Community

  • Visit our Status Page to check the current availability of CodeRabbit.
  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

🔭 Outside diff range comments (3)
duckdns/rootfs/etc/s6-overlay/s6-rc.d/duckdns/run (3)

31-35: Alias extraction is incorrect; jq builds an alias→domain map but looks up by domain key.
This returns no aliases. Select aliases by value (domain) instead.

Apply this diff:

-    for domain in ${domains}; do
-        for alias in $(jq --raw-output --exit-status "[.aliases[]|{(.alias):.domain}]|add.\"${domain}\" | select(. != null)" /data/options.json) ; do
-            aliases+=("${alias}")
-        done
-    done
+    for domain in ${domains}; do
+        # Collect aliases whose "domain" matches the current domain
+        while IFS= read -r alias; do
+            [[ -n "$alias" ]] && aliases+=("$alias")
+        done < <(jq -r --arg domain "$domain" '.aliases // [] | .[] | select(.domain == $domain) | .alias' /data/options.json)
+    done

37-39: Make domain array construction robust to whitespace and quoting.
Rely on newline-delimited expansion from bashio rather than generic word-splitting to avoid accidental concatenation.

Apply this diff and update the loop at Line 31 accordingly:

-    domains=$(bashio::config 'domains')
+    # Produce a newline-delimited list for safe array parsing
+    mapfile -t domainsarray < <(bashio::config 'domains | join($"\n")')
@@
-    for domain in ${domains}; do
+    for domain in "${domainsarray[@]}"; do
@@
-    readarray -t domainsarray <<< "$domains" # line-separated list of domains into an array
+    # domainsarray already populated above

100-102: DuckDNS domain sanitization: block wildcard aliases & handle case sensitivity

Our current regex will pull in domains from wildcard entries (e.g. *.bad.duckdns.orgbad.duckdns.org) and ignores any uppercase input. To tighten this up:

• Exclude any entry beginning with *. before extracting domains
• Normalize to lowercase (or, if you must preserve case, add -i to grep)
• Only match a single-label DuckDNS host (no deeper subdomains)

Proposed pipeline (bash-compliant, avoids look-arounds):

duckdnsDomains=$(
  echo "$DOMAINS" \
    | tr '[:upper:]' '[:lower:]' \
    | tr ' ,>' '\n' \
    | grep -v '^\*\.' \
    | grep -E '^[a-z0-9-]+\.duckdns\.org$' \
    | sort -u \
    | paste -sd,
)

This will:

  1. Lowercase everything (so GOOD.DUCKDNS.ORG is captured)
  2. Split on spaces, commas or >
  3. Drop any line starting with *.
  4. Match only exactly one-label subdomains of duckdns.org
  5. Deduplicate and rejoin with commas
🧹 Nitpick comments (3)
duckdns/CHANGELOG.md (1)

5-6: Tighten grammar for clarity and subject-verb agreement.
Use “that handle” (plural) and remove filler.

Apply this diff:

-- Updated dehydrated fork with support for single-txt domains
-- Use the new dehydrated script parameters which handles individual domain processing now
+- Updated dehydrated fork with support for single TXT domains
+- Use the new dehydrated script parameters that handle individual-domain processing
duckdns/Dockerfile (1)

8-8: Harden curl invocation & pin script version

To improve reliability when fetching the Dehydrated script:

• In duckdns/Dockerfile, change the curl flags to fail fast on network issues:

- && curl -s -o /usr/bin/dehydrated \
+ && curl -fsSL -o /usr/bin/dehydrated \
    "https://raw.githubusercontent.com/Xebozone/dehydrated/${DEHYDRATED_VERSION}/dehydrated" \
+ && chmod a+x /usr/bin/dehydrated

• (Optional, but recommended) Pin to a commit SHA to avoid surprises if a tag is moved:

ARG DEHYDRATED_COMMIT=<commit-sha>
RUN curl -fsSL -o /usr/bin/dehydrated \
    "https://raw.githubusercontent.com/Xebozone/dehydrated/${DEHYDRATED_COMMIT}/dehydrated" \
  && chmod a+x /usr/bin/dehydrated

Since DEHYDRATED_VERSION is declared without a default value, please build the image with a concrete version (or provide a default in the Dockerfile) and verify that:

curl -sSfI "https://raw.githubusercontent.com/Xebozone/dehydrated/${DEHYDRATED_VERSION}/dehydrated"

returns HTTP 200 before merging.

duckdns/rootfs/etc/s6-overlay/s6-rc.d/duckdns/run (1)

49-55: Guard against empty domain_args and avoid masking failures.
Skip dehydrated when no domains/aliases were found and surface errors instead of swallowing them.

Apply this diff:

-    for domain in "${domainsAndAliases[@]}"; do
-        domain_args+=("--domain" "${domain}")
-    done
+    for domain in "${domainsAndAliases[@]}"; do
+        domain_args+=("--domain" "${domain}")
+    done
@@
-    # Do the certificate renewals
-    dehydrated --cron --separate-challenges --algo "${ALGO}" --hook /root/hooks.sh --challenge dns-01 "${domain_args[@]}" --out "${CERT_DIR}" --config "${WORK_DIR}/config" || true
+    # Do the certificate renewals
+    if [ ${#domain_args[@]} -eq 0 ]; then
+        bashio::log.warning "No domains or aliases found; skipping certificate renewal"
+        return 0
+    fi
+    if ! dehydrated --cron --separate-challenges --algo "${ALGO}" --hook /root/hooks.sh --challenge dns-01 "${domain_args[@]}" --out "${CERT_DIR}" --config "${WORK_DIR}/config"; then
+        bashio::log.warning "dehydrated run failed"
+    fi
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
Cache: Disabled due to data retention organization setting
Knowledge Base: Disabled due to data retention organization setting

💡 Knowledge Base configuration:

  • MCP integration is disabled by default for public repositories
  • Jira integration is disabled by default for public repositories
  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between b4c42bb and d571d23.

📒 Files selected for processing (5)
  • duckdns/CHANGELOG.md (1 hunks)
  • duckdns/Dockerfile (1 hunks)
  • duckdns/build.yaml (1 hunks)
  • duckdns/config.yaml (1 hunks)
  • duckdns/rootfs/etc/s6-overlay/s6-rc.d/duckdns/run (1 hunks)
🧰 Additional context used
📓 Path-based instructions (1)
*/**(html|markdown|md)

⚙️ CodeRabbit Configuration File

*/**(html|markdown|md): - For instructional content in documentation, use a direct and authoritative tone. Avoid expressions of politeness such as 'may' or 'please', and ensure the goal of the instruction is fronted.

  • Apply the Microsoft Style Guide to ensure documentation maintains clarity and conciseness.
  • In step-by-step instructions, front the location phrase in the instructional sentence.
  • In step-by-step instructions, front the 'goal' in the instructional sentence.
  • In step-by-step instructions, if in doubt what to front, front the 'goal' before the location phrase in the instructional sentence.
  • do not hyphenate terms like 'top-right' or 'bottom-left' with 'corner'

*/**(html|markdown|md): - Use bold to mark UI strings.

  • If "" are used to mark UI strings, replace them by bold.

  • Be brief in your replies and don't add fluff like "thank you for..." and "Please let me know if"

  • Use sentence-style capitalization also in headings.

do not comment on HTML used for icons

Avoid flagging inline HTML for embedding videos in future reviews for this repository.

Files:

  • duckdns/build.yaml
  • duckdns/Dockerfile
  • duckdns/config.yaml
  • duckdns/CHANGELOG.md
🔇 Additional comments (2)
duckdns/config.yaml (1)

2-2: Version bump looks correct and consistent with PR scope.
Matches CHANGELOG and associated Dehydrated update across the PR.

duckdns/build.yaml (1)

12-12: Confirmed DEHYDRATED_VERSION Tag Resolves Correctly
The raw URL for DEHYDRATED_VERSION 0.8.0 returns HTTP 200 OK, so the non-prefixed tag is valid. No changes needed.

@agners agners changed the title duckDns: Proper Support for Single-TXT Domains & Fix Let's Encrypt Rate-Limit duckdns: Proper Support for Single-TXT Domains & Fix Let's Encrypt Rate-Limit Aug 18, 2025
Copy link
Member

@agners agners left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM, thanks!

@agners agners merged commit 10dfaa5 into home-assistant:master Aug 18, 2025
11 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants