Advantages of libdns?

use lego-deprecated which supports all of lego’s 75+ DNS providers, but without certain advantages.

Can you explain those advantages?

This post explains why the split happened:

Thanks for the quick response. I read that but I still don’t get it. I had my DNS provider provision API tokens for me that intentionally can only set and delete TXT records because I don’t want Caddy to do anything else, and I certainly don’t want to hand Caddy the keys to be able to do anything else.

Is there an advantage (to us, the end-users of Caddy) of libdns over go-acme/lego as far as certificate DNS challenges go? If so, what? Or is Caddy planning on using libdns for something more than certificate DNS challenges and libdns opens up possibilities in other features? Or does libdns just lead to better code within Caddy without exposing any of those advantages to end users?

I can answer this.

Yes, libdns has multiple advantages over lego’s DNS providers:

  • Native context support. This means faster and lighter config reloads without leaking resources. More on this in a closed issue: Use context.Context to enforce cancellation · Issue #970 · go-acme/lego · GitHub
  • Much slimmer code base, meaning less surface area for bugs. Easier to maintain and extend. Smaller, faster builds with less room for things to go wrong.
  • Locally-scoped and centralized configuration. Lego’s DNS providers are configured implicitly through environment variables: this means your web server config depends on hidden variables outside the web server config, which is easy to forget, confusing to troubleshoot, and problematic when getting or giving help. With libdns, the config is explicitly in place within the same config document as the rest of your web server configuration. Also, because they are global variables, you can’t have multiple provider configs for the same server. With libdns, you can configure as many providers as needed and as specifically as needed. More on this in a closed PR: dnsproviders: Implement NewConfigFromEnv() by mholt · Pull Request #1058 · go-acme/lego · GitHub

Now, these are just some of the reasons related to the DNS providers specifically. The switch to libdns is related to a larger switch from lego to acmez:

https://github.com/caddyserver/certmagic/issues/71

After years of experience and several major problems in production (like, 20% of customers’ customers’ websites going offline due to bugs in lego), I can no longer recommend lego for use in large scale deployments at all. I was originally going to refactor lego to fix the bugs, but the refactor was so intensive I basically just rewrote it from scratch, which became acmez; and it’s more reliable, robust, and lightweight in heavy deployments than lego is.

By implementing our own ACME library, we are also able to do more intelligent retries, concurrency, and throttling in large deployments, leading to faster challenges and lower time-to-availability for large numbers of domains. See Throttle individual API requests · Issue #976 · go-acme/lego · GitHub and Better concurrency in challenges · Issue #1062 · go-acme/lego · GitHub for example.

For the same reasons, I recommend acmez for small scale deployments too. We also find that acmez gives customers the flexibility they need to configure the server for their advanced use cases, that lego does not properly allow.

Ultimately, lego’s DNS providers are not implemented with an interface that is compatible with acmez’s requirements for smooth, reliable, customizable operation, and we could not continue using lego. Plus, libdns is a more general API that is not limited to TXT records for ACME challenges.

It is also used for a dynamic DNS plugin, which updates DNS A/AAAA records based on your server’s current IP address, useful if it changes:

Lego’s DNS providers are not capable of this, but libdns is. It’s a set of general purpose DNS manipulation libraries. Honestly it’s kind of a bummer that all of that development time that went into lego’s 75+ providers are only good for the ACME DNS challenge. The general case only takes a fraction more time to implement, but you have to approach it differently, and the lego APIs just aren’t capable of that without rewriting it all.

They’re exposed to the end users in the best way possible: by having fewer problems in production.

To be clear, libdns providers are capable of this too, but it depends on the provider of course, and how it is implemented.

4 Likes

Thanks for the extremely comprehensive answer!

Also, because they are global variables, you can’t have multiple provider configs for the same server. With libdns, you can configure as many providers as needed and as specifically as needed. More on this in a closed PR: dnsproviders: Implement NewConfigFromEnv() by mholt · Pull Request #1058 · go-acme/lego · GitHub

FWIW I’ve actually hit this limitation with Traefik + lego (Provide dnsChallenge credentials per resolver · Issue #5472 · traefik/traefik · GitHub).

2 Likes

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