Using Azure linked templates in your infrastructure-as-code endeavors

Using a single template when deploying your infrastructure-as-code (IaC) is doable when you have a small piece of infrastructure for any given application. However, as you start leveraging more and more infrastructure-as-code to build your applications in the Azure cloud, you will realize that if you have building blocks for specific resources from the enterprise level, then your work would be much simpler. Using ARM templates, we can do exactly that — create building blocks that are reusable on all your projects, and those small templates will be used to deploy specific areas of our infrastructure. From your main template file, we can specify which templates we need to use to build our entire application. We can have the Azure template file in a separate file, and that is called a linked template, which is the goal of this article. However, we also can have another template within the main template, and that type of template is known as the nested template.

Infrastructure-as-code deployment: Using a simple scenario

We have a design that is comprised of several web apps and virtual network/subnets changes as part of one of our new applications. Our goal is to use infrastructure-as-code to deploy everything as fast and dynamic as possible.

We could create several times the web app and virtual network piece of code in a single template.json file and execute that in an Azure DevOps pipeline, and it would work. However, we want to create an elegant code and ARM templates to deliver in an organized and controlled way our new infrastructure and applications into Azure.

Our goal in this article is to create an ARM template called template.json, which will have the main code to deploy our application, and it will call other templates and use them as the building blocks to develop specific resources required by our application.


Variables section

The first change is to create a variable or parameter to receive more than one value. We will use those values with linked templates to provision all resources with a single and modular piece of code.

In this article, we are going to use the v_webAppArray variable, and we will use the name for all web apps that we want to deploy into that variable. In our example, we are defining two web apps: server01 and server02.

Using deployments

Besides the regular resource deployment where we define the type to match the resource that we are creating, we have the Microsoft.Resources/deployments (Item 1), which allows the cloud administrator to specify another template and pass parameters.

In the code below, we can define the resource group (Item 2) to execute the new template. This feature is useful when managing deployment across different resource groups.

The process of using a different template is described in Item 3. We are using the network.json file stored in my GitHub public repository.

The final portion of the code highlighted below is the parameters section. Those are the variables that we can pass to the template that we are defining in this current deployment.


You may be wondering what the differences are in that network.json file that we are calling from the main template, right? Just a simple and straightforward regular JSON file like all the other ones that we have been working on.

The secret is the Microsoft.Resources/deployment type defined in the main template. It is that simple. Just for the sake of transparency, we cleaned up the network.json, and the entire code (only one single subnet) is being listed in this section.

"$schema": "",
"contentVersion": "",
"parameters": {
"type": "string"
"defaultValue": "CaC",
"type": "string"
"type": "string"
"variables": {
"resources": [
"apiVersion": "2018-04-01",
"type": "Microsoft.Network/virtualNetworks/subnets",
"name": "[concat(variables('v_virtualnetworkName'),'/','Subnet-',parameters('regionCode'),'-',parameters('environment'),'-VPN')]",
"location": "[resourcegroup().location]",
"properties": {
"addressPrefix": "[concat('10.',parameters('p_SecondOctet'),'.5.0/28')]"
"outputs": {

Using Copy object and CopyIndex function

In the previous section, we had a simple setup — we call a template once and provide the parameters and of the deployment.

However, we can take advantage of that same process and use the Copy object to create a loop and deploy several resources using the same piece of code in the main template and the same linked template.

In the image below, we are looking at the template.json file, and that is just another entry in the resources section, nothing special.

Looking at Item 1, we can see that the name of the deployment will be the combination of the string linkedtemplate and the current index of the current loop started by the Copy object. The value will be an integer, and the value always starts in 0 (zero).

We are planning to have the web apps in the same resource group from where we are running the main template. To save time and avoid static code, we are using the function [resourcegroup().name], as shown in Item 2.

The Copy object is highlighted in Item 3. The use is simple — provide a name and the number of repetitions that we want to perform.

Our goal is to be dynamic, so instead of typing the specific number of future web apps, we are going to use the function length(variables(‘v_webappArray’)), which will be based on the number of values that we added to our variable.

The last piece of information is to pass the name of the web app that we want on each iteration. In the parameters section, we are using the function [variables(‘v_webAppArray’)[copyIndex()]], and that will pass the server name based on the current iteration.


For example, using the variable that we defined in the first section of this article, the length of the array would be two, and that will be the count number for the Copy object. The first iteration would send server01 and the second iteration would send server02 to the linked template.

Can deploying infrastructure-as-code be elegant? Oh, yes

In this article, we took a more elegant approach for medium-to-larger enterprises that are using ARM templates and infrastructure-as-code to improve their deployment lifecycle in the Azure cloud. Keep in mind that the Copy object can be used in several areas of ARM templates, and they are beneficial when we need to add dynamism to our infrastructure deployment process.

Featured image: Shutterstock

About The Author

Leave a Comment

Your email address will not be published. Required fields are marked *

This site is protected by reCAPTCHA and the Google Privacy Policy and Terms of Service apply.

Scroll to Top