Hello fellow Go programmers!
I have created a new DNS provider module for Caddy.
It’s quite different from the other DNS providers because it does not use any API, instead it simply makes Caddy serve the challenge records itself.
To get this to work, only one additional DNS record (
NS record for
_acme-challenge) is required.
I’ve tested it against Caddy’s own embedded ACME CA and Let’s Encrypt staging (and it works), but it’s not production ready yet.
There are a few reasons for this:
- I’m not actually a Go programmer (this is the first thing I’ve written in it)
- It relies on deprecated & undocumented Caddy behavior (forgive me)
- It’s only been tested manually so far
override_domainisn’t supported, and neither is the
acme_dnsCaddyfile global option
I’d be happy if you guys could take a look at it and give me feedback, especially about whether I’m using Go right.
I’d also like to know whether the
caddy.Replacer stuff in
Provision() makes any sense at all (to be honest, I just copied that from another DNS provider module and don’t really know what it does).
If anyone has a lot of experience with DNS, I’m also curious about the error codes I’ve chosen to return for the various cases (in the
make_handler() function): is it okay to reply
REFUSED to all non-
Realistically, this handler will only be running for a second or so, while the challenge is being completed, but it should still be correct (and in my testing I also saw the LE staging CA query for
Finally, there’s the issue with implementing
acmez.Solver instead of
certmagic.ACMEDNSProvider with the
I chose to do this because I think the
acmez.Solver interface fits a lot better, “semantically”, for what this module provides. In practical terms, it would probably work just as well to launch the server thread and do the
Present() stuff in
AppendRecords() and then do the
DeleteRecords()… but to me that seemed worse than disregarding the deprecation.
I suppose if framed as “this is a server that runs as long as it has records to serve”, it could make sense as a
libdns-style provider, too.
If nothing else works out, this could always be implemented as a
tls.issuance instead of
dns.providers, but that would involve copying almost all of the code from the
Since even the
libdns interfaces are still experimental / WIP I thought it’d be best to just do it like this for now and find out whether this is even useful or practical at all.
Ok, here’s the link (but remember: not production ready):
I’m curious to see what you think!