Throughout this series, I'm going to show how an Azure Functions instance can map APEX domains, add an SSL certificate and update its public inbound IP address to DNS.
- 3 Ways Mapping APEX Domains to Azure Functions
- Adding Let's Encrypt SSL Certificate to Azure Functions
- Updating Azure DNS and SSL Certificate on Azure Functions via GitHub Actions
- Deploying Azure Functions via GitHub Actions without Publish Profile
Let's say there is an Azure Functions instance. One of your customers wants to add a custom domain to the Function app. As long as the custom domain is a sub-domain type like api.contoso.com
, it shouldn't be an issue because CNAME mapping is supported out-of-the-box. But what if the customer wants to add an APEX domain?
Both APEX domain and root domain point to the same thing like
contoso.com
.
Adding the root domain through Azure Portal can't be accomplished with the message above. To add the APEX domain to Azure Functions instance, it requires an A record that needs a public IP address. But Azure Functions instance doesn't support it via the portal.
Should we give it up now? Well, not really.
As always, there's a way to get around. Throughout this post, I'm going to show how to map the APEX domain to an Azure Functions instance in three different ways.
Verifying Domain Ownership
First of all, you need to verify the domain ownership at the Custom Domains
blade of the Function app instance.
- Get the
Custom Domain Verification ID
at the picture above. - Add the TXT record,
asuid.contoso.com
, to your DNS server. - Add the A record with the IP address to your DNS server.
The verification process can be done via the portal.
If you want to run the verification with Azure CLI, please have a look at the link.
Now, you've verified the domain ownership. But you haven't still yet made the APEX domain mapping.
1. Through Azure PowerShell
If you can't make it through Azure Portal, Azure PowerShell will be one alternative. Use the Set-AzWebApp
cmdlet to map your APEX domain.
$resourceGroupName = "<RESOURCE_GROUP_NAME>" | |
$functionAppName = "<FUNCTION_APP_NAME>" | |
$domainName = "contoso.com" | |
Set-AzWebApp ` | |
-ResourceGroupName $resourceGroupName ` | |
-Name $functionAppName ` | |
-HostNames @( $domainName, "$functionAppName.azurewebsites.net" ) |
When you use Azure PowerShell, you MUST make sure one thing. The -HostNames
parameter specified above MUST include the existing domain names (line #7). Otherwise, all existing domains will be removed, and you will get the warning like below:
If you add all custom domains including the default domain name like *.azurewebsites.net
, you will be able to see the screen below:
2. Through Azure CLI
If you prefer to using Azure CLI, use the command, az functionapp config hostname add
.
az functionapp config hostname add \ | |
-g <RESOURCE_GROUP_NAME> \ | |
-n <FUNCTIONAPP_NAME> \ | |
--hostname "contoso.com" |
Unlike Azure PowerShell, you can add one hostname at a time and won't lose the ones already added.
3. Through ARM Template
You can also use ARM Template instead of command-line commands. Here's the bicep code for it (line #5-8).
resource fncapp 'Microsoft.Web/sites@2020-06-01' = { | |
name: functionApp.name | |
... | |
} | |
resource fncappHostname 'Microsoft.Web/sites/hostNameBindings@2020-06-01' = { | |
name: '${fncapp.name}/contoso.com' | |
location: fncapp.location | |
} |
When the bicep file is compiled to ARM Template, it looks like:
{ | |
... | |
"resources": [ | |
... | |
{ | |
"type": "Microsoft.Web/sites/hostNameBindings", | |
"apiVersion": "2020-06-01", | |
"name": "[format('{0}/{1}', variables('functionApp').name, 'contoso.com')]", | |
"location": "[variables('functionApp').location]", | |
"dependsOn": [ | |
"[resourceId('Microsoft.Web/sites', variables('functionApp').name)]" | |
] | |
}, | |
... | |
] | |
... | |
} |
So far, we've used three different ways to map an APEX domain to Azure Functions instance. Generally speaking, it's rare to map a custom domain to an Azure Functions instance. It's even rarer to map the APEX domain. Therefore, the Azure Portal doesn't support this feature. However, as we already saw, we can use either Azure PowerShell or Azure CLI, or ARM templates to add the root domain. I hope this post helps if one of your clients' requests is the one described in this post.
In the next post, I'll discuss how to bind a Let's Encrypt generated SSL certificate to the custom APEX domain on Azure Function app.