Let's Encrypt TLS Certifictes - DevelopingSpace/starchart GitHub Wiki
Overview
Starchart uses Let's Encrypt for our TLS Certificates.
This page collects various pieces of information related to Let's Encrypt, how we use it, and links to resources we need.
Resources
- Let's Encrypt docs
- How it Works
- Staging Environment for testing
- DNS Challenge
- Let's Encrypt Integration Guide has suggestions that apply to us
- Let's Encrypt Rate Limits need to be understood and adhered to in production
- lets/encrypt/pebble is a mini version of Let's Encrypt you can run via docker-compose on localhost and CI for testing (e.g., avoid rate limiting)
- Client Implementations
- certbot is the official Let's Encrypt Acme client/library written in Python
- Lego is the an Acme client/library written in Go. PowerDNS pdns lego provider and source code for setting DNS challenge records
- node-acme-client is probably the most up-to-date node.js client (see also greenlock.js, which doesn't seem maintained any longer)
Understanding What Let's Encrypt Does and Creates
Let's Encrypt is a Certificate Authority (CA) that provides free SSL certificates to everyone, helping to keep the open web secure. We interact with Let's Encrypt in an automated way using the ACME protocol, which is implemented by various clients and libraries written in lots of different languages.
Certificates are issued for a given domain (e.g., example.com
) or for a group of subodomains (e.g., www.example.com
, blog.example.com
, mail.example.com
, etc. using the wildcard domain *.example.com
). Let's Encrypt requires domain owners to prove that they control the given domain(s).
The ACME client must use (i.e., an existing) or generate a new public/private key pair in order to communicate with Let's Encrypt. The client requests that Let's Encrypt issue a certificate for the given domain(s), and Let's Encrypt responds with a set of challenges, which the client uses to prove that it controls the domain(s).
There are two types of challenges: HTTP and DNS. Because Starchart is only focused on domain names (i.e., it provides no hosting), we use a DNS Challenge. In this type of challenge, the client must take a token from Let's Encrypt and place it in a DNS TXT record at the (sub)domain, for example: _acme-challenge.domain.com
. This DNS record must be publicly visible to Let's Encrypt: if we have the power to put this record on the domain's DNS, and the value matches what Let's Encrypt expects, we obviously control the domain.
Now that Let's Encrypt knows that we control the domain, and has authorized our key pair, we can request a certificate. We do this by creating a Certificate Signing Request (CSR). Among other things, the CSR includes a digital signature, our public key, and the domain name for which we are requesting a certificate.
Let's Encrypt verifies the CSR cryptographically, and if everything checks out, a new certificate is issued using the public key that was sent in the CSR. Existing certificates can also be renewed or revoked in a similar manner.
The certificate we obtain from Let's Encrypt is an X.509 Certificate (often shortened to cert). This certificate includes both our public key and a digital signature proving that Let's Encrypt signed this certificate with their own private key. The certificate includes details like the common name (i.e., domain name) for which this certificate is intended, who issued the certificate, the validity period of the certificate (they expire), etc.
We can use the certificate and our private key in various ways. Here's how you might do it in node.js:
const https = require('https');
const fs = require('fs');
const options = {
key: fs.readFileSync('path/to/private/key.pem'),
cert: fs.readFileSync('path/to/public/cert.pem'),
};
https.createServer(options, (req, res) => {
res.writeHead(200);
res.end('hello secure!\n');
}).listen(8000);
Let's Encrypt certificates expire in 90 days, and you are encouraged to renew them ~30 days before they expire. Due to rate limiting, the renewal process can take multiple attempts, so starting the process early is recommended.
A renewal is no different from requesting an initial certificate. Let's Encrypt considers a request a "renewal" if the domain name(s) match those of an existing certificate.