ThorneLabs

Create Let's Encrypt SSL Certificates with lego, DNS Challenge, and Google Cloud DNS

• Updated January 10, 2019


Since it was released to the world, Let’s Encrypt has been a boon for anyone wanting to secure their website or web application with TLS. A lot of work has been, and continues to be, done to provide HTTPS for free to the masses.

Because Let’s Encrypt is an open certificate authority and provides an API to create, renew, and revoke SSL certificates, anyone can create tools to make a historically cumbersome and difficult process more efficient and easier.

certbot is one of the more popular tools to do just that. But, if you are looking for a tool that is more manual and walks you through the process step-by-step, there are websites such as Get HTTPS for free!.

I have used both certbot and Get HTTPS for free! to create and renew my own Let’s Encrypt SSL certificates. certbot is designed to provide a more automated process - especially because Let’s Encrypt SSL certificates are only valid for 3 months - but I could never get a streamlined process implemented due to the way I run my own websites and web applications. I needed something simpler and more scalable. I needed a tool that would allow me to do a DNS challenge instead of an HTTP challenge.

There are probably many tools already available that can do a Let’s Encrypt DNS challenge, but lego - a Let’s Encrypt client written in Go - is the first tool I discovered that made the process exceptionally easy and worked with the cloud platform I am using.

In my particular case, I am using Google Cloud Platform and Google Cloud DNS, and that is what this post will cover. Keep in mind, lego is constantly being developed and works with all of the DNS providers listed here.

Authenticate Against Google Cloud Platform

This post assumes the following:

  • You are familiar with and have already been using Google Cloud Platform
  • You already have a DNS zone created and working in Google Cloud DNS

Additionally, you will need to install the Google Cloud SDK which installs the gcloud command. If you haven’t already installed it, follow the instructions here.

With the Google Cloud SDK installed, authenticate gcloud against your Google Cloud Platform account:

gcloud auth login

A web page will open in your web browser. Select and give permission to your Google account to access Google Cloud Platform, and you should be authenticated.

Since you will be dealing with a DNS zone, verify you can see your existing DNS zone by running the following gcloud command:

gcloud dns managed-zones list

Install Golang

lego is written in Golang. You will need to setup Golang on your workstation if you haven’t already done so. The following steps will focus on installing Golang on macOS, but they should work just as well on modern Linux distributions.

Download the latest stable Golang release for your operating system here.

Once the package is downloaded, execute it and begin installation.

After installation, verify the go command is working:

go

Create a directory for your Go workspace:

sudo mkdir /usr/local/goworkspace

Point the GOPATH environment variable to the directory you just created, and add it to .bash_profile:

echo 'export GOPATH="/usr/local/goworkspace"' >> ~/.bash_profile

Also, add the bin directory in your Go workspace to your shell’s environment path:

echo 'export PATH="$PATH:$GOPATH/bin"' >> ~/.bash_profile

Finally, re-source .bash_profile:

source ~/.bash_profile

Install lego

With your Go environment setup, it is time to install lego.

go get -v -u github.com/xenolf/lego

It might take a couple minutes for the dependencies and lego to install.

Once installed, verify the lego command is working:

lego -h

Create an SSL Certificate with lego

Finally, it’s time to generate an SSL certificate from Let’s Encrypt with lego.

To obtain an SSL certificate for domain example.com, run the following command (replace example-project with your GCP Project name, example.com with your fully qualified domain name, and your-email@address.com with the email address you want to use with Let’s Encrypt):

GCE_PROJECT="example-project" GCE_DOMAIN="example.com" lego \
    --email="your-email@address.com" \
    --domains="example.com" \
    --dns="gcloud" \
    --path="${HOME}/.lego" \
    --server=https://acme-v01.api.letsencrypt.org/directory \
    run

lego works with many different DNS providers, but because it is using the gcloud DNS provider, it uses the Google Cloud DNS API (through the gcloud command) to add a DNS TXT record to your domain’s DNS zone.

If you run gcloud dns record-sets list --zone example.com-zone while the lego command is running, you should see a new DNS TXT record with the name _acme-challenge.example.com. along with a unique string of data. The Let’s Encrypt API uses this DNS TXT record to verify the domain name belongs to you. Once the DNS challenge is complete, the DNS TXT record is deleted.

The output of this entire process will look similar to the following:

2016/11/08 18:17:00 [INFO][example.com] acme: Obtaining bundled SAN certificate
2016/11/08 18:17:00 [INFO][example.com] acme: Could not find solver for: tls-sni-01
2016/11/08 18:17:00 [INFO][example.com] acme: Could not find solver for: http-01
2016/11/08 18:17:00 [INFO][example.com] acme: Trying to solve DNS-01
2016/11/08 18:17:06 [INFO][example.com] Checking DNS record propagation using [8.8.8.8:53 8.8.4.4:53]
2016/11/08 18:17:48 [INFO][example.com] The server validated our request
2016/11/08 18:17:49 [INFO][example.com] acme: Validations succeeded; requesting certificates
2016/11/08 18:17:49 [INFO] acme: Requesting issuer cert from https://acme-v01.api.letsencrypt.org/acme/issuer-cert
2016/11/08 18:17:49 [INFO][example.com] Server responded with a certificate.

With the DNS challenge complete, you will find your new SSL certificate and private key in directory ~/.lego/certificates.

In that directory you should find example.com.crt, example.com.key, and example.com.json.

example.com.crt is a chained SSL certificate that includes the SSL certificate and the Let’s Encrypt intermediate certificate concatenated together.

example.com.key is the SSL private key.

example.com.json is a JSON configuration file used by the lego command.

Renew an SSL Certificate with lego

In order to renew an SSL certificate, your .lego directory must already have an existing SSL certificate and private key for the particular domain. If that file does not exist, the command below will fail, and you will need to run the lego run command above.

But, if you have already run the lego run command above, and you do need to renew the SSL certificate for example.com, run the same command from above but with renew instead of run:

GCE_PROJECT="example-project" GCE_DOMAIN="example.com" lego \
    --email="your-email@address.com" \
    --domains="example.com" \
    --dns="gcloud" \
    --path="${HOME}/.lego" \
    --server=https://acme-v01.api.letsencrypt.org/directory \
    renew

Once again, you will find the renewed SSL certificate in directory ~/.lego/certificates.

References