Get ready for pain.
I assume you’ve already done this:
- Created a static blog from an Azure Storage account
- Hooked up Azure CDN to it.
- Tried to enable a managed HTTPS cert for a custom domain that happens to be a naked/apex domain - eg. “tagisow.dev” instead of “www.tagisow.dev”
Since Azure won’t generate this for you, YOU WILL HAVE TO set up additional Azure resources to automate generating the cert for you. To bring you some relief - somebody already made an Azure blueprint for this.
What you’re trying to do is possible, and it works on this domain that you’re reading this on. It’s easy, but time consuming. Keep reading :)
1. Automating generating a cert for an apex domain
Go to https://github.com/shibayan/keyvault-acmebot#deployment and click the leftmost blue “Deploy to Azure button” This will spawn ~7 Azure resources. The FAQ of this repo says that running this costs $0.01 - https://github.com/shibayan/keyvault-acmebot/wiki/Frequently-Asked-Questions#how-much-does-azure-cost
In the deployment screen after clicking the blue deploy button, I didn’t have to change any defaults. Just keep pressing next and wait for the deployment to finish.
Unfortunately, there are a few things you need to do manually in the Azure portal after you finish.
In general the guide at https://github.com/shibayan/keyvault-acmebot/wiki/Getting-Started is good but it doesn’t hold your hand very much, so I will sprinkle some handholding here.
I didn’t have to do this step. Every setting mentioned there was prefilled of the box after the deploying with the blue button.
- IMPORTANT! You must do this to get a cert!
This is a step where you have to configure the acme bot you just deployed to allow you to modify your DNS records. It’s required for proving to the Certificate Authority that you control the domain (CAs give challenges like “ha, if you really control the domain then put this DNS record on the domain and I’ll check if you put it there”)
The supported DNS providers are here:
The domain you’re reading (tagisow.dev) is on Namecheap, and in the above list Namecheap DNS is not supported. Because of this, I set up an Azure DNS resource ($0.50/mo, this is the most expensive resource for a static blog) and then pointed Namecheap to my new Azure DNS nameserver. To summarize: my domain stayed on Namecheap, but I only told the domain to use my new Azure DNS zone instead of Namecheap’s default one. I used this tutorial https://www.namecheap.com/support/knowledgebase/article.aspx/767/10/how-to-change-dns-for-a-domain/
YOU MUST SET THE Acmebot:AzureDns:SubscriptionId SETTING MANUALLY OR YOU WON’T GET THE CERT
To set the setting, search “Function App” in the Azure portal. Click the function that the blueprint created for you. For me it’s “func-tsvdev-xjhj”. On the left bar, click “Configuration” (it’s in the “Settings” header/category).
The value for that setting should just be your Azure subscription id (the one where you that you link resources to to pay for things) where the DNS zone is. Most likely you have just one subscription - you can search “Subscription” in the portal search bar, go to that panel and just copy the subscription id.
REMEMBER TO CLICK THE DISKETTE ICON IN THE HEADER OF THE Configuration PAGE TO SAVE THE NEW SETTING
If you hard refresh and your new setting disappeared, you forgot to save :)
This is pretty straightforward. The screenshot in the FAQ has 2 functions showing but you’ll have just one.
No explanation necessary. It’s a required step.
- Accessing the Web UI
Now look very closely at the name of the Function App whose settings you were just changing. Again, for me, it’s “func-tsvdev-xjhj”
Go to “[functionname].azurewebsites.net/dashboard”.
Here I got some “DNS Zone is not configured” errors because I skipped step no. 2 like a dumbass, but hopefull you followed it.
In the top right, click “add”. Select your Azure DNS Zone (or other if you configured another with acmebot) from the dropdown.
In the DNS Names, just leave the “Record name” input empty, and click THE BLUE ADD BUTTON, NOT THE GREEN ADD BUTTON. After that, click the green add button.
After you add it, the bot should generate a certificate for you. So now you’ve basically done what Azure didn’t want to do for you - generate a cert for an apex domain.
2. Making the CDN custom domain use the new ACME cert
Sigh. Unfortunately this is a painful step aswell. If you go back to the Azure CDN view where you tried to get get a CDN managed cert for HTTPS and it didn’t let you, you’ll see that there’s a “Use my own certificate” radio button there.
When you deployed the acme bot, it created a key vault for you where it’ll store the generated certificates. After clicking the “Use my own certificate” radio, a “Key vault” input box appears where you should select that vault.
THE PROBLEM IS you won’t be able to select a certificate from the key vault you picked because by default, you don’t have permission to read secrets (such as certificates). YOU CAN’T READ SECRETS BY DEFAULT EVEN IF YOU ARE YOUR AZURE INSTANCE’s ADMIN
You’ll get a yellow bar at the top saying you don’t have permissions. Even the blue instructions above the key vault dropdown box will tell you to run some commands but THEY DON’T WORK. If you already ran them and saw that they don’t work there’s no real need to clean up anything (it just adds a “Contributor” role for the hidden Azure CDN user in your Subscription’s IAM (you can see that in the portal there)).
The solution to this is:
- Go to the acme bot’s keyvault in the portal
- go to it’s “Access Control (IAM)” tab in the sidebar on the left
- click “add role assignment” on the right
- search for the “Key Vaults Secrets User” - make sure you picked Key Vault Secrets User, not sure if Key Vault Secrets Officer works. I’ve used Key Vault Secret User.
- In the “members” tab, give the permission to YOURSELF. Tbh I’ve added so many roles to both myself and the hidden Microsoft.AzureFrontDoor-Cdn user that there may be some additional roles needed here.
If something doesn’t work here, maybe try giving the Secrets User role to the hidden Microsoft.AzureFrontDoor-Cdn user aswell? The user is hidden because you need to put the full name (or at least a large part of it) in the “Members” tab search box in order for it to show up
- Go back to the Azure CDN Custom domain where you previously had permissions issues. Select they key vault, and then select the certificate (this is the same one that you can see in the Function App website).
Now your own cert will be loaded into the CDN domain, and now typing in https://[your domain without www].[your tld suffix] should work - of course only if you added the apex domain record to Azure DNS.
If you forgot about that:
- go to Azure DNS in the portal
- click your DNS zone
- click “+ Record set” in the header of the page.
- In the sidebar that appears on the right, leave the “Name” input empty (or you can put “@” there - Azure will replace the empty input to ’@’ if you leave it empty)
The record type should be “A - Alias record to IPv4 address”
Alias record set should be “Yes”
In the “Azure resource” dropdown, select your Azure CDN resource
- Wait for the DNS to propagate (<1 min for me), then try to visit your site without www. :)
What a journey. This was much easier on AWS.