Make Caddy handle On demand TLS "ask" URL

We’ve recently discovered Caddy while searching for a solution to handle custom domain feature editable by our clients and it seems to be a perfect solution for what we need, especially features such as automatically issuing certificates as well as config updates via API.

Now we’re finalizing the Caddy setup and we wish to implement On demand TLS to make sure our clients correctly pointed their domain names before we start issuing certificates. Since the domain name clients need to point to (CNAME record) is static, we’d like to contain the logic within Caddy server itself.

This means the ask URL should ideally point back to Caddy server. The problem is how to actually proceed from there as there are a couple of possible solutions:

  • Easiest solution would be for the ask URL to point to a public serverless function (Firebase Functions, AWS Lambda etc.) which would do the DNS check
    • Unfortunately doing so would stretch our “custom domain” feature across different tech stacks
  • Spin another server (Node.js, PHP or something similar) on the same instance where Caddy is installed and then proxy “ask” URL via Caddy to the other server which would do the DNS check
    • Problem with this solution is that we should maintain both Caddy and the other server
  • Check the DNS record in a shell script by using nslookup, dig or something similar
    • This solution seems fairly simple with less requirements for maintenance but we’re not sure how to actually execute shell script via HTTP and return 200 or another status code depending on whether DNS check passed or not (we did try CGI module but to no avail)

Has anyone done something similar?

Well, really what ask is meant for is to prevent abuse.

So if you just do a DNS check, it’s tautological. If Caddy got a request for that domain, it’s because DNS was configured for it to reach.

You should probably have a list stored in your database with the domain that the client says they configured, and have whatever responds to ask report successful whether it’s in your database.

As an example of abuse: a bad actor could easily set up a wildcard domain like * and then point that to your server with a CNAME then just make requests to, then and so on, forever, causing you to hit ACME rate limits or even DDOSing you, or filling up your storage with garbage certificates and keys.

1 Like

We do this too, using what you describe as option 2. I think option 1 would work just as well. In our case it’s a simple server doing a single SELECT EXISTS () WHERE domain = lookup on a database, not much to maintain

This topic was automatically closed after 30 days. New replies are no longer allowed.