Skip to content

Instantly share code, notes, and snippets.

@novemberborn
Last active July 31, 2016 14:29
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save novemberborn/4f13d2679a580eb3a080 to your computer and use it in GitHub Desktop.
Save novemberborn/4f13d2679a580eb3a080 to your computer and use it in GitHub Desktop.
Obtaining Let's Encrypt certificates for CloudFlare origin servers, using wilee

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.

Prerequisites

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.

Using wilee

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.

Registering with Let's Encrypt

Run the following to register an account with Let's Encrypt:

wilee --account account.pem new-reg my-email@example.com

Please use your actual email address. Note that MX records must exist. You'll have to agree to the terms of service as well.

Authorize your account for each domain

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.

Requesting the certificate

Once you've authorized all domain names you can request the certificate:

wilee --account account.pem new-cert csr.der --out cert.der

Now for real

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 my-email@example.com

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

Creating a PKCS #12 file with intermediate certificates

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.

Renewing the certificate

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.

@jastuccio
Copy link

jastuccio commented Jul 12, 2016

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 and openssl req -new -sha512...

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment