Azure, Azure Resource Manager, Azure Stack
comments 5

Building Azure Resource Manager Templates – Using Linked Templates

One of the ARM template authoring best practices is to decompose the JSON template, if applicable, into multiple target-specific templates. Think of this as creating re-usable code. You can leverage the re-usable parts of your code within multiple aspects of your application or the deployment.

For linking different external templates within the main template, we need to define the Microsoft.Resources/deployments resource instance. Before we proceed let us look at the scenario for which we are building an ARM template.


So far in this series, we have looked at building an ARM template that deploys the following components of this scenario:

  • A storage account
  • A virtual network
  • A public IP address
  • A load balancer
  • Virtual network interfaces for the DC and other VMs based on the environment type.
  • Finally, a VM with DNS and Directory Services running in it.

dnsBy default, the Azure based IaaS deployments use the Azure DNS. If you have deployed the template that we built in the previous part of this series, you will notice that the virtual network us configured to use Azure DNS.

Since we deployed a VM that runs our own DNS and directory services, we now want to use the custom DNS in the Azure deployment so that other VMs in the deployment can join the domain that we created using the PowerShell DSC configuration.

For this, we will use an external template and call it inside our main template. What we essentially need to do here is to update the existing virtual network to use the custom DNS. Here is how it looks.

The above template is just another ARM JSON template. It has the same syntax. We have defined parameters that are needed for updating the virtual network to use the custom DNS that we just configured. let us save this as vnet-with-dns-server.json and store it at a location that is accessible to the ARM deployment engine. I chose to store it in a public Github repository.

Now, we need to link this template to the main ARM template that we have been authoring. Here is how it is done in the main template.

Within this resource instance, we defined a dependency (line number 6) on the PowerShell DSC extension that creates the AD forest. We don’t want the linked template to execute until the DNS service is created in the DC VM. Line number 11 defines the link our external template that will configure the custom DNS settings. vnet-with-dns-server.json has a few parameters defined for collecting required custom DNS configuration.

Within the main template, we need to pass the parameter values to the external template. This is done using the parameters element within the Microsoft.Resources/deployments resource instance. For the parameter values, we use either what is already gathered from the user using the main template or what is defined in the variables element of the main template. This is how state can be shared between multiple templates. If we need to return some data from the linked template to the main template, we can do so using the outputs element within the linked template. In our scenario, we don’t need any information from the linked template and therefore we will not use the outputs element.

Also, notice line number 9. The mode property within the properties element is set to incremental. This is needed because we already have some of the components within the template deployed. By setting the deployment mode to incremental, we tell the deployment engine to add the new resources or update existing resource configuration within the resource group without deleting any existing resources in the group. In our example, we are updating the configuration of an existing virtual network to use the custom DNS. so, the incremental deployment mode is necessary here.

updatednsOnce you deploy this updated template, you will see that the virtual network within the resource group gets set to use the custom DNS deployed using the PowerShell DSC extension.

In the next part of this series, we will look at adding more virtual machines to the deployment based on the environmentType selected within the template parameters. By the end of next part, we will completely functional ARM template that deploys our scenario end to end.

Filed under: Azure, Azure Resource Manager, Azure Stack


Ravikanth is a principal engineer and the lead architect for Microsoft and VMware virtualized and hybrid cloud solutions within the Infrastructure Solutions Group at Dell EMC. He is a multi-year recipient of Microsoft Most Valuable Professional (MVP) award in Windows PowerShell (CDM) and Microsoft Azure. Ravikanth is the author of Windows PowerShell Desired State Configuration Revealed (Apress) and leads Bangalore PowerShell and Bangalore IT Pro user groups. He can be seen speaking regularly at local user group events and conferences in India and abroad.

  • Manimaran

    From the above blog you mentioned “I chose to store it in a public Github repository”. , Can we choose to store as a relative path from the master template file? or in a internal repo instead of public repo?


  • @Manimaran, you can use relative path but then you need to ensure that the ARM engine understands that by building the complete path. We cannot use private Github repo at the moment.

  • Wessel Kranenborg

    Hi Mani,

    Did you find out if this is possible? I’m also looking for this.

    Thanks, Wessel

  • There is no private Github repo support at the moment. There is no known way of using a storage account too unless the blob URL is public.

  • A workaround could be to use a Github token in KeyVault and then refer to an absolute URL by pulling that token in the template. I will try and write a post on this soon.