How to use DNS provider modules in Caddy 2

Caddy 2 uses a new and improved DNS provider interface for solving the ACME DNS challenge.

All you have to do is plug the service provider(s) you need into your build, then add the DNS challenge to your configuration!

Getting a DNS provider plugin

How you choose to get a custom Caddy build is up to you; we’ll describe two common methods here.

Method 1:

  1. Go to the Caddy download page.
  2. Find your DNS provider in the list of modules (dns.providers.*) and select it.
  3. Download your custom Caddy build.

Method 2:

  1. Find your DNS provider in the caddy-dns repositories.
  2. Build caddy with your DNS provider plugged in. This is a single xcaddy command:
    xcaddy build --with

If you do not find your DNS provider:

If you do not find a module for your DNS provider, that means nobody has implemented it yet. You have two options: either…

  1. implement your DNS provider (recommended), or
  2. use lego-deprecated which supports all of lego’s 75+ DNS providers, but without certain advantages.

Enabling the DNS challenge

Once you have a custom Caddy binary with your DNS provider module plugged in, you simply have to enable the DNS challenge in your config. Do this one of the following ways:


Global option (use DNS challenge for all sites)

For a globally-recognized DNS challenge configuration, use the acme_dns global option at the top of your Caddyfile:

    acme_dns <provider> ...

For example:

    acme_dns cloudflare 1484053787dJQB8vP1q0yc5ZEBnH6JGS4d3mBmvIeMrnnxFi3WtJdF

Per-site configuration

Or, to enable the DNS challenge for a specific site only, use a tls directive in its site block:

tls {
    dns <provider> ...

for example:

tls {
    dns cloudflare 1484053787dJQB8vP1q0yc5ZEBnH6JGS4d3mBmvIeMrnnxFi3WtJdF

(You might also use a {env.*) placeholder if your credentials are in the environment.) Each provider may have a slightly different syntax; check module docs to be sure.


Or, if you use JSON, configure an automation policy with an acme issuer that sets the DNS challenge, for example:

	"module": "acme",
	"challenges": {
        "dns": {
            "provider": {
                "name": "cloudflare",
                "api_token": "YOUR_CLOUDFLARE_API_TOKEN"

A post was split to a new topic: How to get Cloudflare API token?

A post was split to a new topic: Advantages of libdns?

The global option is only in 2.4.0-beta.1, which should be pointed out.
Just spent 2 hours finding out that it wasn’t available on previous versions.

1 Like

That’s not exactly true, it existed for a long time before, but it was broken/non-functional until this commit: caddyfile: Refactor unmarshaling of module tokens · caddyserver/caddy@f021696 · GitHub

A post was split to a new topic: Split up ACME challenges

A post was split to a new topic: DNS challenge troubles

I am using 2.4.0-Beta.1 now. But even before that I was able to do the following

(cloudflare) {
      tls {
        dns cloudflare YOUR_API_KEY
} {
      import cloudflare

It’s easier now that we can define it globally and not have to import it in every site configuration.


the doc link

seems outdate. (empty content)

maybe this link?

Fixed, thanks.

FYI, anyone can edit Wiki posts if you find a problem.

A post was split to a new topic: New DNS provider module