Virtual Machine (ARM) template


Microsoft Azure, as one of the leading cloud computing providers, enables several different approaches one can take to create and manage resources within. From Azure Portal itself and Azure DevOps (f.k.a. Visual Studio Team Services) to PowerShell and Azure CLI, all of the above can use ARM templates for creating and updating desired resources on Azure.

Over the years official ARM (Azure Resource Manager) templates collection on GitHub has been growing and “azure-quickstart-templates” repository now contains more than 700 templates for deploying various types of resources that Azure offers. This rich repository gives a head start in most of the scenarios that one might encounter.

Azure Portal
Azure Portal – May 2019

The template

Working with Azure, I’ve noticed that occasionally I use several different ARM templates to create a simple (or at least not complex) environment. Merging multiple ARM templates into a single one could make things easier to manage. It is not so challenging to combine two or more ARM templates, but making the right choice of resources to include, while extending a template’s functionality, maintaining it’s flexibility and usability, certainly could be.

The ARM template that I have written and provided in this article can be used to create a virtual machine along with:

  • a custom virtual network with multiple custom subnets,
  • an access rule (network security group) for a virtual machine,
  • an availability set for a virtual machine,
  • a public IP address for a virtual machine,
  • a storage for boot diagnostics feature on a virtual machine.

Features included in the template:

  • ability to create a custom virtual network;
  • ability to create multiple custom subnets within a network;
  • ability to create additional virtual machines in an existing virtual network and subnet
  • ability to select an operating system (Windows or Ubuntu) for a virtual machine,
  • ability to specify desired virtual machine size,
  • ability to set a prefered disk type (SSD or HDD) for the operating system’s disk,
  • ability to choose whether to create an availability set for a virtual machine and to set prefered parameters for an availability set,
  • option to create a static public IP address for a virtual machine or not to create one,
  • ability to specify an IP address or a subnet that should be permitted to access the RDP or the SSH port on a virtual machine,
  • ability to set a custom username and password on a virtual machine,
  • ability to provide a public ssh key for authentication on a virtual machine (Ubuntu),
  • option to force ssh key as the only authentication method for the provided key,
  • boot diagnostics feature on a virtual machine.

To get this level of functionality out of a single ARM template, I needed to extend standard JSON format with ARM-specific functions and notation:

  • conditions,
  • a property (resource) loop,
  • string functions (concat, empty, length),
  • logical functions (if),
  • comparison functions (equals),
  • resource functions (resourceId).

Before you begin


  • Azure can bill your subscription for creating and utilising resources deployed by this template;
  • Use of resources deployed by this template, in a production environment, may require the implementation of additional security measures.

To use this template one should own:

  1. a Microsoft account,
  2. a subscription on Azure Portal (,
  3. an organisation on Azure DevOps ( or Azure CLI / PowerShell with access to a subscription where you want to create resources using the ARM template.

Parameter examples in this article are in a format that is compliant with Azure DevOps.

How to use the ARM template

The most convenient way to start creating virtual machines on Azure, using this template, is to submit it to a repository that you will use as the source for your Azure DevOps Pipeline. You can then create an “Azure Resource Group Deployment” job within your Pipeline. Upon selecting a prefered subscription, choose the “Create or update resource group” action, select a resource group and location for a virtual machine, and load the template on the job configuration page.

Opening the “Override template parameters” window will enable you to select desired options and set parameters for your new VM. Hovering over the info icon, on a parameter name, will bring an explanation popup. Confirm your selected and input parameters on the active window and then “Override template parameters” field will be populated accordingly.

Azure DevOps - Override Template Parameters
Azure DevOps – Override Template Parameters

Without loading the template’s parameter file on an “Azure Resource Group Deployment” job page, you can deploy a virtual machine with the default values by providing only a single parameter value.

-userPassword "password_that_meets_the_complexity_requirement"

Default parameter values will set a new virtual machine as a Windows Server 2016 DataCenter, Standard_B1s machine that uses HDD as an OS disk and has an availability set (with two Update Domains and two Fault Domains). By default, a VM will have a static public IP address allowing RDP connections from any IP address using “vm-user” and a provided password from the override parameter field. VM’s default virtual network is with a subnet.

-TemplateUsage "FirstVM" -vnetName "VNet" -vnetAddressPrefix "" -Subnets [{"name":"Subnet","prefix":""}] -publicIPaddress "Create" -accessAddressPrefix "*" -vmName "vm" -OS "Windows2016" -OSdisk "StandardHDD" -vmSize "Standard_B1s" -userName "vm-user" -userPassword "setpassword" -sshKey "" -sshKeyOnly "No" -availabilitySet "Create" -avSetUDcount "2" -avSetFDcount "2" -tags {"ProjectName":"Project"}

Adding another VM to subnet

Have in mind, if you plan to add additional VMs, that you should create all the subnets you may need in the future within your network the first time you are deploying this template to create a VM.
Parameters for adding additional VMs should have the following:

  • parameter “TemplateUsage” with “AdditionalVM” as value;
  • parameters “vnetName” and “vnetAddressPrefix” should have the same values as they had on the first template deployment (they should match an existing network in a resource group);
  • parameter “Subnets” should only contain a single subnet value (an existing subnet and the one where you want a new VM to be in).

The expected parameter values format

Here are examples of correct parameter values:

  • for the “Subnet” parameter, in a case that you want to create more than one subnet, repeat the subnet object within the array;
  • -Subnets [{"name":"first-subnet","prefix":""},{"name":"second-subnet","prefix":""},{"name":"third-subnet","prefix":""}]
  • for the “accessAddressPrefix” parameter, single IP value format is “x.x.x.x/32”;
  • for the “sshKey” parameter value format is “ssh-rsa XYZ…”

[Download] ARM VM template
[Download] ARM VM template (parameters file)

Filip Petronijevic Written by: Filip

System administrator - for more than ten years as an ...
Read more

Be First to Comment

Leave a Reply

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

This site uses Akismet to reduce spam. Learn how your comment data is processed.