In this post, I will guide you step by step through the process of including free Let's Encrypt Certificates for any Web App hosted by the Web App Service on Azure.
The catch with Let's Encrypt SSL Certificates is that they only last for 90 days. But hey, nothing automation couldn't solve.
This tutorial will be based on the Azure Web App Site Extension "Azure Let's Encrypt" by Simon J.K. Pedersen.
(Small Disclaimer: The site extension is not supported by Microsoft, I am using it for many smaller projects and it is working great so far).
Azure Web App Site Extension for easy installation and configuration of Let's Encrypt issued SSL certifcates for custom domain names.
Let's Encrypt Site Extension
This Azure Web App Site Extension enables easy installation and configuration of Let's Encrypt issued SSL certificates for you custom domain names.
The site extension requires that you have configured a DNS entry for your custom domain to point to Azure Web App.
November 2019 - Microsoft finally acknowledge that maybe it is in due time that they add first level support for free SSL certificates, see this announcement about App Service Managed Certificates, be aware that it is in preview and currently doesn't support the apex/naked domain.
How to install
- This site-extension is NOT supported by Microsoft it is my own work based on https://github.com/fszlin/certes - this means don't expect 24x7 support, I use it for several of my own smaller sites, but if you are running sites that are important you should consider spending the few $ on a certificate…
- An Azure Account (If you are a student, click here to find out how to get free Azure Ressources.)
- A Web Application hosted using the App Service Web Apps (Could be simple HTML and CSS or something like React)
- Your own custom DNS entry configured to point to your Web App.
⚠ Ideally, your App Service Plan and your App Service are in the same resource group.
First of all, we are going to create an Azure Storage Account so the extension is able to renew the Let's Encrypt Certificates every 3 months by using Azure WebJobs.
"The storage account must be of kind
BlobStorage will not work."
Now we will need to add 2 application settings called
AzureWebJobsStorage with the connection string of our previously created Storage Account. The connection string should look for example like this:
For the extension to work unattended and without our manual interference we need to create an Azure Service Principle, which works basically as an "on behalf of" delegate Azure AD entry.
- Go into the Azure Active Directory (AAD) directory you want to use to create your new application.
- In the panel of the directory select
Create a new application and set it up like shown in the picture.
Create a new client secret for the application. Make sure you save the generated secret, as you will not be able to access it in clear text again!
Go back to the Overview tab and also save the Application (Client) ID. To continue you should now have the client secret and the Application ID.
Now the Service Principle needs "Contribute" Access for the Resource Group of your App Service and App Service Plan.
This is done by accessing the
Access control (IAM)menu of the resource group and then clicking the 'Add' button.
In the upcoming menu, choose the
Contributorrole and add it to the created service principle.
⚠ If you have further services in the resource group, you are also able to add the
Contributor role only to the App Service and Service Plan.
Now that we set up all the necessities for the extension to work, we are able to install and configure it.
Head over to your App Service and search in the App Service menu for the extensions site. On the site add the extension
Azure Let's Encrypt by SJKP.
To configure the extension we need to head over to the
Advanced Tools page of our App Service. You find it by searching for
Advanced Tools in the menu's search bar and it will take you to a site like
To get to the extension settings you just have to click at the
Site extensions button in the menu at the top and click on the 'Launch' button of the extension. It will take you to the configuration page of the extension, shown in the picture below.
Tenant: is the Azure AD directory (tenant) that the service principal was created in -
- SubscriptionId: is the Id of the subscription you used for the resource group (the Id is also displayed on the 'Overview' page of your Resource Group). Also, you can get the Ids you are able to access from (https://portal.azure.com/#blade/Microsoft_Azure_Billing/SubscriptionsBlade)[https://portal.azure.com/#blade/Microsoft_Azure_Billing/SubscriptionsBlade].
- ClienId and ClientSecret: are the Id and secret you hopefully still got from the Service Principle we created.
- ResourceGroupName: is the name of the Resource Group of your App Service.
ServicePlanResourceGroupName: if the Service Plan and the App Service are in the same Resource Group, this name is identical to the
ResourceGroupName. Otherwise, you have to enter the name of the Resource Group that the Service Plan is located in (if so, remember to grant the Service Principle access to this Resource Group as well).
- Update Application Settings: should be set to true at the first run to save all the settings as web application settings. This is required so the settings are available when the WebJob renews the certificates.
After you have done so, you will see an overview of your custom domains, SSL Bindings, and Certificates. Since you still need to generate them, you should continue to the next page. There you are able to choose your domains (you can select several by holding the Ctrl key) you want to request an SSL certificate for.
Before doing so, you need to provide an email address, which will receive warnings by Let's Encrypt, for example in case a certificate was not renewed.
And that is everything you need to do, have fun! 🐱💻
Because Let's Encrypt needs to reach your page, to authorize your domain, make sure this URL is accessible to the public:
http://<yourDomain>.com/.well-known/acme-challenge/. In most cases of an error, this URL cannot be reached, for example, because of a rule-set in a web.config or because https is enforced in the App Service Settings.