Create an Azure Virtual Machine Using a Customized Virtual Hard Disk


file copy featured

In this article found on, I showed you how to copy a virtual hard disk (VHD). In today’s Ask the Admin, I will show you how to attach a VHD to a new Azure virtual machine (VM).



When provisioning a new VM in the Azure management portal, you will find the option to select which OS to deploy from the Azure gallery. A pre-configured OS disk cannot be attached. It is possible to attach a customized VHD to a VM using PowerShell. In Deploy VMs Using Azure Resource Manager and PowerShell on Petri, you will see how to deploy a Resource Manager (ARM) VM. As part of the script, I defined a variable ($osSKU) to specify which OS image to use for the deployment.

The script uses the Set-AzureRmVMOSDisk cmdlet to set the OS disk for the new VM, as well as these two other cmdlets, Set-AzureRmVMOperatingSystem and Set-AzureRmVMSourceImage. Use these to set the image to install on the OS disk. If we have a custom VHD that we would like to use for the VM’s OS disk, then the same script can be used to provision the VM. Remove the previous two cmdlets and modify Set-AzureRmVMOSDisk to point to an existing VHD.

The original code looks like this:

Set-AzureRmVMOperatingSystem -Windows -VM $newVM -ProvisionVMAgent -EnableAutoUpdate -Credential $creds -ComputerName $vmname 

Set-AzureRmVMSourceImage -VM $newVM -PublisherName $images[0].PublisherName -Offer $images[0].Offer -Skus $images[0].Skus -Version $images[0].Version 

Set-AzureRmVMOSDisk -VM $newVM -Name $disknameOS -VhdUri $vhduri -Caching ReadWrite -CreateOption fromImage

We can remove Set-AzureRmVMOperatingSystem and Set-AzureRmVMSourceImage. Manually set the $vhduri variable to the URI of the VHD we want to use and modify the Set-AzureRmVMOSDisk as shown below:  

$vhduri = ""

Set-AzureRmVMOSDisk -VM $newVM -Name $disknameOS -VhdUri $vhduri -CreateOption Attach -Windows -Caching ReadWrite

The specialized VHD is from an existing VM, which means that user accounts, applications, and other state data from the original VM are maintained.

Network Security Group

Another option that I did not originally include, allows you to add code to create a Network Security Group (NSG). You can also include a security exception to allow inbound RDP. When ARM VMs are provisioned using the Azure management portal, NSGs are also created. For more information on NSGs, see Configuring Network Security Groups in Microsoft Azure on Petri.

$nsgName = ‘myNsg’

$rdpRule = New-AzureRmNetworkSecurityRuleConfig -Name myRdpRule -Description ‘Allow RDP’ -Access Allow -Protocol Tcp -Direction Inbound -Priority 110 -SourceAddressPrefix Internet -SourcePortRange * -DestinationAddressPrefix * -DestinationPortRange 3389

$nsg = New-AzureRmNetworkSecurityGroup -ResourceGroupName $rgName -Location $location -Name $nsgName -SecurityRules $rdpRule

We looked at how to change the PowerShell script in this article on Petri. This will help you to provision a VM in Azure with a customized VHD.