www/caddy: Add DNS-01 challenge delegation via CNAME (#4950)

* caddy: Add DNS-01 override domain feature

Adds support for DNS-01 CNAME delegation through the dns_challenge_override_domain directive. This enables least-privilege DNS setups where the certificate domain delegates ACME challenges to a target domain managed by the configured DNS provider.

* Review feedback: Remove default defs and align validation string with existing one

---------

Co-authored-by: Christophe Neuerburg <c.neuerburg@sdsys.ch>
This commit is contained in:
sdsys-ch
2025-09-24 08:45:05 +02:00
committed by GitHub
parent dfcb4cb138
commit b2401a695c
3 changed files with 19 additions and 0 deletions
@@ -73,6 +73,16 @@
<formatter>boolean</formatter>
</grid_view>
</field>
<field>
<id>reverse.DnsChallengeOverrideDomain</id>
<label>DNS-01 Override Domain</label>
<type>text</type>
<help><![CDATA[If using CNAME delegation for DNS-01 challenges, enter the target domain here. The DNS provider will manage TXT records at '_acme-challenge.targetdomain' instead of the certificate domain. Your configured DNS Provider must have write access to this target domain. For wildcard certificates, ensure the CNAME delegation covers the _acme-challenge label. This enables least-privilege setups or can be used as a workaround when the primary DNS provider lacks an API. Leave empty if your DNS Provider has a dedicated field for this.]]></help>
<advanced>true</advanced>
<grid_view>
<visible>false</visible>
</grid_view>
</field>
<field>
<id>reverse.DynDns</id>
<label>Dynamic DNS</label>
@@ -212,6 +212,10 @@
</basicauth>
<description type="DescriptionField"/>
<DnsChallenge type="BooleanField"/>
<DnsChallengeOverrideDomain type="HostnameField">
<IpAllowed>N</IpAllowed>
<ValidationMessage>Please enter a valid domain name.</ValidationMessage>
</DnsChallengeOverrideDomain>
<CustomCertificate type="CertificateField">
<BlankDesc>Auto HTTPS</BlankDesc>
</CustomCertificate>
@@ -302,6 +302,7 @@ http://{{ domain }} {
{% macro tls_configuration(
customCert="",
dnsChallenge="0",
dnsChallengeOverrideDomain="",
clientAuthTrustPool="",
clientAuthMode="",
dnsProvider="",
@@ -316,6 +317,9 @@ http://{{ domain }} {
{% if not customCert and (dnsChallenge == "1" and dnsProvider) %}
issuer acme {
dns {{ dnsProvider }} {{ dnsApiKey }}
{% if dnsChallengeOverrideDomain %}
dns_challenge_override_domain {{ dnsChallengeOverrideDomain }}
{% endif %}
{% if tlsDnsPropagationResolvers %}
resolvers {{ tlsDnsPropagationResolvers }}
@@ -622,6 +626,7 @@ http://{{ domain }} {
{{ tls_configuration(
customCert=reverse.CustomCertificate|default(""),
dnsChallenge=reverse.DnsChallenge|default("0"),
dnsChallengeOverrideDomain=reverse.DnsChallengeOverrideDomain|default(""),
clientAuthTrustPool=reverse.ClientAuthTrustPool|default(""),
clientAuthMode=reverse.ClientAuthMode|default(""),
dnsProvider=generalSettings.TlsDnsProvider,