Microsoft Azure Documentation

Create a Windows Virtual Machine with an ARM Template

This guide walks you through creating a Windows Virtual Machine (VM) in Azure using an Azure Resource Manager (ARM) template. ARM templates allow you to define your infrastructure as code, enabling consistent and repeatable deployments.

Prerequisites

Understanding the ARM Template

An ARM template is a JavaScript Object Notation (JSON) file that defines the infrastructure for your solution. It typically includes:

Example ARM Template for a Windows VM

Below is a simplified ARM template to deploy a Windows Server 2019 Datacenter VM. You can save this as azuredeploy.json.


{
  "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",
  "contentVersion": "1.0.0.0",
  "parameters": {
    "vmName": {
      "type": "string",
      "defaultValue": "myWindowsVM",
      "metadata": {
        "description": "Name of the Windows virtual machine."
      }
    },
    "adminUsername": {
      "type": "string",
      "defaultValue": "azureuser",
      "metadata": {
        "description": "Administrator username for the virtual machine."
      }
    },
    "adminPassword": {
      "type": "securestring",
      "metadata": {
        "description": "Administrator password for the virtual machine."
      }
    },
    "vmSize": {
      "type": "string",
      "defaultValue": "Standard_DS1_v2",
      "allowedValues": [
        "Standard_DS1_v2",
        "Standard_DS2_v2",
        "Standard_B1s"
      ],
      "metadata": {
        "description": "Size of the virtual machine."
      }
    },
    "location": {
      "type": "string",
      "defaultValue": "[resourceGroup().location]",
      "metadata": {
        "description": "Location for the virtual machine."
      }
    }
  },
  "variables": {
    "nicName": "[concat(parameters('vmName'), '-nic')]",
    "vnetName": "[concat(parameters('vmName'), '-vnet')]",
    "subnetName": "[concat(parameters('vmName'), '-subnet')]",
    "publicIpName": "[concat(parameters('vmName'), '-publicip')]",
    "osDiskName": "[concat(parameters('vmName'), '-osdisk')]",
    "networkSecurityGroupName": "[concat(parameters('vmName'), '-nsg')]"
  },
  "resources": [
    {
      "type": "Microsoft.Network/virtualNetworks",
      "apiVersion": "2020-11-01",
      "name": "[variables('vnetName')]",
      "location": "[parameters('location')]",
      "properties": {
        "addressSpace": {
          "addressPrefixes": [
            "10.0.0.0/16"
          ]
        },
        "subnets": [
          {
            "name": "[variables('subnetName')]",
            "properties": {
              "addressPrefix": "10.0.0.0/24"
            }
          }
        ]
      }
    },
    {
      "type": "Microsoft.Network/publicIpAddresses",
      "apiVersion": "2020-11-01",
      "name": "[variables('publicIpName')]",
      "location": "[parameters('location')]",
      "properties": {
        "dnsSettings": {
          "domainNameLabel": "[concat(parameters('vmName'), '-dns')]"
        },
        "publicIPAllocationMethod": "Static"
      }
    },
    {
      "type": "Microsoft.Network/networkSecurityGroups",
      "apiVersion": "2020-11-01",
      "name": "[variables('networkSecurityGroupName')]",
      "location": "[parameters('location')]",
      "properties": {
        "securityRules": [
          {
            "name": "RDP",
            "properties": {
              "priority": 1000,
              "access": "Allow",
              "direction": "Inbound",
              "protocol": "Tcp",
              "sourcePortRange": "*",
              "destinationPortRange": "3389",
              "sourceAddressPrefix": "*",
              "destinationAddressPrefix": "*"
            }
          }
        ]
      }
    },
    {
      "type": "Microsoft.Network/networkInterfaces",
      "apiVersion": "2020-11-01",
      "name": "[variables('nicName')]",
      "location": "[parameters('location')]",
      "dependsOn": [
        "[resourceId('Microsoft.Network/virtualNetworks', variables('vnetName'))]",
        "[resourceId('Microsoft.Network/publicIpAddresses', variables('publicIpName'))]",
        "[resourceId('Microsoft.Network/networkSecurityGroups', variables('networkSecurityGroupName'))]"
      ],
      "properties": {
        "ipConfigurations": [
          {
            "name": "ipconfig1",
            "properties": {
              "subnet": {
                "id": "[resourceId('Microsoft.Network/virtualNetworks/subnets', variables('vnetName'), variables('subnetName'))]"
              },
              "publicIPAddress": {
                "id": "[resourceId('Microsoft.Network/publicIpAddresses', variables('publicIpName'))]"
              }
            }
          }
        ],
        "networkSecurityGroup": {
            "id": "[resourceId('Microsoft.Network/networkSecurityGroups', variables('networkSecurityGroupName'))]"
        }
      }
    },
    {
      "type": "Microsoft.Compute/virtualMachines",
      "apiVersion": "2020-12-01",
      "name": "[parameters('vmName')]",
      "location": "[parameters('location')]",
      "dependsOn": [
        "[resourceId('Microsoft.Network/networkInterfaces', variables('nicName'))]"
      ],
      "properties": {
        "hardwareProfile": {
          "vmSize": "[parameters('vmSize')]"
        },
        "storageProfile": {
          "imageReference": {
            "publisher": "MicrosoftWindowsServer",
            "offer": "WindowsServer",
            "sku": "2019-Datacenter",
            "version": "latest"
          },
          "osDisk": {
            "createOption": "FromImage",
            "name": "[variables('osDiskName')]"
          }
        },
        "osProfile": {
          "computerName": "[parameters('vmName')]",
          "adminUsername": "[parameters('adminUsername')]",
          "adminPassword": "[parameters('adminPassword')]"
        },
        "networkProfile": {
          "networkInterfaces": [
            {
              "id": "[resourceId('Microsoft.Network/networkInterfaces', variables('nicName'))]"
            }
          ]
        }
      }
    }
  ],
  "outputs": {
    "publicIpAddress": {
      "type": "string",
      "value": "[reference(resourceId('Microsoft.Network/publicIpAddresses', variables('publicIpName'))).ipAddress]"
    },
    "vmName": {
      "type": "string",
      "value": "[parameters('vmName')]"
    }
  }
}
        
Important: For production environments, consider using more secure methods for handling credentials, such as Azure Key Vault. The password parameter is marked as securestring, which means it should be handled securely during deployment.

Deploying the ARM Template

You can deploy the ARM template using Azure CLI or Azure PowerShell.

Using Azure CLI

Save the template above as azuredeploy.json. Then, run the following command in your terminal:


az deployment group create \
  --name MyVMDeployment \
  --resource-group YourResourceGroupName \
  --template-file azuredeploy.json \
  --parameters vmName=myTestVM adminUsername=testuser adminPassword='YourSecurePasswordHere!'
        

Replace YourResourceGroupName with the name of your Azure resource group and 'YourSecurePasswordHere!' with a strong password.

Using Azure PowerShell

Save the template above as azuredeploy.json. Then, run the following command:


New-AzResourceGroupDeployment `
  -Name "MyVMDeployment" `
  -ResourceGroupName "YourResourceGroupName" `
  -TemplateFile "azuredeploy.json" `
  -vmName "myTestVM" `
  -adminUsername "testuser" `
  -adminPassword "YourSecurePasswordHere!"
        

Replace YourResourceGroupName with the name of your Azure resource group and "YourSecurePasswordHere!" with a strong password.

Next Steps

For more detailed information and advanced configurations, refer to the full Azure VM documentation.