Loading...
Loading...
Marco Franssen

Let's Encrypt is a free, automated service that provides SSL certificates. Although the certificates are valid for only three months, you can automate requests and renewals. In the setup described here, Let's Encrypt's Python client runs on Linux.
In this post, I'll show you how I used the Let's Encrypt Vagrant box (an Ubuntu VM) to validate a certificate request for an Azure website. We'll set up a reverse proxy for the specific URLs Let's Encrypt uses to validate the request.
If you're impatient, skip straight to the summary.
First, let's configure a reverse proxy on our Azure website to handle requests intended for Let's Encrypt. The service needs to reach the Vagrant box from which we'll request the certificate, so I created a reverse proxy on my Azure website.
Make sure you have an applicationHost.xtd file in the /site folder of your Azure website. This folder also contains wwwroot.
<?xml version="1.0"?>
<configuration xmlns:xdt="http://schemas.microsoft.com/XML-Document-Transform">
<system.webServer>
<proxy xdt:Transform="InsertIfMissing" enabled="true" preserveHostHeader="false" reverseRewriteHostInResponseHeaders="false" />
</system.webServer>
</configuration>Make sure the following configuration is in your web.config file, in /site/wwwroot.
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<system.webServer>
<rewrite>
<rules>
<rule name="Letsencrypt" stopProcessing="true">
<match url="^.well-known/acme-challenge/(.*)" />
<action type="Rewrite" url="http://{my-home-ip}:9999/.well-known/acme-challenge/{R:1}" />
</rule>
</rules>
</rewrite>
<system.webServer>
</configuration>This rewrite rule forwards traffic for /.well-known/acme-challenge/ to my home IP address on port 9999. In my router, I've forwarded this port to my laptop's IP address. A request to https://marcofranssen.nl/.well-known/acme-challenge/ will then reach the Let's Encrypt Vagrant box on my laptop. Well, not quite yet—keep reading. ;-)
To reach the Vagrant box later, we'll also need a port forwarding rule in the router. Forward traffic on port 9999 to port 9999 on your laptop or PC.
Example:
99990.0.0.09999192.168.0.20Requests to this port will now reach your laptop or PC on port 9999.
Next, we'll get the Let's Encrypt client running on this port. First, clone the Let's Encrypt repository from GitHub.
git clone git@github.com:letsencrypt/letsencrypt.gitAdd the following line to the Vagrantfile to forward traffic from the host to the VM. Let's Encrypt will use this port to access the validation files when we request the certificate.
ubuntu_trusty.vm.network "forwarded_port", guest: 9999, host: 9999, id: "letsencrypt"Run vagrant up from the letsencrypt folder in Bash or PowerShell to boot the VM. Once it's running, use vagrant ssh to connect. Inside the VM, change to /vagrant to access the letsencrypt-auto client.
cd /vagrant
./letsencrypt-auto certonly \
--text \
--agree-tos \
--email your@email.com \
--renew-by-default \
--standalone \
--standalone-supported-challenges http-01 \
--http-01-port 9999 \
-d marcofranssen.nlThe command above requests an SSL certificate for marcofranssen.nl. You can find the certificate files in /etc/letsencrypt/live/marcofranssen.nl:
$ sudo ls /etc/letsencrypt/live/marcofranssen.nl
cert.pem chain.pem fullchain.pem privkey.pemAzure requires a .pfx file, so we need one more step to create it. I store the files under /vagrant so I can retrieve them from the host's letsencrypt folder and upload them to Azure. The host's letsencrypt folder is mapped to /vagrant inside the VM.
$ mkdir -p $CERTIFICATES
$ cd $CERTIFICATES
$ sudo openssl pkcs12 -inkey $LE_OUTPUT/$DOMAIN/privkey.pem -in $LE_OUTPUT/$DOMAIN/fullchain.pem -export -out ${DOMAIN}.pfx
Enter Export Password:
Verifying - Enter Export Password:Now that we have the pfx, we can upload it to Azure to install the certificate.
To bring this together, we can put the commands in a Bash script and run it for each Azure website where we've configured the reverse proxy. Place the file in your letsencrypt folder.
#!/bin/bash
LE_OUTPUT=/etc/letsencrypt/live
CERTIFICATES=/vagrant/certificates
EMAIL=your@email.com
DOMAIN=$1
if [[ -z "$DOMAIN" ]] ; then
echo Please provide a domain name...
echo Example:
echo " ./letsencrypt-domain.sh marcofranssen.nl"
echo " ./letsencrypt-domain.sh subdomain.marcofranssen.nl"
exit 1
fi
./letsencrypt-auto certonly \
--text \
--agree-tos \
--email $EMAIL \
--renew-by-default \
--standalone \
--standalone-supported-challenges http-01 \
--http-01-port 9999 \
-d $DOMAIN
mkdir -p $CERTIFICATES
cd $CERTIFICATES
sudo openssl pkcs12 -inkey $LE_OUTPUT/$DOMAIN/privkey.pem -in $LE_OUTPUT/$DOMAIN/fullchain.pem -export -out ${DOMAIN}.pfxUnfortunately, I didn't find a way to upload the certificate to Azure automatically. Otherwise, we could have added that step to the script using curl.
Your certificate renewal workflow then looks like this:
$ cd /c/letsencrypt
$ vagrant up
$ vagrant ssh
$ cd /vagrant
$ ./letsencrypt-domain.sh marcofranssen.nl
Enter Export Password:
Verifying - Enter Export Password:
$ ./letsencrypt-domain.sh subdomain.marcofranssen.nl
Enter Export Password:
Verifying - Enter Export Password:
$ ./letsencrypt-domain.sh someotherdomain.nl
Enter Export Password:
Verifying - Enter Export Password:
$ exit
$ vagrant haltYou'll find your certificates in c:\letsencrypt\certificates, assuming you cloned the letsencrypt repository in c:\. Upload them to your Azure website, and you're done…
For Apache, Nginx, and HAProxy, you can put fullchain.pem in place on the server. As a challenge, try adding Bash commands to copy fullchain.pem to your web server and restart it with the appropriate command once the files are in place. That way, you can automate this workflow without running Let's Encrypt on those servers.
Marco Franssen
Set up a Docker development environment on Windows or Mac using Docker Machine and VirtualBox, then configure your shell and run a test container.
Marco Franssen
Learn how to replace Node.js error-first callbacks with Promises, flatten nested asynchronous code, and wrap callback APIs with practical examples.
Marco Franssen
Set up separate Windows 10 boot profiles with bcdedit to switch between Hyper-V for the Windows Phone emulator and VirtualBox for Linux development.
Marco Franssen
Compare Jasmine 2.4 and Mocha 2.3, including test structure, Chai assertions, Sinon spies and asynchronous testing with callbacks and promises.