A Caddy DNS module for eDNS (edns.de), so Caddy can obtain certificates through the ACME DNS-01 challenge — including wildcard certificates, and for hosts that are not reachable from the internet at all.
The provider itself lives in libdns/ednsde; this repository is only the Caddy module wrapper.
This module is not in the standard Caddy distribution. Build Caddy with xcaddy:
xcaddy build --with github.com/caddy-dns/ednsdeVerify it is present:
./caddy list-modules | grep dns.providers.ednsdeCaddyfile, token as an argument:
tls {
dns ednsde {env.EDNS_TOKEN}
}or as a block:
tls {
dns ednsde {
api_token {env.EDNS_TOKEN}
}
}Giving the token both ways at once is an error — a credential with two sources of truth is one waiting to drift.
JSON:
{
"module": "acme",
"challenges": {
"dns": {
"provider": {
"name": "ednsde",
"api_token": "YOUR_EDNS_ACCESS_TOKEN"
}
}
}
}tls {
dns ednsde {env.EDNS_TOKEN}
propagation_delay 30s
propagation_timeout 10m
}eDNS confirms a challenge record immediately; when its nameservers start answering with it is another matter, and the two servers do not move together. Four records published a minute apart, watched on both authoritative nameservers of a live zone at once:
| Record | ns4 |
ns3 |
|---|---|---|
| 1 | 17 s | 66 s |
| 2 | 17 s | 29 s |
| 3 | 65 s | 26 s |
| 4 | 27 s | 27 s |
Either server can be the slow one, and watching from two machines on different continents made no difference — they agreed on every moment to within three seconds. Removals take about 307 seconds, the 300-second record TTL. Nothing in this module or the provider influences any of it.
propagation_delay 30s covers the fast case without spending it on lookups that
cannot yet succeed. The long timeout is the important part. Ten minutes
rather than Caddy's two-minute default: Caddy is usually satisfied by whichever
server has the value first, but a lagging server that still answers NXDOMAIN
ends that round, so the slow tail reaches you anyway — and a tight timeout does
not make eDNS faster, it turns a slow publish into a failed order.
Two values on one name — what a certificate covering both example.com and
*.example.com needs — publish no slower than one, so a SAN certificate costs
nothing extra here.
If you configure resolvers in the tls block, check your zone's SOA
minimum too. That puts a caching resolver back into the propagation check, and
_acme-challenge.<your-host> does not exist before the first issuance — the
NXDOMAIN is cached for the SOA minimum and the check cannot see past it. Without
resolvers, Caddy queries the zone's authoritative nameservers directly and this
does not arise.
dig +short SOA example.com | awk '{print "negative TTL:", $NF}'At 86400 a first issuance could be stuck for a day, and no ACME client setting would help. Lowering it to 300 in the eDNS zone settings is cheap insurance either way.
A reverse proxy with a wildcard certificate, reachable only over HTTPS:
{
email you@example.com
}
*.example.com {
tls {
dns ednsde {env.EDNS_TOKEN}
propagation_delay 30s
propagation_timeout 10m
}
reverse_proxy 127.0.0.1:8080
}- In the eDNS web interface: SSL-Zertifikate → Automation-API-Verwaltung → API-Zugang anlegen.
- Open the zone and select that token on its DNS-01-Challenge tab.
Step 2 is easy to miss and produces a 401 that reads exactly like an invalid
token — the API does not distinguish the two. One token may be assigned to
several zones.
Unit tests need nothing but Go:
go test ./...The end-to-end test builds Caddy with this module, obtains real certificates from Let's Encrypt staging over DNS-01, and proves the result by proxying a request to a second Caddy instance. It writes into a real zone and needs a real token:
EDNS_TOKEN=... ./e2e/run.shSee e2e/README.md for what it does and what it requires.
MIT