When providing training, I demonstrate how to obtain free automated Let’s Encrypt certificates and store them in Azure Key Vault using an ACME Bot. I’ve been asked a few times to put together a step-by-step guide, so here it is.
IMPORTANT: I am implementing this solution in a demo environment with a domain name I have registered, which is not used in production. Please be careful when implementing any new solution in production. Ensure you thoroughly research and understand what you’re deploying first.
In this post I will go through a step by step guide on how to deploy a low cost solution in Azure to obtain free TLS certs from Let’s Encrypt and store them in Azure Key Vault. Furthermore, we can automatically renew these certificates and request for additional TLS certificates as needed.
Free Managed Certificates provided by the Azure platform
Depending on which services you use in Azure, there are free certificates available for use, for example, with Azure App Services and Azure Front Door. These certs are free, managed by the Azure platform and automatically renewed. However, free managed certs are limited to some services in Azure, so can not be used for all solutions.
What is Let’s Encrypt?
Let’s Encrypt is a Certificate Authority that provides free TLS certificates, making it easy for websites to enable HTTPS encryption and create a more secure Internet for everyone. Let’s Encrypt is a project of the nonprofit Internet Security Research Group.
What is ACME?
ACME stands for Automatic Certificate Management Environment. It’s a protocol that helps automate the process of obtaining and renewing SSL/TLS certificates. This means you don’t have to manually request or update certificates; ACME does it for you, making it easier to keep your website secure. There are several ACME providers, including Let’s Encrypt, which is the provider I will be using. Other providers include Buypass Go SSL, ZeroSSL, Google Trust Services, SSL.com and more.
Let’s Encrypt is one of the well known providers, offering free certificates and supports the ACME protocol for automation. To request free TLS certs, I will deploy a client to interact with the provider Let’s Encrypt. I’ll cover further details on the client later in this post.
If you wish to follow along with this demo, I will be deploying/using the below services. If you don’t have access to an Azure subscription, not to worry, I will provide a step by step guide including screenshots whilst I go through the deployment.
- Azure Subscription: this solution will cost a small amount so an Azure Subscription is required for billing.
- Domain name: I’ll be using a domain I have previously registered, cloudcrazy.co.uk
- Client: Key Vault ACME bot. I’ll be using an Azure Function to run the Key Vault ACME bot client. The ACME bot will connect to the ACME provider (Let’s Encrypt) to allow me to request FREE TLS certs. I won’t be building the ACME bot client from scratch, it already exists on GitHub at the following link, GitHub Acmebot.
- Azure App Service Plan: an Azure App Service Plan will be deployed for the Client (Azure Function App) to run in consumption mode, so it will only cost a small amount when I trigger the function app requesting for new certs, or when the app checks for certificate expiry/renewals.
- Storage account: A storage account will be required for the client (Azure Function App) but won’t take up to much storage.
- Azure Key Vault: the ACME bot will also connect to Key Vault as that’s where I will be storing my TLS certs.
- Azure DNS: The DNS zone name I will be using and requesting certificates for is cloudcrazy.co.uk. You will need your own domain name. I’ll be creating an Azure DNS zone and configuring name server records for cloudcrazy.co.uk to redirect to Azure DNS. Other domain providers are also supported, such as Amazon Route 53, Cloudflare, GoDaddy, Google Cloud DNS and more. I’ll be deploying Azure DNS. With some additional effort you can also use your own custom DNS solution.
Let’s get started
- Visit the ACME Bot GitHub page at the following link, GitHub ACMEbot
- Feel free to browse the page to understand the ACME Bot further. The page shows the following at the time of writing this post.



3. Scrolling down to the bottom of the page, I see the option to deploy this solution into my Azure environment using an ARM (Azure Resource Manager) template. I’ll be deploying into Azure (Public). Click the Deploy to Azure button. The repository also includes the option to deploy via Terraform modules and Azure Bicep if that’s what you’re already using as part of your preferred IaC (Infrastructure as code) solution.

4. You’ll be prompted to login to the Azure portal

5. After I log in, the provided ARM template is automatically launched from the ACME GitHub repository into my Azure environment with some default settings enabled. I will need to complete the remaining fields before I deploy.

6. After completing the additional fields, this is what my deployment will look like. Please feel free to change as per your requirements.
Resource group name: rg-KeyVaultBot
Region: UK South
Mail Address: Email address for ACME account
ACME Endpoint: I am using provider Let’s Encrypt
Create With Key Vault: true (A new Key Vault will be created. If you have an existing Key Vault, click false and enter your key vault url in the Key Vault Base Url field.
Note
The new Azure Key Vault deployment configures RBAC for permissions and not access policies.

7. When ready, click Review + Create, and then create after reading the terms.


8. The deployment should take about 5 minutes

8. Click the button Go to resource group after the deployment has completed to check what has been deployed as part of this deployment.

9. Click on the Function App from inside the resource group

10. Explore the function app for now. Don’t make any changes.
11. If you click on Identity from the left pane, you’ll find that the deployment configured a system managed Identity for the function app. This gives the function app an identity which has been granted permissions to access the Azure Key Vault.

12. Let’s open the client app via the function app. Copy the url of your function app from the overview page, and open it in a web browser.

13. I get an error, not a very useful error but this is due to an authentication failure. I need to enable authentication for the app to allow me to login and access the client. We don’t want everyone on the Internet accessing this url anonymously and issuing certs on my behalf. In the next step, I will configure Entra ID authentication.

14. I’ll be using authentication via Entra ID which will allow me to use my Entra ID account. There are also other authentication methods available. Click Authentication (Under Settings) from the left pane in your function app. It is also possible to configure authentication directly from Entra ID. I’ll be using the authentication option inside the function app for this demo.

15. Click the button Add identity provider

16. Click Microsoft from the list of Identity providers

17. This wizard will create me an Entra ID app registration which will allow me to login to the function app using my Entra ID credentials. I am going to accept the default options here.


18. Click Add and wait for the deployment to complete

19. Let’s try the client (function app) url again
Success, Entra ID is prompting for credentials

20. Login with your Entra ID credentials
21. Permissions are needed for the application to access some information. Expand to check what permissions the app is needing.
Note: Carefully review what permissions are being granted before accepting for any app.


21. I click Accept button to grant the needed permissions

22. I successfully log in to the client (function app), but there is a further error related to DNS.
Orchestrator function ‘GetCertificates_Orchestrator’ failed: The activity function ‘GetAllCertificates’ failed: “DNS Provider is not configured. Please check the documentation and configure it.”. See the function execution logs for additional details.

The function app does not have access to my domain cloudcrazy.co.uk, therefore, it can not connect. I will need to resolve this before I can request for new TLS certificates from Let’s Encrypt.
23. Back in the Azure function app, under Settings, click Environment variables.

24. Click the Add button

25. Type the below:
Name: Acmebot:AzureDns:SubscriptionId
Value: Enter your subscription ID

26. Click Apply, and the click Apply again to save changes.
27. Click Confirm. Your app may restart.


Azure DNS
I’ll be creating a new Azure DNS zone in my demo environment.
28. In the Azure Portal, search for and click DNS Zones

29. Click create, select a resource group and input your domain.
Click Review and Create.

30. Next, I need to grant permissions for the Azure Function App (the client) to connect to my DNS zone. This will allow the app to request and perform verification when requesting TLS certs from Let’s Encrypt.

31. Click Add and then Add role assignment

32. Select DNS Zone Contributor and click Next

33. Select Managed identity and click + Select members

34. Select the function app from the list and click Select. This allows the function app access to my Azure DNS zone.

35. Click the button Review + Assign
36. Finally, I’ll be configuring the name servers for my domain cloudcrazy.co.uk so they point to my Azure DNS zone. Access the Azure DNS zone again and access the overview page.
I add the DNS name servers provided on the overview page to my new domain cloudcrazy.co.uk
Note: please don’t reconfigure name servers for a domain in production without prior planning. This could lead to downtime of your critical services. The domain I am using is currently not used for any production services.

37. I login to my domain registrar portal and add the 4 provided name servers from the Azure portal. This process delegates access, allowing me to control my public DNS for cloudcrazy.co.uk from within the Azure portal.
IMPORTANT: I am implementing this solution in a demo environment with a domain name I have registered, which is not used in production. Please be careful when implementing any new solution in production. Ensure you thoroughly research and understand what you’re deploying first.
I add the name servers to my domain by accessing the domain registrar portal.

38. That should be it. I’ll access my Azure Function app url again. No more DNS error.
39. Click Add

40. Click the DNS Zone drop down list. Great, the function app is able to view the domain from Azure DNS. Remember, I allowed permissions for the app to access my Azure DNS zone in step 30 above.

41. Now, it’s time to request for a cert from Let’s Encrypt. This is where we test if the client (Azure Function App) can connect to Let’s Encrypt and issue me a certificate which should automatically be stored in Azure Key Vault.
I request for a certificate for demo.cloudcrazy.co.uk

42. Click the Add button which appears next to the DNS Names field, and then click Add towards the bottom. See image below.

Advanced options allows you to modify the key size and add a custom certificate name if needed. I’ll be leaving the defaults.

43. Done. If successful the certificate details should appear as shown in the image below.

What happened in the background
The function app connected to Let’s Encrypt requesting for a TLS cert for demo.cloudcrazy.co.uk. Let’s Encrypt responds with instructions on what needs to be done in Azure DNS to verify that I own the domain. The Azure Function App adds a temporary dns record provided by Let’s Encrypt into my Azure DNS zone to complete the verification process. The Function App then returns to Let’s Encrypt to confirm the record has been added. Let’s Encrypt completes the verification check to confirm I own the domain cloudcrazy.co.uk, and issues the free TLS cert. The temporary record is then automatically deleted by the Azure Function App. This process took about 1 minute to complete and was completed automatically after I clicked the Add button in step 42.

The image above displays Unmanaged certificates and Another CA certificates.
Unmanaged Certificates: If you had certificates in your Azure Key Vault which were not created by the ACME bot, those certificates would appear under unmanaged certificates.
Another CA certificates: certificates issued by another CA (Certificate Authority) would appear here.
44. Click the details button and explore the options available.


As seen in the image above, I can manage the certificate from the client dashboard, including manually renewing or revoking the certificate. Also, because the function app has an API, I could automate the process without having to access the dashboard directly.
Where is the certificate stored?
45. Finally, let’s check if the certificate is visible in Azure Key Vault.
- I’ll access my Azure Key Vault, which was created as part of the deployment earlier.
- Inside Key Vault, click certificates from the left pane

46. You may receive the error below:
Error: The operation is not allowed by RBAC. If role assignments were recently changed, please wait several minutes for role assignments to become effective.

This permissions error indicates that my user accounts does not have the permissions to access certificates in Azure Key Vault. Let’s grant permissions by accessing Access control (IAM).

For the purpose of this demo, I am granting my account the role, Key Vault Administrator.
Note: there are other lower privileged Key Vault roles available.

47. Now that I have assigned my account permissions, let’s try that again.
The certificate is now visible to me in Azure Key Vault

48. Click the certificate and you’ll see one version. Go back to your Azure function app and click the button to renew the certificate, you’ll find another version of the certificate will automatically appear in your Azure Key Vault. Any apps connecting to your certs will automatically start to use the new version of the certificate upon renewal.


And the Azure Key Vault now shows the new version of the certificate.

49. Go ahead and request for a new certificate from within the Azure Function App dashboard. This time, I’ll input portal.cloudcrazy.co.uk and I’ll try a wild card of *.cloudcrazy.co.uk




Two additional certificates are now visible in Azure Key Vault as shown in the image below.

I hope you found this demo useful.