DEV Community

Ope Adeyomoye
Ope Adeyomoye

Posted on

Securing your Azure Web App with Let's Encrypt.

This post assumes that you have deployed your web app in a Docker container on Microsoft Azure's fully-managed App Service platform. It also assumes that, for some reason, you want to manually obtain an SSL certificate for your app, and manually renew it before it expires.

Before we get to certificates...

When you deploy your app on Azure's App Service platform, you automatically get a URL that can be used to view your app. It'll usually be in the form: https://your-app-name.azurewebsites.net. If you like the free domain and don't exactly see a need to use a custom domain, then you probably don't need most of the rest of this post. I'd suggest you turn on "HTTPS only" tho.

Chances are, however, you do want to serve your app using a custom domain. If you've not added a custom domain to your App Service app, please see Azure's docs on this and follow the steps there.

It could be much easier

Azure lets you create a free certificate and add it your App Service app at the click of a couple buttons. It's issued by DigiCert, managed by App Service, and renewed automatically.

If you'd like to use this instead of rolling your own, see Azure's docs on it and don't forget to turn on HTTPS Only.

Getting a certificate

Let's Encrypt recommends using the Certbot ACME client for certificate issuance. Certbot can automate certificate issuance and installation, but this post demonstrates using Certbot in manual mode.

First, let's install Certbot. On Debian 10+ systems:

$ sudo apt-get update
$ sudo apt-get install certbot
Enter fullscreen mode Exit fullscreen mode

For other Debian versions, linux distros or different operating systems, please see Certbot's installation docs.

Issuing a certificate

Now, let's get an SSL certificate issued for yourdomain.com. On the command line:

$ sudo certbot certonly -d yourdomain.com --manual --preferred-challenges dns
Enter fullscreen mode Exit fullscreen mode

That command:

  • via the certonly sub-command, tells Certbot to simply obtain a new certificate, and not install it on your local machine;
  • tells Certbot to use a DNS challenge. As opposed to an HTTPS challenge where you'd have to upload a certain file to a specific directory on your server, a DNS challenge requires you to add a DNS TXT record on your domain.

After a few simple questions, Certbot will ask you to create a DNS TXT record, usually under the name _acme-challenge.yourdomain.com, with a value it provides. Usually, you'll do this via your DNS provider. Please see your DNS provider's docs on how to create DNS records for your domain.

If it all went well, you should see a message like this:

IMPORTANT NOTES:
 - Congratulations! Your certificate and chain have been saved at:
   /etc/letsencrypt/live/yourdomain.com/fullchain.pem
   Your key file has been saved at:
   /etc/letsencrypt/live/yourdomain.com/privkey.pem
   Your cert will expire on <some-date>. To obtain a new or tweaked
   version of this certificate in the future, simply run certbot
   again. To non-interactively renew *all* of your certificates, run
   "certbot renew"
 - If you like Certbot, please consider supporting our work by:

   Donating to ISRG / Let's Encrypt:   https://letsencrypt.org/donate
   Donating to EFF:                    https://eff.org/donate-le
Enter fullscreen mode Exit fullscreen mode

Add your shiny new certificate to App Service

To secure a custom domain for your web app, Azure requires a private certificate in the PKCS #12 file format. Certbot does not generate this file by default, but you can create it using some of the files it does generate.

Create a private certificate

For this, you'll need:

  1. your server certificate file;
  2. the private key for your certificate;
  3. the intermediate certificate from Let's Encrypt CA.

All those files can be found at /etc/letsencrypt/live/yourdomain.com/, and you can simply run the following commands to create your private certificate:

# create a staging area
$ mkdir /tmp/sandbox -p
$ cd /tmp/sandbox

# copy the needed files over
$ SOURCE=/etc/letsencrypt/live/yourdomain.com
$ sudo cp $SOURCE/{cert.pem,privkey.pem,chain.pem} .

# make the files your own
# assuming your username is ope...
$ sudo chown ope *.pem

# finally, create the private certificate,
# saving it to "certificate.pfx"
$ openssl pkcs12 -export -out certificate.pfx -inkey privkey.pem -in cert.pem -certfile chain.pem
Enter fullscreen mode Exit fullscreen mode

That last command asks you to enter an export password. Please make note of that password since you'll need it when uploading your private certificate on Azure.

Upload the private certificate

From your Azure portal, navigate to your App Service web app and click on the "Custom domains" menu item. In the page that comes up, find the row that contains the custom domain you added and click "Add binding" under the "SSL Binding" column.

Alt Text

In the sidebar that comes up, click "Upload PFX Certificate"

Alt Text

Within the form that's displayed next, select the certificate.pfx file you created, and enter the password you chose.

Alt Text

Click "Upload" to proceed. The next screen should look like this:

Alt Text

Click "Add Binding" once you've selected the relevant options.

That's it! Once the deployment is complete on Azure, you can now navigate to your web app, via your custom domain, using HTTPS.

Clean up

You can't subsequently download your private certificate from Azure App Service, so you might want to store the local copy somewhere other than the system temp directory:

$ cp /tmp/sandbox/certificate.pfx /path/to/dir/
Enter fullscreen mode Exit fullscreen mode

Once your private certificate is safe, you may clear out the sandbox:

$ rm /tmp/sandbox/ -R
Enter fullscreen mode Exit fullscreen mode

Consider turning on "HTTPS Only"

Azure App Service has a little handy feature, called HTTPS Only, that helps redirect all of your app's HTTP traffic to HTTPS.

That makes sure that any client communication with your app is encrypted, and visitors aren't scared away with "Connection not secure" messages from their browsers.

To turn this on, head on to your App Service within the Azure portal, and click on the TLS/SSL settings menu item. You'll find the option there under "Protocol Settings".

Top comments (14)

Collapse
 
jowilsonfo profile image
jowilsonfo

Thanks, save a lot of my time. I complemented the flow adapting the script from docs.microsoft.com/en-us/azure/app..., after some ajusts, to auto upload the certificate to the web app docker.

Collapse
 
panachesoftwaredev profile image
Peter Davis

I'm late to this post but I have to say thank you for this guide. After spending almost the entire day fighting with trying to generate a pfx from a godaddy certificate and tearing my hair out as I simply couldn't find a way to get things to work, this guide worked first time within minutes and got me fully up and running.

You're a lifesaver!

Collapse
 
ope profile image
Ope Adeyomoye

Glad it helped!

Collapse
 
tusabweb profile image
TUSAB-web

Thanks for this guide! I needed to do this manually for an Azure site for reasons I won't get into. All I had to do with your guide was change the preferred challenge to HTML in my case and followed all the instructions - got my certificate created and uploaded!

Collapse
 
ope profile image
Ope Adeyomoye

Awesome! Thanks a lot for your comment. Glad you found it helpful.

Collapse
 
teddyorkie profile image
Quang Le

Awesome guide. Exactly what I was looking for. The DNS vs HTTPS challenge was what got me stuck from the beginning. Guess I have to read certbot instruction/manual more careful.

Collapse
 
ope profile image
Ope Adeyomoye

Glad it helped!

Collapse
 
kissless profile image
Ilya

Thanks a lot! I thought I would have to deal with injecting certificates to the docker containers in order to validate the domain ownership, but this article saved me from that :)

Collapse
 
ope profile image
Ope Adeyomoye

Haha thanks Ilya. Glad it helped!

Collapse
 
nguyentk90 profile image
Nguyen Tran

Thanks for your guide!

Collapse
 
diomedesdominguez profile image
Diomedes Ignacio Domínguez Ureña

Thanks for this, can you help us to renovate the certificate?

Collapse
 
ope profile image
Ope Adeyomoye

How do you mean?

Collapse
 
hboelman profile image
Henk Boelman

Thank you! Very helpful!

Collapse
 
antarr profile image
antarr

Awesome! Not time to automate it.