Today I needed to set up an SSL certificate for our company website. Being frugal, and interested, I decided to try Let’s Encrypt (a new organisation which aims to make SSL free, so that nobody has any excuses).
First step, get the client by cloning the git repository:
git clone https://github.com/letsencrypt/letsencrypt.git
Now, before you start: if you’re on a mac, you should make sure you have homebrew installed and working. Once that is done, install python through it (because the homebrew version comes with pip the python package manager):
brew install python
Then when that is installed, install virtualenv:
pip install virtualenv
Right, that’s all the dependencies for the letsencrypt client. Let’s move on to prepping your azure website. I assume that you have a running website under a custom domain already. The internet has plenty of documentation on how to get there. Let’s Encrypt uses a protocol called ACME to verify that you own the domain that you are trying to get a certificate for. It does this by asking you to serve a particular piece of content, unique to your request for a certificate. Getting Azure to do this is actually fairly simple, if you have the right documentation collated together, so here it is:
- Through your FTP access to your website create a directory called well-known as a sibling of the wwwroot directory, and within this new directory, create a directory called acme-challenge
- In the Application settings blade of your website, in the new Azure portal, right down the bottom of the blade, add an entry under Virtual applications and directories with the following values
- Virtual Directory: /.well-known
- Physical path rel: site\well-known
- Leave the ‘application’ box unticked
- Next create a web.config file with the following contents:
<?xml version="1.0"?> <configuration> <system.webServer> <staticContent> <mimeMap fileExtension="." mimeType="text/plain" /> <mimeMap fileExtension=".txt" mimeType="text/plain" /> </staticContent> </system.webServer> </configuration>
- Place the web config file into both the well-known, and acme-challenge directories.
- Create a .txt file with something in it, and place it in the acme-challenge directory, then try to access it. If you get the content of your text file showing up in your browser, you’re good.
Ok, now you’re good to go, so change to the directory where you cloned the letsencrypt repository
The command is quite simple:
./letsencrypt-auto certonly -a manual --rsa-key-size 4096 -d domain.com --debug
If you’re using a Mac and you leave off the –debug flag, you’ll just get told to put it on. At this point you’ll go through a few screens with some prompts etc, and then you’ll get to this:
Make sure your web server displays the following content at http://domain.com/.well-known/acme-challenge/KkRlmp5Y7Vtitd37tyZ3M7rtwrZ7b9KyoFf4-UdGMBI before continuing: KkRlmp5Y7Vtitd37tyZ3M7rtwrZ7b9KyoFf4-UdGMBI.0XPKTuHHwF3vk2VV7czrfw72_Lnq8oEZPzXVPbkbk_E If you don't have HTTP server configured, you can run the following command on the target server (as root): mkdir -p /tmp/letsencrypt/public_html/.well-known/acme-challenge cd /tmp/letsencrypt/public_html printf "%s" KkRlmp5Y7Vtitd37tyZ3M7rtwrZ7b9KyoFf4-UdGMBI.0XPKTuHHwF3vk2VV7czrfw72_Lnq8oEZPzXVPbkbk_E > .well-known/acme-challenge/KkRlmp5Y7Vtitd37tyZ3M7rtwrZ7b9KyoFf4-UdGMBI # run only once per server: $(command -v python2 || command -v python2.7 || command -v python2.6) -c \ "import BaseHTTPServer, SimpleHTTPServer; \ s = BaseHTTPServer.HTTPServer(('', 80), SimpleHTTPServer.SimpleHTTPRequestHandler); \ s.serve_forever()" Press ENTER to continue
I wouldn’t worry about the lower bit, telling you how to run a very simple python server, but the upper half is quite important, particularly this bit:
printf "%s" KkRlmp5Y7Vtitd37tyZ3M7rtwrZ7b9KyoFf4-UdGMBI.0XPKTuHHwF3vk2VV7czrfw72_Lnq8oEZPzXVPbkbk_E > .well-known/acme-challenge/KkRlmp5Y7Vtitd37tyZ3M7rtwrZ7b9KyoFf4-UdGMBI
If you try to copy-paste the content into a file, you’ll probably get a newline in the file which will cause your attempt to fail. I didn’t read instructions properly the first three times, and I failed each attempt, until I looked more closely and realised they were telling me how to make the file I wanted in the first place!
Once you have a file generated as above, copy it into the acme-challenge directory you created via ftp. Now double check that it downloads correctly, but visiting the url they give you. If you get what they’re telling you they expect to see, then you’re good to go: press ENTER.
If you’re successful, you’ll get something like this:
IMPORTANT NOTES: - Congratulations! Your certificate and chain have been saved at /etc/letsencrypt/live/mwabu.com/fullchain.pem. Your cert will expire on 2016-04-17. To obtain a new version of the certificate in the future, simply run Let's Encrypt again. - If you like Let's Encrypt, please consider supporting our work by: Donating to ISRG / Let's Encrypt: https://letsencrypt.org/donate Donating to EFF: https://eff.org/donate-le
Now, that’s a really sucky place for them to put the certificates. I went in through finder and gave myself permissions to those directories. While you’re doing the ‘live’ directory, also do the ‘archive’ directory, as that is where the files really live – they’re just symlinked into live. I copied the archive folder elsewhere to do the next step, but you could do it in-place as well.
Ok, great so now you have a bunch of PEM files, but azure wants a PFX. That’s ok though because we can manage that with openssl. You might need to install this via homebrew, but try it first:
openssl pkcs12 -export -out /path/to/output/file.pfx -inkey /path/to/archive/privkey1.pem -in /path/to/archive/fullchain1.pem
Put in a password, as this file has a private key in it, so you don’t really want it lying around unprotected. I’ve subsequently deleted the extra copies I made, and I’ve removed my permissions from those directories as well. That way someone has to get into my computer, and log in as root in order to even see the files.
Ok, nearly there. Now you can upload the certificate to Azure, and once it is uploaded you can set up a binding to it. There are already plenty of docs out there about those two steps.