Getting Let's Encrypt Certificate for a Google App Engine Hosted Website
Let's Encrypt is a completely free Certificate Authority (CA) who distributed free and trusted TLS server certificates for website owners around the world to use. The process of using their certificate on a Google App Engine (GAE) hosted site, however, was a little tricky and thus I will record the steps I have done in order to achieve this.
Obtain an ACME Client
First things first, Let's Encrypt does not have any web form for obtaining a certificate. In order to do so, you have to use so called an Automated Certificate Management Environment (ACME) client to talk with Let's Encrypt's server, which implements the ACME server side protocol. After you have proven the ownership of your domain, the server will automatically signs your private key and the whole process takes less than 5 min to complete.
In order to download the official ACME client made by the Let's Encrypt project, go to their GitHub and follow the instructions on there.
Once you have a working ACME client, next thing you will need to do is to run the ACME client in "Certificate Only" and "Manual Authentication Mode. " The reason for this being that Let's Encrypt was created as a "fool proof" one-liner solution that will ideally obtain and install a TLS certificate on your website automatically in a typical setup. Unfortunately, as GAE user, we do not have direct control over the server hosting our website and thus we would have to do those process by ourself.
Obtain the Certificate
Let's run the ACME client in the mode we have mentioned above:
[datong@localhost letsencrypt]$ ./letsencrypt-auto certonly --manual
Give few seconds for any output to come back since this command will do some auto-update work before invoking the actual ACME client program. If you are prompted to enter a sudo
password, this is perfectly normal since Let's Encrypt's ACME client stores the generated private key in a location only accessible by root
by default in order to protect it.
If you are running this in a Terminal window and everything goes smoothly, you will see an old school ncurses
style text based GUI. The first thing it will ask you is the domain name(s) you would like to sign for in your requested certificate. If you provide multiple ones, the resulted certificate will be containing an extra "Subject Alternative Names (SAN)" field which allows it to work with multiple domain names. Since today we are only encrypting one website, I will just put one domain name www.cyfly.org
inside the box.
After that, you will be presented to agree their terms and verify your ownership of the domain. Different from most of the public CAs out there, which uses Email Validation, Let's Encrypt used the HTTP File Validation method. In order to prove your ownership of the website, Let's Encrypt will instruct you to do something like the following:
Make sure your web server displays the following content at
http://www.cyfly.org/.well-known/acme-challenge/vjiHqi5E9FfiNjOe2yajth-eVzxS1oHfMCBwj6HVQoE before continuing:
vjiHqi5E9FfiNjOe2yajth-eVzxS1oHfMCBwj6HVQoE.2GhklWKkNkag5BcFx95RAhNTluIbbubTNSXlUR_dsNY
Configure GAE to Serve Our Token File
In order to let GAE serve this file over the specified URL by Let's Encrypt, we need to find a convenient location under your application directory that will be used to store the actual file. I created a sub-directory called well-known
under static
for this purpose.
Please note that you do not have to and can not create a directory starting with .
. Doing so will make appcfg.py
ignore this directory during the scanning peocess and the directory will never be uploaded to Google's Server! This is why I created a directory called well-known
, omitting the leading dot.
To map the URL /.well-known
to the directory we newly created, we simply add a new static file handler in our app.yaml
file:
- url: /.well-known
static_dir: application/static/well-known
mime_type: text/plain
secure: always
Remember to change the static_dir
section to match your actual setup. Also mime_type
and secure
are not technically required but it allows you to check the content of the file using your browser easily and thus was added.
Next, we need to create the acme-challenge/vjiHqi5E9FfiNjOe2yajth-eVzxS1oHfMCBwj6HVQoE
file under well-known
as requested by the ACME client. Use whatever editor of your choice but remember this file contains only one line of content and do not put a newline character after the first line. The content of the file will be:
vjiHqi5E9FfiNjOe2yajth-eVzxS1oHfMCBwj6HVQoE.2GhklWKkNkag5BcFx95RAhNTluIbbubTNSXlUR_dsNY
as required by the client.
After that, update your GAE application and make sure http://www.cyfly.org/.well-known/acme-challenge/vjiHqi5E9FfiNjOe2yajth-eVzxS1oHfMCBwj6HVQoE
is indeed accessible and contains the correct file format. After that let the ACME client to continue and if you did everything correctly, you will get a new certificate within couple of seconds.
Installing the Certificate
By default, the ACME client stores the certificate along with it's private key under /etc/letsencrypt/live/<your domain name>/
. Navigate to that directory as root, fullchain.pem
file contains the certificate along with any required intermediates for your certificate and should almost always be used. privkey.pem
is your private key.
When uploading your certificate to Google, the certificate file will simply be fullchain.pem
. For the private key, however, you will have to run a simple command to get rid of the extra OID indicating the type of key first before Google would accept it. Currently Google only accepts RSA private key for custom TLS and Let's Encrypt only signs certificates using RSA public key so should work out pretty well.
To convert:
[root@localhost www.cyfly.org]# openssl rsa -in privkey.pem -check
Simply copy the content from -----BEGIN RSA PRIVATE KEY-----
to -----END RSA PRIVATE KEY-----
and paste it into the Google form and it should work right away.
After that, enable your new certificate and make sure it works by checking your website using ssllabs.com. You can keep or remove the authentication file safely on your website since it is only used once by Let's Encrypt and does not contain any useful information regarding your website.