• Home
  • History
  • Annotate
Name Date Size #Lines LOC

..03-May-2022-

.github/H14-Apr-2020-

.gitignoreH A D14-Apr-202012

README.mdH A D14-Apr-202028.4 KiB

acmeclient.goH A D14-Apr-202012.7 KiB

acmemanager.goH A D14-Apr-202011.3 KiB

acmemanager_test.goH A D14-Apr-202072

async.goH A D14-Apr-20204.2 KiB

azure-pipelines.ymlH A D14-Apr-20202.6 KiB

cache.goH A D14-Apr-20209.4 KiB

cache_test.goH A D14-Apr-20201.4 KiB

certificates.goH A D14-Apr-202012.7 KiB

certificates_test.goH A D14-Apr-20207 KiB

certmagic.goH A D14-Apr-202015.6 KiB

certmagic_test.goH A D14-Apr-2020617

config.goH A D14-Apr-202024.2 KiB

config_test.goH A D14-Apr-20202.2 KiB

crypto.goH A D14-Apr-20208.1 KiB

crypto_test.goH A D14-Apr-20202.4 KiB

doc_test.goH A D14-Apr-20201.1 KiB

filestorage.goH A D14-Apr-20209.4 KiB

go.modH A D14-Apr-2020188

go.sumH A D14-Apr-202037.1 KiB

handshake.goH A D14-Apr-202018.3 KiB

handshake_test.goH A D14-Apr-20204.2 KiB

httphandler.goH A D14-Apr-20204 KiB

httphandler_test.goH A D14-Apr-20201.7 KiB

maintain.goH A D14-Apr-202016.2 KiB

ocsp.goH A D14-Apr-20207.6 KiB

ratelimiter.goH A D14-Apr-20205.8 KiB

solvers.goH A D14-Apr-202013.3 KiB

storage.goH A D14-Apr-20208.6 KiB

storage_test.goH A D14-Apr-20202.8 KiB

user.goH A D14-Apr-202010.5 KiB

user_test.goH A D14-Apr-20207.3 KiB

README.md

1<p align="center">
2	<a href="https://pkg.go.dev/github.com/caddyserver/certmagic?tab=doc"><img src="https://user-images.githubusercontent.com/1128849/49704830-49d37200-fbd5-11e8-8385-767e0cd033c3.png" alt="CertMagic" width="550"></a>
3</p>
4<h3 align="center">Easy and Powerful TLS Automation</h3>
5<p align="center">The same library used by the <a href="https://caddyserver.com">Caddy Web Server</a></p>
6<p align="center">
7	<a href="https://pkg.go.dev/github.com/caddyserver/certmagic?tab=doc"><img src="https://img.shields.io/badge/godoc-reference-blue.svg"></a>
8	<a href="https://dev.azure.com/mholt-dev/CertMagic/_build"><img src="https://img.shields.io/azure-devops/build/mholt-dev/3511431f-630c-43ac-833f-be949b4f4ee7/3.svg?label=cross-platform%20tests"></a>
9	<a href="https://sourcegraph.com/github.com/caddyserver/certmagic?badge"><img src="https://sourcegraph.com/github.com/caddyserver/certmagic/-/badge.svg"></a>
10</p>
11
12
13Caddy's automagic TLS features&mdash;now for your own Go programs&mdash;in one powerful and easy-to-use library!
14
15CertMagic is the most mature, robust, and capable ACME client integration for Go... and perhaps ever.
16
17With CertMagic, you can add one line to your Go application to serve securely over TLS, without ever having to touch certificates.
18
19Instead of:
20
21```go
22// plaintext HTTP, gross ��
23http.ListenAndServe(":80", mux)
24```
25
26Use CertMagic:
27
28```go
29// encrypted HTTPS with HTTP->HTTPS redirects - yay! ����
30certmagic.HTTPS([]string{"example.com"}, mux)
31```
32
33That line of code will serve your HTTP router `mux` over HTTPS, complete with HTTP->HTTPS redirects. It obtains and renews the TLS certificates. It staples OCSP responses for greater privacy and security. As long as your domain name points to your server, CertMagic will keep its connections secure.
34
35Compared to other ACME client libraries for Go, only CertMagic supports the full suite of ACME features, and no other library matches CertMagic's maturity and reliability.
36
37
38
39
40CertMagic - Automatic HTTPS using Let's Encrypt
41===============================================
42
43**Sponsored by Relica - Cross-platform local and cloud file backup:**
44
45<a href="https://relicabackup.com"><img src="https://caddyserver.com/resources/images/sponsors/relica.png" width="220" alt="Relica - Cross-platform file backup to the cloud, local disks, or other computers"></a>
46
47
48## Menu
49
50- [Features](#features)
51- [Requirements](#requirements)
52- [Installation](#installation)
53- [Usage](#usage)
54	- [Package Overview](#package-overview)
55		- [Certificate authority](#certificate-authority)
56		- [The `Config` type](#the-config-type)
57		- [Defaults](#defaults)
58		- [Providing an email address](#providing-an-email-address)
59		- [Rate limiting](#rate-limiting)
60	- [Development and testing](#development-and-testing)
61	- [Examples](#examples)
62		- [Serving HTTP handlers with HTTPS](#serving-http-handlers-with-https)
63		- [Starting a TLS listener](#starting-a-tls-listener)
64		- [Getting a tls.Config](#getting-a-tlsconfig)
65		- [Advanced use](#advanced-use)
66	- [Wildcard Certificates](#wildcard-certificates)
67	- [Behind a load balancer (or in a cluster)](#behind-a-load-balancer-or-in-a-cluster)
68	- [The ACME Challenges](#the-acme-challenges)
69		- [HTTP Challenge](#http-challenge)
70		- [TLS-ALPN Challenge](#tls-alpn-challenge)
71		- [DNS Challenge](#dns-challenge)
72	- [On-Demand TLS](#on-demand-tls)
73	- [Storage](#storage)
74	- [Cache](#cache)
75- [Contributing](#contributing)
76- [Project History](#project-history)
77- [Credits and License](#credits-and-license)
78
79
80## Features
81
82- Fully automated certificate management including issuance and renewal
83- One-liner, fully managed HTTPS servers
84- Full control over almost every aspect of the system
85- HTTP->HTTPS redirects
86- Solves all 3 ACME challenges: HTTP, TLS-ALPN, and DNS
87- Most robust error handling of _any_ ACME client
88	- Challenges are randomized to avoid accidental dependence
89	- Challenges are rotated to overcome certain network blockages
90	- Robust retries for up to 30 days
91	- Exponential backoff with carefully-tuned intervals
92	- Retries with optional test/staging CA endpoint instead of production, to avoid rate limits
93- Over 50 DNS providers work out-of-the-box (powered by [lego](https://github.com/go-acme/lego)!)
94- Written in Go, a language with memory-safety guarantees
95- Pluggable storage implementations (default: file system)
96- Wildcard certificates
97- Automatic OCSP stapling ([done right](https://gist.github.com/sleevi/5efe9ef98961ecfb4da8#gistcomment-2336055)) [keeps your sites online!](https://twitter.com/caddyserver/status/1234874273724084226)
98	- Will [automatically attempt](https://twitter.com/mholt6/status/1235577699541762048) to replace [revoked certificates](https://community.letsencrypt.org/t/2020-02-29-caa-rechecking-bug/114591/3?u=mholt)!
99	- Staples stored to disk in case of responder outages
100- Distributed solving of all challenges (works behind load balancers)
101	- Highly efficient, coordinated management in a fleet
102	- Active locking
103	- Smart queueing
104- Supports "on-demand" issuance of certificates (during TLS handshakes!)
105	- Caddy / CertMagic pioneered this technology
106	- Custom decision functions to regulate and throttle on-demand behavior
107- Optional event hooks for observation
108- Works with any certificate authority (CA) compliant with the ACME specification
109- Certificate revocation (please, only if private key is compromised)
110- Must-Staple (optional; not default)
111- Cross-platform support! Mac, Windows, Linux, BSD, Android...
112- Scales to hundreds of thousands of names/certificates per instance
113- Use in conjunction with your own certificates
114
115
116## Requirements
117
1181. Public DNS name(s) you control
1192. Server reachable from public Internet
120	- Or use the DNS challenge to waive this requirement
1213. Control over port 80 (HTTP) and/or 443 (HTTPS)
122	- Or they can be forwarded to other ports you control
123	- Or use the DNS challenge to waive this requirement
124	- (This is a requirement of the ACME protocol, not a library limitation)
1254. Persistent storage
126	- Typically the local file system (default)
127	- Other integrations available/possible
128
129**_Before using this library, your domain names MUST be pointed (A/AAAA records) at your server (unless you use the DNS challenge)!_**
130
131
132## Installation
133
134```bash
135$ go get github.com/caddyserver/certmagic
136```
137
138
139## Usage
140
141### Package Overview
142
143#### Certificate authority
144
145This library uses Let's Encrypt by default, but you can use any certificate authority that conforms to the ACME specification. Known/common CAs are provided as consts in the package, for example `LetsEncryptStagingCA` and `LetsEncryptProductionCA`.
146
147#### The `Config` type
148
149The `certmagic.Config` struct is how you can wield the power of this fully armed and operational battle station. However, an empty/uninitialized `Config` is _not_ a valid one! In time, you will learn to use the force of `certmagic.NewDefault()` as I have.
150
151#### Defaults
152
153The default `Config` value is called `certmagic.Default`. Change its fields to suit your needs, then call `certmagic.NewDefault()` when you need a valid `Config` value. In other words, `certmagic.Default` is a template and is not valid for use directly.
154
155You can set the default values easily, for example: `certmagic.Default.Issuer = ...`.
156
157Similarly, to configure ACME-specific defaults, use `certmagic.DefaultACME`.
158
159The high-level functions in this package (`HTTPS()`, `Listen()`, `ManageSync()`, and `ManageAsync()`) use the default config exclusively. This is how most of you will interact with the package. This is suitable when all your certificates are managed the same way. However, if you need to manage certificates differently depending on their name, you will need to make your own cache and configs (keep reading).
160
161
162#### Providing an email address
163
164Although not strictly required, this is highly recommended best practice. It allows you to receive expiration emails if your certificates are expiring for some reason, and also allows the CA's engineers to potentially get in touch with you if something is wrong. I recommend setting `certmagic.DefaultACME.Email` or always setting the `Email` field of a new `Config` struct.
165
166
167#### Rate limiting
168
169To avoid firehosing the CA's servers, CertMagic has built-in rate limiting. Currently, its default limit is up to 10 transactions (obtain or renew) every 1 minute (sliding window). This can be changed by setting the `RateLimitEvents` and `RateLimitEventsWindow` variables, if desired.
170
171The CA may still enforce their own rate limits, and there's nothing (well, nothing ethical) CertMagic can do to bypass them for you.
172
173Additionally, CertMagic will retry failed validations with exponential backoff for up to 30 days, with a reasonable maximum interval between attempts (an "attempt" means trying each enabled challenge type once).
174
175
176### Development and Testing
177
178Note that Let's Encrypt imposes [strict rate limits](https://letsencrypt.org/docs/rate-limits/) at its production endpoint, so using it while developing your application may lock you out for a few days if you aren't careful!
179
180While developing your application and testing it, use [their staging endpoint](https://letsencrypt.org/docs/staging-environment/) which has much higher rate limits. Even then, don't hammer it: but it's much safer for when you're testing. When deploying, though, use their production CA because their staging CA doesn't issue trusted certificates.
181
182To use staging, set `certmagic.DefaultACME.CA = certmagic.LetsEncryptStagingCA` or set `CA` of every `ACMEManager` struct.
183
184
185
186### Examples
187
188There are many ways to use this library. We'll start with the highest-level (simplest) and work down (more control).
189
190All these high-level examples use `certmagic.Default` and `certmagic.DefaultACME` for the config and the default cache and storage for serving up certificates.
191
192First, we'll follow best practices and do the following:
193
194```go
195// read and agree to your CA's legal documents
196certmagic.DefaultACME.Agreed = true
197
198// provide an email address
199certmagic.DefaultACME.Email = "you@yours.com"
200
201// use the staging endpoint while we're developing
202certmagic.DefaultACME.CA = certmagic.LetsEncryptStagingCA
203```
204
205For fully-functional program examples, check out [this Twitter thread](https://twitter.com/mholt6/status/1073103805112147968) (or read it [unrolled into a single post](https://threadreaderapp.com/thread/1073103805112147968.html)). (Note that the package API has changed slightly since these posts.)
206
207
208#### Serving HTTP handlers with HTTPS
209
210```go
211err := certmagic.HTTPS([]string{"example.com", "www.example.com"}, mux)
212if err != nil {
213	return err
214}
215```
216
217This starts HTTP and HTTPS listeners and redirects HTTP to HTTPS!
218
219#### Starting a TLS listener
220
221```go
222ln, err := certmagic.Listen([]string{"example.com"})
223if err != nil {
224	return err
225}
226```
227
228
229#### Getting a tls.Config
230
231```go
232tlsConfig, err := certmagic.TLS([]string{"example.com"})
233if err != nil {
234	return err
235}
236```
237
238
239#### Advanced use
240
241For more control (particularly, if you need a different way of managing each certificate), you'll make and use a `Cache` and a `Config` like so:
242
243```go
244cache := certmagic.NewCache(certmagic.CacheOptions{
245	GetConfigForCert: func(cert certmagic.Certificate) (*certmagic.Config, error) {
246		// do whatever you need to do to get the right
247		// configuration for this certificate; keep in
248		// mind that this config value is used as a
249		// template, and will be completed with any
250		// defaults that are set in the Default config
251		return certmagic.Config{
252			// ...
253		}), nil
254	},
255	...
256})
257
258magic := certmagic.New(cache, certmagic.Config{
259	// any customizations you need go here
260})
261
262myACME := certmagic.NewACMEManager(magic, ACMEManager{
263	CA:     certmagic.LetsEncryptStagingCA,
264	Email:  "you@yours.com",
265	Agreed: true,
266	// plus any other customizations you need
267})
268
269magic.Issuer = myACME
270
271// this obtains certificates or renews them if necessary
272err := magic.ManageSync([]string{"example.com", "sub.example.com"})
273if err != nil {
274	return err
275}
276
277// to use its certificates and solve the TLS-ALPN challenge,
278// you can get a TLS config to use in a TLS listener!
279tlsConfig := magic.TLSConfig()
280
281//// OR ////
282
283// if you already have a TLS config you don't want to replace,
284// we can simply set its GetCertificate field and append the
285// TLS-ALPN challenge protocol to the NextProtos
286myTLSConfig.GetCertificate = magic.GetCertificate
287myTLSConfig.NextProtos = append(myTLSConfig.NextProtos, tlsalpn01.ACMETLS1Protocol}
288
289// the HTTP challenge has to be handled by your HTTP server;
290// if you don't have one, you should have disabled it earlier
291// when you made the certmagic.Config
292httpMux = myACME.HTTPChallengeHandler(httpMux)
293```
294
295Great! This example grants you much more flexibility for advanced programs. However, _the vast majority of you will only use the high-level functions described earlier_, especially since you can still customize them by setting the package-level `Default` config.
296
297
298### Wildcard certificates
299
300At time of writing (December 2018), Let's Encrypt only issues wildcard certificates with the DNS challenge. You can easily enable the DNS challenge with CertMagic for numerous providers (see the relevant section in the docs).
301
302
303### Behind a load balancer (or in a cluster)
304
305CertMagic runs effectively behind load balancers and/or in cluster/fleet environments. In other words, you can have 10 or 1,000 servers all serving the same domain names, all sharing certificates and OCSP staples.
306
307To do so, simply ensure that each instance is using the same Storage. That is the sole criteria for determining whether an instance is part of a cluster.
308
309The default Storage is implemented using the file system, so mounting the same shared folder is sufficient (see [Storage](#storage) for more on that)! If you need an alternate Storage implementation, feel free to use one, provided that all the instances use the _same_ one. :)
310
311See [Storage](#storage) and the associated [pkg.go.dev](https://pkg.go.dev/github.com/caddyserver/certmagic?tab=doc#Storage) for more information!
312
313
314## The ACME Challenges
315
316This section describes how to solve the ACME challenges. Challenges are how you demonstrate to the certificate authority some control over your domain name, thus authorizing them to grant you a certificate for that name. [The great innovation of ACME](https://www.dotconferences.com/2016/10/matthew-holt-go-with-acme) is that verification by CAs can now be automated, rather than having to click links in emails (who ever thought that was a good idea??).
317
318If you're using the high-level convenience functions like `HTTPS()`, `Listen()`, or `TLS()`, the HTTP and/or TLS-ALPN challenges are solved for you because they also start listeners. However, if you're making a `Config` and you start your own server manually, you'll need to be sure the ACME challenges can be solved so certificates can be renewed.
319
320The HTTP and TLS-ALPN challenges are the defaults because they don't require configuration from you, but they require that your server is accessible from external IPs on low ports. If that is not possible in your situation, you can enable the DNS challenge, which will disable the HTTP and TLS-ALPN challenges and use the DNS challenge exclusively.
321
322Technically, only one challenge needs to be enabled for things to work, but using multiple is good for reliability in case a challenge is discontinued by the CA. This happened to the TLS-SNI challenge in early 2018&mdash;many popular ACME clients such as Traefik and Autocert broke, resulting in downtime for some sites, until new releases were made and patches deployed, because they used only one challenge; Caddy, however&mdash;this library's forerunner&mdash;was unaffected because it also used the HTTP challenge. If multiple challenges are enabled, they are chosen randomly to help prevent false reliance on a single challenge type. And if one fails, any remaining enabled challenges are tried before giving up.
323
324
325### HTTP Challenge
326
327Per the ACME spec, the HTTP challenge requires port 80, or at least packet forwarding from port 80. It works by serving a specific HTTP response that only the genuine server would have to a normal HTTP request at a special endpoint.
328
329If you are running an HTTP server, solving this challenge is very easy: just wrap your handler in `HTTPChallengeHandler` _or_ call `SolveHTTPChallenge()` inside your own `ServeHTTP()` method.
330
331For example, if you're using the standard library:
332
333```go
334mux := http.NewServeMux()
335mux.HandleFunc("/", func(w http.ResponseWriter, req *http.Request) {
336	fmt.Fprintf(w, "Lookit my cool website over HTTPS!")
337})
338
339http.ListenAndServe(":80", myACME.HTTPChallengeHandler(mux))
340```
341
342If wrapping your handler is not a good solution, try this inside your `ServeHTTP()` instead:
343
344```go
345magic := certmagic.NewDefault()
346myACME := certmagic.NewACMEManager(magic, certmagic.DefaultACME)
347
348func ServeHTTP(w http.ResponseWriter, req *http.Request) {
349	if myACME.HandleHTTPChallenge(w, r) {
350		return // challenge handled; nothing else to do
351	}
352	...
353}
354```
355
356If you are not running an HTTP server, you should disable the HTTP challenge _or_ run an HTTP server whose sole job it is to solve the HTTP challenge.
357
358
359### TLS-ALPN Challenge
360
361Per the ACME spec, the TLS-ALPN challenge requires port 443, or at least packet forwarding from port 443. It works by providing a special certificate using a standard TLS extension, Application Layer Protocol Negotiation (ALPN), having a special value. This is the most convenient challenge type because it usually requires no extra configuration and uses the standard TLS port which is where the certificates are used, also.
362
363This challenge is easy to solve: just use the provided `tls.Config` when you make your TLS listener:
364
365```go
366// use this to configure a TLS listener
367tlsConfig := magic.TLSConfig()
368```
369
370Or make two simple changes to an existing `tls.Config`:
371
372```go
373myTLSConfig.GetCertificate = magic.GetCertificate
374myTLSConfig.NextProtos = append(myTLSConfig.NextProtos, tlsalpn01.ACMETLS1Protocol}
375```
376
377Then just make sure your TLS listener is listening on port 443:
378
379```go
380ln, err := tls.Listen("tcp", ":443", myTLSConfig)
381```
382
383
384### DNS Challenge
385
386The DNS challenge is perhaps the most useful challenge because it allows you to obtain certificates without your server needing to be publicly accessible on the Internet, and it's the only challenge by which Let's Encrypt will issue wildcard certificates.
387
388This challenge works by setting a special record in the domain's zone. To do this automatically, your DNS provider needs to offer an API by which changes can be made to domain names, and the changes need to take effect immediately for best results. CertMagic supports [all of lego's DNS provider implementations](https://github.com/go-acme/lego/tree/master/providers/dns)! All of them clean up the temporary record after the challenge completes.
389
390To enable it, just set the `DNSProvider` field on a `certmagic.Config` struct, or set the default `certmagic.DNSProvider` variable. For example, if my domains' DNS was served by DNSimple and I set my DNSimple API credentials in environment variables:
391
392```go
393import "github.com/go-acme/lego/v3/providers/dns/dnsimple"
394
395provider, err := dnsimple.NewDNSProvider()
396if err != nil {
397	return err
398}
399
400certmagic.DefaultACME.DNSProvider = provider
401```
402
403Now the DNS challenge will be used by default, and I can obtain certificates for wildcard domains. See the [pkg.go.dev documentation for the provider you're using](https://pkg.go.dev/github.com/go-acme/lego/providers/dns?tab=subdirectories) to learn how to configure it. Most can be configured by env variables or by passing in a config struct. If you pass a config struct instead of using env variables, you will probably need to set some other defaults (that's just how lego works, currently):
404
405```go
406PropagationTimeout: dns01.DefaultPollingInterval,
407PollingInterval:    dns01.DefaultPollingInterval,
408TTL:                dns01.DefaultTTL,
409```
410
411Enabling the DNS challenge disables the other challenges for that `certmagic.Config` instance.
412
413
414## On-Demand TLS
415
416Normally, certificates are obtained and renewed before a listener starts serving, and then those certificates are maintained throughout the lifetime of the program. In other words, the certificate names are static. But sometimes you don't know all the names ahead of time, or you don't want to manage all the certificates up front. This is where On-Demand TLS shines.
417
418Originally invented for use in Caddy (which was the first program to use such technology), On-Demand TLS makes it possible and easy to serve certificates for arbitrary or specific names during the lifetime of the server. When a TLS handshake is received, CertMagic will read the Server Name Indication (SNI) value and either load and present that certificate in the ServerHello, or if one does not exist, it will obtain it from a CA right then-and-there.
419
420Of course, this has some obvious security implications. You don't want to DoS a CA or allow arbitrary clients to fill your storage with spammy TLS handshakes. That's why, when you enable On-Demand issuance, you should set limits or policy to allow getting certificates. CertMagic has an implicit whitelist built-in which is sufficient for nearly everyone, but also has a more advanced way to control on-demand issuance.
421
422The simplest way to enable on-demand issuance is to set the OnDemand field of a Config (or the default package-level value):
423
424```go
425certmagic.Default.OnDemand = new(certmagic.OnDemandConfig)
426```
427
428By setting this to a non-nil value, on-demand TLS is enabled for that config. For convenient security, CertMagic's high-level abstraction functions such as `HTTPS()`, `TLS()`, `ManageSync()`, `ManageAsync()`, and `Listen()` (which all accept a list of domain names) will whitelist those names automatically so only certificates for those names can be obtained when using the Default config. Usually this is sufficient for most users.
429
430However, if you require advanced control over which domains can be issued certificates on-demand (for example, if you do not know which domain names you are managing, or just need to defer their operations until later), you should implement your own DecisionFunc:
431
432```go
433// if the decision function returns an error, a certificate
434// may not be obtained for that name at that time
435certmagic.Default.OnDemand = &certmagic.OnDemandConfig{
436	DecisionFunc: func(name string) error {
437		if name != "example.com" {
438			return fmt.Errorf("not allowed")
439		}
440		return nil
441	},
442}
443```
444
445The [pkg.go.dev](https://pkg.go.dev/github.com/caddyserver/certmagic?tab=doc#OnDemandConfig) describes how to use this in full detail, so please check it out!
446
447
448## Storage
449
450CertMagic relies on storage to store certificates and other TLS assets (OCSP staple cache, coordinating locks, etc). Persistent storage is a requirement when using CertMagic: ephemeral storage will likely lead to rate limiting on the CA-side as CertMagic will always have to get new certificates.
451
452By default, CertMagic stores assets on the local file system in `$HOME/.local/share/certmagic` (and honors `$XDG_DATA_HOME` if set). CertMagic will create the directory if it does not exist. If writes are denied, things will not be happy, so make sure CertMagic can write to it!
453
454The notion of a "cluster" or "fleet" of instances that may be serving the same site and sharing certificates, etc, is tied to storage. Simply, any instances that use the same storage facilities are considered part of the cluster. So if you deploy 100 instances of CertMagic behind a load balancer, they are all part of the same cluster if they share the same storage configuration. Sharing storage could be mounting a shared folder, or implementing some other distributed storage system such as a database server or KV store.
455
456The easiest way to change the storage being used is to set `certmagic.DefaultStorage` to a value that satisfies the [Storage interface](https://pkg.go.dev/github.com/caddyserver/certmagic?tab=doc#Storage). Keep in mind that a valid `Storage` must be able to implement some operations atomically in order to provide locking and synchronization.
457
458If you write a Storage implementation, please add it to the [project wiki](https://github.com/caddyserver/certmagic/wiki/Storage-Implementations) so people can find it!
459
460
461## Cache
462
463All of the certificates in use are de-duplicated and cached in memory for optimal performance at handshake-time. This cache must be backed by persistent storage as described above.
464
465Most applications will not need to interact with certificate caches directly. Usually, the closest you will come is to set the package-wide `certmagic.DefaultStorage` variable (before attempting to create any Configs). However, if your use case requires using different storage facilities for different Configs (that's highly unlikely and NOT recommended! Even Caddy doesn't get that crazy), you will need to call `certmagic.NewCache()` and pass in the storage you want to use, then get new `Config` structs with `certmagic.NewWithCache()` and pass in the cache.
466
467Again, if you're needing to do this, you've probably over-complicated your application design.
468
469
470## FAQ
471
472### Can I use some of my own certificates while using CertMagic?
473
474Yes, just call the relevant method on the `Config` to add your own certificate to the cache:
475
476- [`CacheUnmanagedCertificatePEMBytes()`](https://pkg.go.dev/github.com/caddyserver/certmagic?tab=doc#Config.CacheUnmanagedCertificatePEMBytes)
477- [`CacheUnmanagedCertificatePEMFile()`](https://pkg.go.dev/github.com/caddyserver/certmagic?tab=doc#Config.CacheUnmanagedCertificatePEMFile)
478- [`CacheUnmanagedTLSCertificate()`](https://pkg.go.dev/github.com/caddyserver/certmagic?tab=doc#Config.CacheUnmanagedTLSCertificate)
479
480Keep in mind that unmanaged certificates are (obviously) not renewed for you, so you'll have to replace them when you do. However, OCSP stapling is performed even for unmanaged certificates that qualify.
481
482
483### Does CertMagic obtain SAN certificates?
484
485Technically all certificates these days are SAN certificates because CommonName is deprecated. But if you're asking whether CertMagic issues and manages certificates with multiple SANs, the answer is no. But it does support serving them, if you provide your own.
486
487
488### How can I listen on ports 80 and 443? Do I have to run as root?
489
490On Linux, you can use `setcap` to grant your binary the permission to bind low ports:
491
492```bash
493$ sudo setcap cap_net_bind_service=+ep /path/to/your/binary
494```
495
496and then you will not need to run with root privileges.
497
498
499## Contributing
500
501We welcome your contributions! Please see our **[contributing guidelines](https://github.com/caddyserver/certmagic/blob/master/.github/CONTRIBUTING.md)** for instructions.
502
503
504## Project History
505
506CertMagic is the core of Caddy's advanced TLS automation code, extracted into a library. The underlying ACME client implementation is [lego](https://github.com/go-acme/lego), which was originally developed for use in Caddy even before Let's Encrypt entered public beta in 2015.
507
508In the years since then, Caddy's TLS automation techniques have been widely adopted, tried and tested in production, and served millions of sites and secured trillions of connections.
509
510Now, CertMagic is _the actual library used by Caddy_. It's incredibly powerful and feature-rich, but also easy to use for simple Go programs: one line of code can enable fully-automated HTTPS applications with HTTP->HTTPS redirects.
511
512Caddy is known for its robust HTTPS+ACME features. When ACME certificate authorities have had outages, in some cases Caddy was the only major client that didn't experience any downtime. Caddy can weather OCSP outages lasting days, or CA outages lasting weeks, without taking your sites offline.
513
514Caddy was also the first to sport "on-demand" issuance technology, which obtains certificates during the first TLS handshake for an allowed SNI name.
515
516Consequently, CertMagic brings all these (and more) features and capabilities right into your own Go programs.
517
518You can [watch a 2016 dotGo talk](https://www.dotconferences.com/2016/10/matthew-holt-go-with-acme) by the author of this library about using ACME to automate certificate management in Go programs:
519
520[![Matthew Holt speaking at dotGo 2016 about ACME in Go](https://user-images.githubusercontent.com/1128849/49921557-2d506780-fe6b-11e8-97bf-6053b6b4eb48.png)](https://www.dotconferences.com/2016/10/matthew-holt-go-with-acme)
521
522
523
524## Credits and License
525
526CertMagic is a project by [Matthew Holt](https://twitter.com/mholt6), who is the author; and various contributors, who are credited in the commit history of either CertMagic or Caddy.
527
528CertMagic is licensed under Apache 2.0, an open source license. For convenience, its main points are summarized as follows (but this is no replacement for the actual license text):
529
530- The author owns the copyright to this code
531- Use, distribute, and modify the software freely
532- Private and internal use is allowed
533- License text and copyright notices must stay intact and be included with distributions
534- Any and all changes to the code must be documented
535