This Gist documents how to obtain a Let's Encrypt certificate for use with CloudFlare origin servers. For background please see my article on CloudFlare and Origin Servers for the Rightfully Paranoid.
I'm assuming OpenSSL is installed on your machine. You're also going to need
Node.js 5.6.0 or above. We'll be using
wilee
to obtain the certificate from
Let's Encrypt.
First generate the private key for your Let's Encrypt account:
openssl genrsa -out account.pem 4096
Then generate the private key for the certificate you want issued:
openssl genrsa -out privkey.pem 2048
You'll have to create a certificate signing request that gets sent to Let's
Encrypt. Most likely you'll want the certificate to work for your main domain
and the www
subdomain. Here's the approach that worked for me.
First copy the openssl.cnf
file to a new location. On OS X it should be under
/System/Library/OpenSSL/openssl.cnf
, on Linux it's probably under
/etc/ssl/openssl.cnf
. Add the following at the end:
[ req ]
req_extensions = v3_req
[ v3_req ]
# Extensions to add to a certificate request
basicConstraints = CA:FALSE
keyUsage = nonRepudiation, digitalSignature, keyEncipherment
subjectAltName = @alt_names
[alt_names]
Then under alt_names
list the DNS names, like:
DNS.1=example.com
DNS.2=www.example.com
Substitute example.com
for your domain name. You can add more domains, e.g.
DNS.3=admin.example.com
, DNS.4=beta.example.com
.
Create the request like this:
openssl req -new -sha256 -key privkey.pem -outform der -out csr.der -config openssl.cnf
Please see this Google Developers tutorial on how to answer the CSR questions.
Next install wilee
:
npm install -g wilee
Rate limits
apply
when you use Let's Encrypt. It's best to go through this flow using their
staging
server
first. This is the default when you use wilee
so let's push on.
Run the following to register an account with Let's Encrypt:
wilee --account account.pem new-reg [email protected]
Please use your actual email address. Note that MX
records must exist. You'll
have to agree to the terms of service as well.
Your account needs to be authorized for each domain you've included in the
certificate signing request. Run the following to authorize your account for
example.com
:
wilee --account account.pem new-authz example.com
This will prompt you to create a TXT
record for _acme-challenge.example.com
with a specific value. You can create this record using CloudFlare's dashboard.
Make sure to use the smallest possible TTL value.
wilee
will poll DNS until the record exists, then it'll ask Let's Encrypt to
verify.
Repeat for your other domain names, e.g.:
wilee --account account.pem new-authz www.example.com
This will prompt you to create a TXT
record for
_acme-challenge.www.example.com
with a different value.
Once you've authorized all domain names you can request the certificate:
wilee --account account.pem new-cert csr.der --out cert.der
Assuming all this worked you can repeat the process using Let's Encrypt's production server. You'll be making a new account and you'll have to authorize your domains again.
To register:
wilee --account account.pem --directory https://acme-v01.api.letsencrypt.org/directory new-reg [email protected]
To authorize a domain:
wilee --account account.pem --directory https://acme-v01.api.letsencrypt.org/directory new-authz example.com
To request the certificate:
wilee --account account.pem --directory https://acme-v01.api.letsencrypt.org/directory new-cert csr.der --out cert.der
CloudFlare won't accept the certificate by itself. It needs the intermediate certificates.
Personally I like creating a .p12
file which combines the private key and
certificates. Node.js accepts these files when you create an HTTPS server using
the pfx
option.
First convert the cert.der
file:
openssl x509 -inform der -in cert.der -out chain.pem
Append the content of
https://letsencrypt.org/certs/lets-encrypt-x3-cross-signed.pem.txt to
chain.pem
:
curl https://letsencrypt.org/certs/lets-encrypt-x3-cross-signed.pem.txt >> chain.pem
Then to create the .p12
file:
openssl pkcs12 -export -passout pass: -inkey privkey.pem -in chain.pem -out cert.p12
Configure your server to use cert.p12
and CloudFlare should accept it.
Let's Encrypt certificates expire after 90 days. The process described in this Gist is manual, so you'll have to repeat it before your certificate has expired. It's recommended to do this in the last 30 days that your certificate is still valid.
You can use your existing Let's Encrypt account, provided you haven't lost the
account key. You should be able to use your existing certificate signing request
as well. Simply request the new certificate and follow the steps to create a new
.p12
file:
wilee --account account.pem --directory https://acme-v01.api.letsencrypt.org/directory new-cert csr.der --out cert.der
Domain authorizations expire after 10 months. You'll have to reauthorize domains at that point.
Error 'rsa routines:RSA_sign:digest too big for rsa key:rsa_sign.c:122'
I regenerated privkey.pem using
openssl genrsa -out privkey.pem 4096
andopenssl req -new -sha512...