1. Your main domain is important.example.com with provider A. No DNS API token for security.
2. Your throwaway domain in a dedicated account with DNS API is example.net with provider B and a DNS API token in your ACME client
3. You create _acme-challenge.important.example.com not as TXT via API but permanent as CNAME to _acme-challenge.example.net or _acme-challenge.important.example.com.example.net
4. Your ACME client writes the challenge responses for important.example.com into a TXT at the unimportant _acme-challenge.example.net and has only API access to provider B. If this gets hacked and example.net lost you change the CNAMES and use a new domain whatever.tld as CNAME target.
acme.sh supports this (see https://github.com/acmesh-official/acme.sh/wiki/DNS-alias-mo... this also works for wildcards as described there), most ACME clients do.
I also wrote an acme.sh Ansible role supporting this: https://github.com/foundata/ansible-collection-acmesh/tree/m.... Example values:
[...]
# certificate: "foo.example.com" with an additional "bar.example.com" SAN
- domains:
- name: "foo.example.com"
challenge: # parameters depend on type
type: "dns"
dns_provider: "dns_hetzner"
# CNAME _acme-challenge.foo.example.com => _acme-challenge.foo.example.com.example.net
challenge_alias: "foo.example.com.example.net"
- name: "bar.example.com"
challenge:
type: "dns"
dns_provider: "dns_inwx"
# CNAME _acme-challenge.bar.example.com => _acme-challenge.example.net
challenge_alias: "example.net"
[...]https://community.cloudflare.com/t/restrict-scope-api-tokens...
There's a NS record so *.acme-dns.example.com delegates requests to it, so each of my hosts that need a cert have a public CNAME like _acme-challenge.www.example.com CNAME asdfasf.acme-dns.example.com which points back to the acme-dns server.
When setting up a new hostname/certificate, a REST request is sent to acme-dns to register a new username/password/subdomain which is fed to acme.sh. Then every time acme.sh needs to issue/renew the certificate it sends the TXT info to the internal acme-dns server, which in turn makes it available to the world.
You can cname _acme-challenge.foo.com to foo.bar.com.
Now, if when you do the DNS challenge, you make a TXT at foo.bar.com with the challenge response, through CNAME redirection, the TXT record is picked up as if it were directly at _acme-challenge.foo.com. You can now issue wildcard certs for anything for foo.com.
I have it on my backlog to build an automated solution to this later this year to handle this for hundreds of individual domains and then put the resulting certificates in AWS secrets manager.
I'm going to also see if I can make some sort of ACME proxy, so internal clients authenticate to me, but they cant control dns, so I make the requests on their behalf. We need to get prepared for ACME everywhere. In May 2026, its 200 day certs, it only goes down from there.
An A-record lookup for ns.example.com resolves to the IP of my server.
This server listens on port 53. It is a custom, small Python server using `dnslib`, which also listens on port let's say 8053 for incoming HTTPS connections.
In certbot I have a custom handler, which, when it is passed the challenge for the domain verification, sends the challenge information via HTTPS to ns.example.com:8053/certbot/cache. The small DNS-server then stores it and waits for a DNS query on port 53 for that challenge to come in, and if it does, it serves it that challenge's TXT record.
elif qtype == 'TXT':
if qname.lower().startswith('_acme-challenge.'):
domain = qname[len('_acme-challenge.'):].strip('.').lower()
if domain in storage['domains']:
for verification_code in storage['domains'][domain.lower()]:
a.add_answer(*dnslib.RR.fromZone(qname + " 30 IN TXT " + verification_code))
The certbot hook looks like this #!/usr/bin/env python3
import ...
r = requests.get('https://ns.example.com:8053/certbot/cache?domain='+urllib.parse.quote(os.environ['CERTBOT_DOMAIN'])+'&validation-code='+urllib.parse.quote(os.environ['CERTBOT_VALIDATION']))
That one nameserver-instance and hook can be used for any domain and certificate, so it is not just limited to the example.com-domain, but can also deal with challenges for let's say a *.testing.other-example.com wildcard certificate.And since it already is a nameserver, it might as well serve the A records for dev1.testing.other-example.com, if you've set the NS record for testing.other-example.com to ns.example.com.
I use this for my Jellyfin server at home so that anyone can just type in blah.foo regardless of if their device supports anything like mDNS, as half the devices claim to support it but do not correctly.
If you have any idea how this tool would work on a docker swarm cluster, I'm all ears.
https://docs.certifytheweb.com/docs/dns/providers/certifydns...
Can even be controlled quite granularly with a Lua-based updatepolicy, if you want e.g. restricting to only the ACME TXT records. [2]
[1] https://doc.powerdns.com/authoritative/dnsupdate.html
[2] https://github.com/PowerDNS/pdns/wiki/Lua-Examples-(Authorit...
We don't need 100s of custom APIs.
AWS IAM can be a huge pain but it can also solve a lot of problems.
https://docs.aws.amazon.com/IAM/latest/UserGuide/reference_p...
https://repost.aws/questions/QU-HJgT3V0TzSlizZ7rVT4mQ/how-do...
https://docs.aws.amazon.com/Route53/latest/DeveloperGuide/sp...
(angie is the nginx fork lead by original nginx developers that left f5)
https://github.com/nginx/nginx/blob/master/LICENSE looks like a nice normal permissive license. I don't care that there's a premium version if all the features I want are in the OSS version.
He’s curious where it’s being used outside of home labs and in small shops. Matt, it’s fantastic software and will only get better as go improves.
I used it in a proxy setup for ingress to kubernetes that’s overlayed across multiple clouds - for the government (prior admin, this admin killed it). I can’t tell you more information than that. Other than it goes WWW -> ALB -> Caddy Cluster * Other Cloud -> K8s Router -> K8s pod -> Fiber Golang service. :chefs kiss:
When a pod is registered to the K8s router, we fire off a request to the caddy cluster to register the route. Bam, we got traffic, we got TLS, we got magic. No downtime.
Complex root domain routing and complex dynamic rewrite logic remains behind Apache/NginX/HaProxy, a lot of apps are then served in a container architecture with Caddy for easy cert renewal without relying on hacky certbot architectures. So we don't really serve that much traffic with just one instance. Also, a lot of our traffic is bots. More than one would think.
The basic configuration being tiny makes it the perfect fit for people with varying capabilities and know how when it comes to devops. As a devops engineer, I enjoy the easy integration with tailscale.
Not sure if you‘ll read this 7 days after the fact, but an easier/caddy native way to deal with bots, in the sense of caddy-defender or Anubis would be a godsend.
Definitely something that's important. An Anubis caddy plugin is in the works too! See https://github.com/TecharoHQ/anubis/issues/16
However anything in caddy would likely still be a plugin and non native
The best thing about caddy is the fact you can reload config, add sites, routes, without ever having to shutdown. Writing a service to keep your orchestration platform and your ingress in sync is meh. K8s has the events, DNS service has the src mesh records, you just need a way to tell caddy to send it to your backend.
The feature should be done soon but they need to ensure it works across K8s flavors.
I don’t believe DNS-over-HTTPS is relevant in this context. AFAIK, it’s used by clients who want to query a DNS server, and not for an operator who wants to create a DNS record. (Please correct me if I’m wrong.)
- wildcard certs. DNS-01 is a strict requirement here. - certs for a service whose TLS is terminated by multiple servers (e.g. load balancers). DNS-01 is a practical requirement here because only one of the terminating servers would be able to respond during an HTTP or ALPN challenge.
Reverse-proxying or otherwise forwarding requests for .well-known/acme-challenge/ to a single server should be just as easy to set up as DNS-01.
In other words, no, it's not just as easy as setting up DNS-01. Different operational characteristics, and a need for bespoke glue code.
Wouldn't you have to do that anyway? Or is the idea that each server requests and renews a separate cert for itself? That sounds as if you'd have to watch out for multiple servers stepping on each other's toes during the DNS-01 challenge, if there is ever a situation where two or more servers want to renew their cert at the same time.
https://datatracker.ietf.org/doc/draft-ietf-acme-dns-account...
2. Query for TXT records for the validation domain name
3. Verify that the contents of one of the TXT records match the
digest value
And then the certbot docs[2] show how it's a well-behaved client that wouldn't clobber TXT records from concurrent instances:> You can have multiple TXT records in place for the same name. For instance, this might happen if you are validating a challenge for a wildcard and a non-wildcard certificate at the same time. However, you should make sure to clean up old TXT records, because if the response size gets too big Let’s Encrypt will start rejecting it. > ... > It works well even if you have multiple web servers.
That bit about "multiple webservers" is a little ambiguous, but I think the preceding line indicates clearly enough how everything is supposed to work.
[0] https://datatracker.ietf.org/doc/html/rfc8555#section-8.4
[1] https://letsencrypt.org/docs/challenge-types/#dns-01-challen...
Let's ignore that DoH is a client oriented protocol and there's no same way to only run a DoH server without an underlying DNS server. How do you plan to get the first certificate so the query to the DoH server doesn't get rejected for invalid certificate?
It would also be unreasonable to tell everyone to move their domains to a handful of giants like AWS and Cloudflare who already control so much of the internet, just so they could get certificates with DNS-01. I like my DNS a bit more decentralized than that.
I wonder what a good solution to this would be? In theory, Nginx could call another application that handles the communication with the DNS provider, so that the user can tailor it to their needs. (The user could write it in Python or Go or whatever.) Not sure how robust that would be though.
Lego supports it.
You can get wildcards with DNS. If you want *.foo.com, you just need to be able to set _acme-challenge.foo.com and you can get the wildcard.
One reason I can think of for HTTP-01 / TLS-ALPN-01 is on-demand issuance, issuing the certificate when you get the request. Which might seem insane (and kinda is), but can be useful for e.g crazy web-migration projects. If you have an enormous, deeply levelled, domain sprawl that are almost never used but you need it up for some reason it can be quite handy.
(Another reason, soon, is that HTTP-01 will be able to issue certs for IP addresses: https://letsencrypt.org/2025/07/01/issuing-our-first-ip-addr...)
Nevermind, I agree!
DNS and wildcards aren't the only options. I've done annoying hacks to give internal services an HTTPS cert without using either.
But they're the only sane options.
It'd be nice if LE could issue intermediary certificates constrained to a specific domain ( https://datatracker.ietf.org/doc/html/rfc5280#section-4.2.1.... ).
NB that rate limits apply https://letsencrypt.org/docs/rate-limits/
Plus, it takes setting up an API key and most of the time you don't need a wildcard anyway.
Wildcards are the only temptation.
That's so much more work than either of the options in my first comment. Aliasing a directory takes about one minute.
How so? It's just serving static files.
The issue is that supporting dns-01 is just supporting dns-01 it's providing a common interface to interact with different providers that implement dns-01.
I think this is kinda the OPs point, nginx an http server, why should it be messing with dns? There are plenty of other acme clients to do this with ease
It may still be required by some users, but I don't think that it makes sense for nginx
Well, I am supporting it, but I pointed why it's not as straightforward as supporting http-01.
> I don't think that it makes sense for nginx
It makes sense for nginx because ultimately I don't make certificates just for the fun of it, I do it to give it to some HTTP server. So it makes sense.
However, this isn't a future that will be not used by paid users, and F5 seems to be opposing making OSS version users lives better.
Whoever first recommended using that mode in anything other than some sort of emergency situation needs to be given a firm kick in the butt.
Certbot also has a mode that mangles your apache or nginx config files in an attempt to wire up certificates to your virtual hosts. Whoever wrote the nginx integration also needs a butt kick, it's terrible. I've helped a number of people fix their broken servers after certbot mangled their config files. Just because you're on a crusade to encrypt the web doesn't give you a right to mess with other programs' config files, that's not how Unix works!
It is not as if they couldn't already choose (to buy) such short lifetimes already.
Authoritarianism at its finest.
It is a terrible piece of software. I use dehydrated which I'd much friendlier to automation.
When I need to use the HTTP challenge, I always configure the web server in advance to serve /.well-known/ from a certain directory and point certbot at it with `certbot certonly --webroot-path`. No need to take down the normal web server. Graceful reload. Zero downtime. Works with any web server.
Wrote an article how to set it up https://blog.haschek.at/2023/letsencrypt-wildcard-cert.html
The solution has been evolving along these years and currently the las IETF draft is https://datatracker.ietf.org/doc/draft-ietf-acme-dns-account...
The new proposal brings the dns-account-01 challenge, incorporating the ACME account URL into the DNS validation record name.
DNS-01 is probably the most impactful for users of nginx that isn't public facing (i.e., via Nginx Proxy Manager). I really want to see DNS-01 land! I've always felt that it's also one of the cleanest because it's just updating some records and doesn't need to be directly tethered to what you're hosting.