Trusted certificates for localhost and internal sites

We’ve reached an agreement with Smallstep to help bring fully-managed PKI to Caddy!

The goal here is to put every site – even local and internal ones – on HTTPS. Using HTTPS on localhost can help streamline the transition from development into production, and using HTTPS on internal infrastructure (mTLS) can provide greater security and privacy, especially on untrusted/cloud networks.

Currently, managing the infrastructure needed for proper HTTPS on local and internal hosts is tedious and error-prone. Integrating Smallstep into Caddy will allow us to serve https://localhost or https://example.local using trusted certificates with much less hassle.

The goal is to make them work just like HTTPS for public sites that use Let’s Encrypt. The main difference is that the CA is private rather than public.

Design work will begin shortly!

Join the discussion on GitHub: Caddy+Smallstep integration (trusted certs for localhost and internal sites) · Issue #3021 · caddyserver/caddy · GitHub


This sounds amazing. It’s actually a real problem as you’ve highlighted, when moving from development into production.

I am curious though, Is the private CA signed by a trusted cert known to all browsers? Just wondering how a private CA will be automatically trusted in browsers?

Thanks Matt!

Managing certificates and trusting certificates are two separate problems, so we’re considering and approaching them totally separately. While you can use a certificate anywhere you want/need, what programs or connections decide to trust it is a different matter.

Trust might be established at the OS level (i.e. added to the system root store), which causes all applications that use the system trust store to automatically trust the certificate. Some programs, like Firefox and Java, bundle their own trust store. Many custom services written in Go can also be choosy about which authorities they trust (by default, Go uses the system trust store, but you can override this in Go code).

So, I think trust is the more complicated side of this integration. It has potentially far-reaching implications, and arguably, it is not the web server’s problem to solve in the first place, so we’ll be conservative about it at first. We’ll have to expose a certain amount of configuration surface area in order to make trust configurable by the user. I don’t know what the defaults will be yet. Probably depends a lot on the scenario.

For a local dev certificate, you just want to trust it and don’t really care too much (as long as you don’t share the private key!) – kind of like mkcert. In a similar fashion to mkcert, Caddy will generate CA root and intermediate certs, and then a site leaf cert, and Caddy can add the CA’s root to the system trust store if you want – as well as Firefox’s and Java’s trust stores. (But production servers probably won’t need the Firefox—and maybe Java—trust.) This requires root privileges.

In the long run, we hope that Caddy will be able to selectively trust its own certificates for internal fleet deployments (i.e. mTLS) according to some sort of trust model established by the user.