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
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
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
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:
- your server certificate file;
- the private key for your certificate;
- 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
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.
In the sidebar that comes up, click "Upload PFX Certificate"
Within the form that's displayed next, select the certificate.pfx
file you created, and enter the password you chose.
Click "Upload" to proceed. The next screen should look like this:
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/
Once your private certificate is safe, you may clear out the sandbox:
$ rm /tmp/sandbox/ -R
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)
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.
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!
Glad it helped!
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!
Awesome! Thanks a lot for your comment. Glad you found it helpful.
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.
Glad it helped!
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 :)
Haha thanks Ilya. Glad it helped!
Thanks for your guide!
Thanks for this, can you help us to renovate the certificate?
How do you mean?
Thank you! Very helpful!
Awesome! Not time to automate it.