Deploying a Virtual Machine
Start course

In this course, I’ll start with an overview of Azure Resource Manager templates. Then I’ll show you how to build a template from scratch and deploy an Azure Storage account with it. Next, I’ll show you how to use a template to deploy a virtual machine, which is a more complicated resource. After that, I’ll explain how to make your templates more usable by adding parameters and variables. Finally, I’ll show you how to make your templates more sophisticated by using functions.

Learning Objectives

  • Describe the structure of Azure Resource Manager templates
  • Build an ARM template and use it to deploy a resource
  • Use an ARM template to deploy a virtual machine
  • Use parameters and variables in an ARM template
  • Use functions in an ARM template

Intended Audience

  • Azure administrators and developers


  • Basic knowledge of Azure Virtual Machines, Azure Storage, and Azure Virtual Networks

An ARM template that can deploy a virtual machine requires a lot more details than a template for a storage account does because it needs to include not only the VM but all of its supporting resources as well, such as an operating system disk and a network interface. Fortunately, the ARM extension in VS Code will still fill in most of the details for you.

Let’s create a new template and call it “vm.json”. Then type “arm” and select the first option. Now put the cursor in between the square brackets in the resources section and type “vm”. Let’s choose a Windows VM.

It added a bunch of different resources. First, there’s a storage account. Why? Because the operating system disk needs to be in a storage account. Next is a public IP address. Then there’s a network security group. This will be attached to the virtual network, which is the next resource. You can see that it has a dependsOn element saying that the virtual network depends on the existence of the network security group. The subnet is down here, and this is what references the network security group.

Then we have the network interface. It depends on the public IP address and the virtual network. And finally, we have the virtual machine. It depends on the storage account and the network interface.

So this is quite a complicated template because it has so many interconnected pieces, but the great thing is that the ARM extension in VS Code took care of all of this for us. Even better, it gives you a way to see all of these interconnections. In the View menu, select “Command Palette”, and then type “arm viewer”. When you select that, it brings up this nice diagram showing how these resources fit together.

I’m going to change the VM name to “catestVM1”.

Okay, bear in mind that the ARM extension in VS Code didn’t fill in everything you might need for a VM, so you might have to add some extra properties or resources. For example, if you wanted this VM to run a script that installs some additional software after it gets deployed, then you’d need to add a Custom Script Extension resource.

To do that, you’d go down to the last curly brace in the resources section, and add a comma and an opening curly brace. Then, if you type “extension”, it comes back with a list of possibilities. Since this is a Windows VM, we’ll choose “arm-vm-script-windows”. There are some values that need to be filled in, of course, such as this one. It’s where you put in the command to execute after the VM starts up. This is the name of the script file over here.

We’re not actually going to configure this. I just wanted to show it to you. I’ll hit the undo key until we get back to where we were. There.

All right, now we just need to take care of one more detail before we deploy this. In the virtual machine’s properties, there’s one called “osProfile” that includes the administrator’s username and password. We can leave all of the other values in this template with the defaults, and it will work fine, but we have to change the password. If we don’t we’ll get an error because this password doesn’t meet the requirement of having a numeric digit or a special character. Of course, it’s also a really bad password, so we should change it anyway.

However, before we do that, I should mention that we shouldn’t be putting the password in this file at all because that’s a security risk. If we were creating a Linux VM, then we could use an SSH key instead of a password. But that’s not an option with a Windows VM, so we have to do something else.

The preferred solution is to put the password in an Azure Key Vault and then make a reference to it in the template. Here’s what that would look like. Instead of putting in the plaintext password, we use the “reference” keyword and specify the key vault ID and the secret name. This reference will return the password from the key vault.

It would take a while to show you how to set all of this up, so instead, I’ve included a link to a tutorial in the transcript below (

For this example, I’ll just put in a password, which I definitely don’t recommend doing in a production environment. I’ll change it to “Don’tusethis1”. And save the file.

Now we can deploy it. Go into the Terminal menu and select “New Terminal”. Then type the same command as before but change the template file to “vm.json”.

It’s done. I’ll go back to the portal to check on it. There’s the VM and all of its supporting resources, so it worked.

About the Author
Learning Paths

Guy launched his first training website in 1995 and he's been helping people learn IT technologies ever since. He has been a sysadmin, instructor, sales engineer, IT manager, and entrepreneur. In his most recent venture, he founded and led a cloud-based training infrastructure company that provided virtual labs for some of the largest software vendors in the world. Guy’s passion is making complex technology easy to understand. His activities outside of work have included riding an elephant and skydiving (although not at the same time).