Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

caddytls: Support multiple issuers #3862

Merged
merged 4 commits into from
Nov 16, 2020
Merged

caddytls: Support multiple issuers #3862

merged 4 commits into from
Nov 16, 2020

Conversation

mholt
Copy link
Member

@mholt mholt commented Nov 12, 2020

The flagship feature of Caddy 2.3: multiple certificate issuers!

What is this?

Currently, Caddy -- and pretty much every other web server or ACME client -- only supports 1 certificate issuer, or source. For example, you can configure Let's Encrypt, ZeroSSL, or Let's Encrypt Staging depending on your needs. But what if the CA is down, or you've hit rate limits, or there's some other problem? You can't get a certificate, unless you manually log in and change your configuration, but this is a hassle and can result in downtime, especially for new sites.

At the end of the day, a trusted certificate is a trusted certificate. As long as it's trusted, the clients (web browsers) don't care where it comes from.

With this change, you can configure multiple certificate issuers, and Caddy will try each one in sequence until it successfully gets a certificate. Now that there are multiple public ACME endpoints, this feature is especially handy. This is true multi-CA redundancy, for the first time.

The multiple issuers are not limited to just ACME. You could, for example, configure yet another issuer, internal, which is the internal CA that allows Caddy to issue certificates itself. They aren't publicly trusted, but if all public CAs are down and you just need encryption, that's a good fallback plan in some cases. In the future there may be more issuer types, and this is compatible with all of them.

As far as I know, no other web server implements functionality like this.

What are the defaults?

Before this change, Caddy defaults only to Let's Encrypt for public-looking domain names.

With this change, Caddy will default to both Let's Encrypt and ZeroSSL. If one fails for some reason, the other will be used implicitly. This gives Caddy sites significantly more reliability than any other HTTPS servers on the Web.

In otherwords, this Caddyfile config is the new default and you do not have to configure this manually:

tls {
	issuer acme
	issuer zerossl
}

Why use ZeroSSL?

We're going to see this question a lot more so I want to start answering it now. First, to clarify: Let's Encrypt is the gold standard CA, especially among ACME CAs, and there's absolutely nothing wrong with it. You may keep using Let's Encrypt if you prefer! Aside from the obvious fact that Caddy has been acquired by the company behind ZeroSSL, there are actual beneficial reasons for Caddy to default to ZeroSSL:

  • Let's Encrypt is a busy non-profit organization. We can help maximize their budget by not using it as the exclusive default for every server.
  • ZeroSSL does not have rate limits and is also publicly trusted. And yes, it is free to use it with ACME.
  • ZeroSSL offers a graphical dashboard where you can log in and see and download your certificates.
  • Having more than just 1 free ACME CA is a very, very good thing for the PKI ecosystem.

There are no plans to remove Let's Encrypt as a default CA. You can also override any of these choices in your own config any time.

What does this break?

Well, there are probably bugs. This change needs to be tested in low-stakes environments, like local dev, or small personal sites, or large staging environments.

Also, the issuer field of automation policies is being deprecated in favor of issuers, which is an array (not yet shown in documentation, because this is not yet released). For now, we print a warning when the deprecated field is used, and we'll append that to the issuers list in the meantime to help you transition. In a future version of Caddy, the issuer field will be removed.

What does the config look like?

Very similar!

In JSON, issuers is simply an array of issuer objects, instead of a single object:

{
	"tls": {
		"automation": {
			"policies": [
				{
					"issuers": [
						...
					]
				}
			]
		}
	}
}

In Caddyfile, you can use the issuer subdirective of the tls directive multiple times instead of just once:

{
	email you@yours.com
}

example.com

tls {
	issuer zerossl
	issuer acme
	issuer internal
}

Using that, if Caddy can't get a certificate using ZeroSSL or Let's Encrypt (the default ACME issuer endpoint), then it will get a locally-trusted cert from its own internal CA.

This is super cool. Please help test it out!!

We need your help!

Please help test it! This was a really difficult change and I put it through the wringer on my end, but I think there's a lot of combinations and I couldn't get them all. Please try with your configs in any environments you can, and expect bugs or other weird behavior in the meantime. Please report bugs with enough detail to reproduce the problem! Simplify your configs as much as possible when reporting.

Since no other software has done this before, I didn't really have anything to go off of in terms of a reference implementation. Even a lot of the logic I had to come up with myself, although I thank people like Ryan Hurst, Ryan Sleevi, Jacob Hoffman-Andrews, and a few others for their advice as I worked through difficult questions. Anyway, because of this, please expect bugs. Start testing now -- we'll have some pre-releases but don't wait for those, please. 😅 Let's get it right ASAP.

What's planned?

Other than squashing bugs and updating the documentation, the goal is to switch to using ZeroSSL as the primary default with Let's Encrypt as secondary. This will help relieve load on the already-very-busy, donation-powered Let's Encrypt servers, while also helping reduce rate limit errors that large-scale deployments experience.

We also are developing a hopeful-standard JSON document that can describe available ACME endpoints, complete with feature descriptions and mappings to CAA records, so that ACME clients can be given a single "directory of directories" to automatically fill in its issuer list using a single URL.

Defaults are Let's Encrypt and ZeroSSL.

There are probably bugs.
@mholt mholt added the help wanted 🆘 Extra attention is needed label Nov 12, 2020
@mholt mholt added this to the v2.3.0 milestone Nov 12, 2020
@mholt mholt requested a review from francislavoie November 12, 2020 00:15
@mholt mholt self-assigned this Nov 12, 2020
@mholt mholt requested a review from mohammed90 November 12, 2020 00:33
@mholt mholt added the under review 🧐 Review is pending before merging label Nov 12, 2020
francislavoie
francislavoie previously approved these changes Nov 12, 2020
Copy link
Member

@francislavoie francislavoie left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah this all makes sense to me! Exciting!

mohammed90
mohammed90 previously approved these changes Nov 14, 2020
Copy link
Member

@mohammed90 mohammed90 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looking all good. Let's see it rolling! 🎉 Keep in mind, currently this is perfectly valid config 😄

"issuers": [
	{
	  "module": "internal"
	},
	{
		"module": "acme",
		"ca": "acme-v02.api.letsencrypt.org/directory"
	},
	{
	  "module": "internal"
	},
	{
	  "module": "internal"
	},
	{
		"module": "acme",
		"ca": "acme-v02.api.letsencrypt.org/directory"
	},
	{
	  "module": "internal"
	},
	{
	  "module": "internal"
	},
	{
	  "module": "internal"
	},
]

@mholt
Copy link
Member Author

mholt commented Nov 14, 2020

Thanks for the reviews!

And yes @mohammed90 that is technically valid and there are a lot of ways to sabotage your web server but I'll just leave it at that. 😉

@mholt mholt removed the under review 🧐 Review is pending before merging label Nov 16, 2020
@mholt mholt dismissed stale reviews from mohammed90 and francislavoie via 9feac63 November 16, 2020 17:58
@mholt
Copy link
Member Author

mholt commented Nov 16, 2020

As soon as the tests complete, I'm going to go ahead and merge this in so that at least the few people who build from source will start using it, and hopefully we can get reports of any bugs in sooner rather than later. We'll do pre-releases too.

@mholt mholt merged commit 13781e6 into master Nov 16, 2020
@mholt mholt deleted the multi-issuer branch November 16, 2020 18:06
@mholt mholt removed the help wanted 🆘 Extra attention is needed label Nov 16, 2020
mholt added a commit that referenced this pull request Feb 8, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants