This page could be helpful if you want to create virtual machines on Azure via Powershell, as we did to create our Office365 reference environment. With this, you could create your own test environment.

This page will guide you through a couple of steps to create a Windows Server 2016 virtual machine. Also we will show a way to create a Windows 10 client vm on Azure without a visual studio subscription, but with your own Windows 10 license key. Be aware that is (still) unsupported by Microsoft.

These steps will guide you through the process of creating the following components:

  • Resource group
    • You can use a resource group, to logically group related resources. In this case, we will place all of the machine components in the same resource group. You can find more information in the Azure documentation about resource groups.
  • Network components
    • You will need several network components for your virtual machine. We will show you, how you are able to create subnets, network interfaces and security rules.
  • Virtual machine configuration
    • This configuration is needed to create the virtual machine. The configuration exists of network components, images, VM sizing and so on.
  • Virtual machine
    • The virtual machine will be created, based on the virtual machine configuration that you created.
  • Windows 10 Ent VHD
    • We created a Prepare your VHD for Windows 10 guide, that will take you through the steps that are needed to create a Windows 10 Ent VHD to use on Microsoft Azure. There are specific steps to be taken, otherwise this won't work.
  • Storage account
    • You need to create a storage account on Microsoft Azure where you can store your VHD. This VHD will be stored on the so called blob storage. You can find more information in the Azure documentation about Azure storage.
  • Virtual machine backups
    • You might want to backup the VM(s). This step takes care of that.


Create a Windows Server 2016 virtual machine on Microsoft Azure

These steps will guide you through the process of creating a Windows Server 2016 virtual machine on Microsoft Azure with PowerShell.

Remember to enter all of the information for the requested parameters.

Step 1: Install and configure Azure PowerShell

Before you are able to connect to Microsoft Azure via PowerShell, you will need to install Azure Powershell. The steps below will guide you through this. First make sure you have the appropriate version of PowerShellGet:

PowerShellGet
Get-Module PowerShellGet -list | Select-Object Name,Version,Path

You should see something like this:

PowerShellGet Output
Name          Version Path
----          ------- ----
PowerShellGet 1.0.0.1 C:\Program Files\WindowsPowerShell\Modules\PowerShellGet\1.0.0.1\PowerShellGet.psd1


You will need elevated privileges to install Azure PowerShell. Run the following command to Install Azure PowerShell:

Install Azure PowerShell
# Install the Azure Resource Manager modules from the PowerShell Gallery
Install-Module AzureRM

You should see the following message:

Message
Untrusted repository

You are installing the modules from an untrusted repository. If you trust this repository, change
its InstallationPolicy value by running the Set-PSRepository cmdlet.

Are you sure you want to install the modules from 'PSGallery'?
[Y] Yes  [A] Yes to All  [N] No  [L] No to All  [S] Suspend  [?] Help (default is "N"): Y

Answer 'Yes' or 'Yes to All' to continue the installation

After the installation, you can import the Azure module in your PowerShell. This doesn't have to be done with elevated privileges:

Import-Module
Import-Module AzureRM

Step 2: Create a new resource group

Create a new resource group
$Environment = "AzureCloud"
$TenantId = "ADD YOUR TENANTID"
$SubscriptionId = "ADD YOUR SUBSCRIPTIONID"
$SubscriptionName = "ADD YOUR SUBSCRIPTION NAME"
$Location = "ADD YOUR LOCATION (we used westeurope)"
$ResourceGroupName = "ADD YOUR RESOURCEGROUP NAME"

#### Logon to Azure ####
Login-AzureRmAccount -TenantId $TenantId -SubscriptionId $SubscriptionId
Get-AzureRmSubscription -SubscriptionId $SubscriptionId -TenantId $TenantId 

#### Get All VM Images Publishers ####
Get-AzureRmVMImagePublisher -Location $Location

#### Get Microsoft VM Images ####
Get-AzureRmVMImageOffer -Location $Location -PublisherName "MicrosoftWindowsServer"

#### Get Windows Server Images ####
Get-AzureRmVMImageSku -Location $Location -PublisherName "MicrosoftWindowsServer" -Offer "WindowsServer"

#### Create New ResourceGroup on Azure ####
New-AzureRmResourceGroup -Name $ResourceGroupName -Location $Location

#### Check if the ResourceGroup is created ####
Get-AzureRmResourceGroup -ResourceGroupName $ResourceGroupName

Step 3: Create network components

Create network components
############################################# CREATE NETWORK COMPONENTS #############################################
$ServerSubnet = "ADD SUBNET (for example: 192.168.1.0/24)"
$ServerSubnetName = "ADD SUBNET NAME"
$ServerVnetName = "ADD VNET NAME"
$ServerVnetAddresPrefix = "ADD VNET ADDRESS PREFIX (for example: 192.168.0.0/16)"
$ServerAllocationMethod = "Static"
$ServerIdleTimeout = "4"
$ServerPublicDNSName = "ADD YOUR PUBLIC DNS NAME (For Example: Servermypublicdns$(Get-Random))"
$ServerNetworkSecGrpRDP = "ADD YOUR NETWORK SECURITY RULE NAME FOR RDP TRAFFIC"
$ServerNetworkSecGrpWWW = "ADD YOUR NETWORK SECURITY RULE NAME FOR WWW TRAFFIC"
$ServerNetworkSecurityGroupName = "ADD YOUR NETWORK SECURITY GROUP NAME"
$ServerPubNicName = "ADD YOUR PUBLIC NIC NAME"
 
Register-AzureRmResourceProvider -ProviderNamespace Microsoft.Network
 
#### Create a subnet configuration ####
$ServerSubnetConfig = New-AzureRmVirtualNetworkSubnetConfig -Name $ServerSubnetName -AddressPrefix $ServerSubnet
 
#### Create a virtual network ####
$ServerVnet = New-AzureRmVirtualNetwork -ResourceGroupName $ResourceGroupName -Location $Location -Name $ServerVnetName -AddressPrefix $ServerVnetAddresPrefix -Subnet $ServerSubnetConfig
 
#### Create a public IP address and specify a DNS name ####
$ServerPublicIp = New-AzureRmPublicIpAddress -ResourceGroupName $ResourceGroupName -Location $Location -AllocationMethod $ServerAllocationMethod -IdleTimeoutInMinutes $ServerIdleTimeout -Name $ServerPublicDNSName
 
#### Create an inbound network security group rule for port 3389 ####
$ServerNsgRuleRDP = New-AzureRmNetworkSecurityRuleConfig -Name $ServerNetworkSecGrpRDP  -Protocol Tcp -Direction Inbound -Priority 1000 -SourceAddressPrefix * -SourcePortRange * -DestinationAddressPrefix * -DestinationPortRange 3389 -Access Allow
 
#### Create an inbound network security group rule for port 80 ####
$ServerNsgRuleWeb = New-AzureRmNetworkSecurityRuleConfig -Name $ServerNetworkSecGrpWWW -Protocol Tcp -Direction Inbound -Priority 1001 -SourceAddressPrefix * -SourcePortRange * -DestinationAddressPrefix *  -DestinationPortRange 80 -Access Allow
 
#### Create a network security group ####
$ServerNetworkSecurityGroup = New-AzureRmNetworkSecurityGroup -ResourceGroupName $ResourceGroupName -Location $Location -Name $ServerNetworkSecurityGroupName -SecurityRules $ServerNsgRuleRDP,$ServerNsgRuleWeb
 
#### Create a virtual network card and associate with public IP address and NSG ####
$ServerPubNic = New-AzureRmNetworkInterface -Name $ServerPubNicName -ResourceGroupName $ResourceGroupName -Location $Location -SubnetId $ServerVnet.Subnets[0].Id -PublicIpAddressId $ServerPublicIp.Id -NetworkSecurityGroupId $ServerNetworkSecurityGroup.Id

Step 4: Create a virtual machine configuration

In this step, you will create the VM configuration that you will need to create the VM. Note that you will need several parameters from the previous step

VM Configuration
$ServerVMName = "ADD YOUR VM NAME"
$ServerVMSize = "ADD YOUR VM SIZE (For example: Standard_DS2)"
 
#### Define a credential object ####
$cred = Get-Credential

Register-AzureRmResourceProvider -ProviderNamespace Microsoft.Compute

#### Create a virtual machine configuration ####
$vmConfig = New-AzureRmVMConfig -VMName $ServerVMName -VMSize $ServerVMSize | Set-AzureRmVMOperatingSystem -Windows -ComputerName $ServerVMName -Credential $cred | Set-AzureRmVMSourceImage -PublisherName MicrosoftWindowsServer -Offer WindowsServer -Skus 2016-Datacenter -Version latest | Add-AzureRmVMNetworkInterface -Id $ServerPubNic.Id

Step 5: Create the virtual machine

In this step, you will create the actual virtual machine. Note that you will need several parameters from the previous steps

Create a virtual machine
$Location = "ADD YOUR LOCATION (we used westeurope)"
$ResourceGroupName = "ADD YOUR RESOURCEGROUP NAME"
 
#### Create a virtual machine ####
New-AzureRmVM -ResourceGroupName $ResourceGroupName -Location $Location -VM $vmConfig 

Create a Windows 10 virtual machine on Microsoft Azure, without a visual studio subscription

These steps will help you to create a Windows 10 virtual machine on Microsoft Azure. If you want to use the available Windows images on Azure, you will need a visual studio subscription. When you don't have a visual studio subscription, you could use these steps and the Prepare your VHD for Windows 10 guide. Note that this is unsupported by Microsoft.

Remember to enter all of the information for the requested parameters.

Step 1: Create the network components

In this step, you will create the network components for you Windows 10 client.

Create network components
$Environment = "AzureCloud"
$TenantId = "ENTER YOUR TENANTID"
$SubscriptionId = "ENTER YOUR SUBSCRIPTIONID"
$SubscriptionName = "ENTER YOUR SUBSCRIPTION NAME"
$Location = "ENTER YOUR LOCATION (we used westeurope)"
$ResourceGroupName = "ENTER YOUR RESOURCEGROUP NAME"

################################################## CREATE NETWORK COMPONENTS ##################################################
$ClientSubnetName = "ENTER YOUR SUBNET NAME"
$ClientVnetName = "ENTER YOUR VNET NAME"
$ClientVnetAddresPrefix = "ENTER YOUR VNET ADDRESS PREFIX (For example: 10.0.0.0/24)"
$ClientSubnet = "ENTER YOUR SUBNET (For example: 10.0.0.0/24)"
$ClientSubnetName = "ENTER YOUR SUBNET NAME"
$ClientAllocationMethod = "Static"
$ClientIdleTimeout = "4"
$ClientPublicDNSName = "ENTER YOUR PUBLIC DNS NAME (For example: Clientmypublicdns$(Get-Random))"
$ClientNetworkSecGrpRDP = "ENTER YOUR NETWORK SECURITY RULE NAME FOR RDP TRAFFIC"
$ClientNetworkSecGrpWWW = "ENTER YOUR NETWORK SECURITY RULE NAME FOR WWW TRAFFIC"
$ClientNetworkSecurityGroupName = "ENTER YOUR NETWORK SECURITY GROUP NAME"
$ClientPubNicName = "ENTER YOUR PUBLIC NIC NAME"
$ClientNicName = "ENTER YOUR NIC NAME"

Register-AzureRmResourceProvider -ProviderNamespace Microsoft.Network

#### Create a subnet configuration ####
$subnetConfig = New-AzureRmVirtualNetworkSubnetConfig -Name $ClientSubnetName -AddressPrefix $ClientSubnet

#### Create a virtual network ####
$vnet = New-AzureRmVirtualNetwork -ResourceGroupName $ResourceGroupName -Location $Location -Name $ClientVnetName -AddressPrefix $ClientVnetAddresPrefix -Subnet $subnetConfig

#### Create a public IP address and specify a DNS name ####
$pip = New-AzureRmPublicIpAddress -ResourceGroupName $ResourceGroupName -Location $Location -AllocationMethod $ClientAllocationMethod -IdleTimeoutInMinutes $ClientIdleTimeout -Name $ClientPublicDNSName

#### Create an inbound network security group rule for port 3389 ####
$nsgRuleRDP = New-AzureRmNetworkSecurityRuleConfig -Name $ClientNetworkSecGrpRDP  -Protocol Tcp -Direction Inbound -Priority 1000 -SourceAddressPrefix * -SourcePortRange * -DestinationAddressPrefix * -DestinationPortRange 3389 -Access Allow

#### Create an inbound network security group rule for port 80 ####
$nsgRuleWeb = New-AzureRmNetworkSecurityRuleConfig -Name $ClientNetworkSecGrpWWW  -Protocol Tcp -Direction Inbound -Priority 1001 -SourceAddressPrefix * -SourcePortRange * -DestinationAddressPrefix * -DestinationPortRange 80 -Access Allow

#### Create a network security group ####
$nsg = New-AzureRmNetworkSecurityGroup -ResourceGroupName $ResourceGroupName -Location $Location -Name $ClientNetworkSecurityGroupName -SecurityRules $nsgRuleRDP,$nsgRuleWeb

#### Create a virtual network card and associate with public IP address and NSG ####
$nic = New-AzureRmNetworkInterface -Name $ClientNicName -ResourceGroupName $ResourceGroupName -Location $Location -SubnetId $vnet.Subnets[0].Id -PublicIpAddressId $pip.Id -NetworkSecurityGroupId $nsg.Id

#### Define a credential object ####
$cred = Get-Credential

Step 2: Prepare your VHD on a (local) machine with Hyper-V Manager

This guide can be used to prepare a VHD on a (local) machine with Hyper-V Manager. This is (still) unsupported by Microsoft.

Step 3: Upload VHD and create VM image

In this step, you will create a new storage account, upload the prepared VHD and create a VM image. Note that you will need several parameters from the previous step.

Upload VHD and create VM image
################################################## UPLOAD VHD AND CREATE IMAGE ##################################################
$sourceVhd = "ENTER THE SOURCE VHD LOCATION (For example: C:\Users\Public\Documents\Hyper-V\Virtual hard disks\******.vhd)"
$destinationVhd = "ENTER THE DESTINATION (Looks like: https://******.blob.core.windows.net/vhd/*****.vhd)"
$NumberOfUploaderThreads = "5"
$StorageAccountName = "ENTER YOUR STORAGE ACCOUNT NAME"
$StorageAccountLabel = "ENTER YOUR STORAGE ACCOUNT LABEL"
 
#### Define a credential object ####
$cred = Get-Credential
 
#### Create storage account ####
New-AzureStorageAccount -StorageAccountName $StorageAccountName -Label $StorageAccountLabel -Location $Location
 
#### Upload VHD ####
Add-AzureRmVhd -LocalFilePath $sourceVHD -Destination $destinationVHD -ResourceGroupName $ResourceGroupName -NumberOfUploaderThreads $NumberOfUploaderThreads
 
#### Create Image from uploaded VHD ####
$storageAccountResourceId = "ENTER YOUR STORAGE ACCOUNT RESOURCE ID (Look like: /subscriptions/5abca34e-******-****-*****/resourceGroups/*******/providers/Microsoft.Storage/storageAccounts/*****)"
$diskName = "ENTER YOUR DISKNAME"
$diskSize = "ENTER DISK SIZE IN GB (For example: 35)"
$imageName = "ENTER IMAGE NAME"
$osType = "Windows"
$AccountType = "StandardLRS"

Select-AzureRmSubscription -SubscriptionId $SubscriptionId
 
#### Create Managed Disk in the target subscription using the VHD file in the source subscription ####
$diskConfig = New-AzureRmDiskConfig -AccountType $AccountType -Location $Location -CreateOption Import -SourceUri $destinationVhd -StorageAccountId $storageAccountResourceId -DiskSizeGB $diskSize
$osDisk = New-AzureRmDisk -DiskName $diskName -Disk $diskConfig -ResourceGroupName $ResourceGroupName
 
#### Create an image in the target subscription using the Managed Disk created in the same subscription ####
$imageConfig = New-AzureRmImageConfig -Location $Location
$imageConfig = Set-AzureRmImageOsDisk -Image $imageConfig -OsType $osType -OsState Generalized -ManagedDiskId $osDisk.Id
$image = New-AzureRmImage -ImageName $imageName -ResourceGroupName $ResourceGroupName -Image $imageConfig 
 
#### Delete the Managed Disk created in Step 1 ####
Remove-AzureRmDisk -ResourceGroupName $ResourceGroupName -DiskName $diskName

Step 4: Create the virtual machine based on the created image

In this step, you wil create the virtual machine based on the created image. Note that you will need several parameters from the previous steps.

Create virtual machine
$ClientVMName = "ENTER THE VM NAME"
$ClientVMSize = "ENTER THE VM SIZE (For example: Standard_DS2_v2)"
$DiskSizeInGB = "ENTER DISK SIZE IN GB (For example: 35)"

Register-AzureRmResourceProvider -ProviderNamespace Microsoft.Compute
$cred = Get-Credential

#### Set VM CONFIG ####
$vm = New-AzureRmVMConfig -VMName $ClientVMName -VMSize $ClientVMSize

#### SET IMAGE TO BE USED ####
$vm = Set-AzureRmVMSourceImage -VM $vm -Id $image.Id

#### SET VM CREATION PARAMETERS ####
$vm = Set-AzureRmVMOSDisk -VM $vm -DiskSizeInGB $DiskSizeInGB -CreateOption FromImage -Caching ReadWrite

#### SET VM OPERATING SYSTEM PARAMETERS ####
$vm = Set-AzureRmVMOperatingSystem -VM $vm -Windows -ComputerName $ClientComputerName -Credential $cred -ProvisionVMAgent -EnableAutoUpdate

#### SET VM NETWORK COMPONENTS ####
$vm = Add-AzureRmVMNetworkInterface -VM $vm -Id $ClientPubNicName.Id

#### CREATE VM ####
New-AzureRmVM -VM $vm -ResourceGroupName $ResourceGroupName -Location $location

#### CHECK IF THE VM IS PROVISIONED ####
$vmList = Get-AzureRmVM -ResourceGroupName $ResourceGroupName
$vmList.Name

Create a virtual machine backup in Microsoft Azure with PowerShell

After setting up a virtual machine, you probably want to make a backup. This step will set this up.

Create VM backup
################################################## CREATE VM BACKUP ##################################################
$RecoveryResourceVault = "ENTER BACKUP VAULT NAME"
$BackupPolicy = "ENTER BACKUP POLICY NAME"
$WorkloadType = "AzureVM"
$VM = "ENTER VM NAME"

Register-AzureRmResourceProvider -ProviderNamespace "Microsoft.RecoveryServices"

#### Create Backup vault ####
New-AzureRmRecoveryServicesVault -Name $RecoveryResourceVault -ResourceGroupName $ResourceGroupName -Location $Location

#### Set backup redundancy #### 
$Vault = Get-AzureRmRecoveryServicesVault -Name $RecoveryResourceVault
Set-AzureRmRecoveryServicesBackupProperties  -Vault $Vault -BackupStorageRedundancy LocallyRedundant
Get-AzureRmRecoveryServicesVault -Name $RecoveryResourceVault | Set-AzureRmRecoveryServicesVaultContext

#### Show available backup policies ####
Get-AzureRmRecoveryServicesBackupProtectionPolicy -WorkloadType $WorkloadType

#### Create a new backup policy with the default schedule and retention policy ####
$schPol = Get-AzureRmRecoveryServicesBackupSchedulePolicyObject -WorkloadType $WorkloadType
$retPol = Get-AzureRmRecoveryServicesBackupRetentionPolicyObject -WorkloadType $WorkloadType
New-AzureRmRecoveryServicesBackupProtectionPolicy -Name $BackupPolicy -WorkloadType $WorkloadType -RetentionPolicy $retPol -SchedulePolicy $schPol

#### Enable the backup ###
$pol=Get-AzureRmRecoveryServicesBackupProtectionPolicy -Name $BackupPolicy
Enable-AzureRmRecoveryServicesBackupProtection -Policy $pol -Name $VM -ResourceGroupName $ResourceGroupName
 
#### Adjust the backup retention policy ####
$retPol = Get-AzureRmRecoveryServicesBackupRetentionPolicyObject -WorkloadType $WorkloadType
$retPol.DailySchedule.DurationCountInDays = 30
$retPol.WeeklySchedule.DurationCountInWeeks = 4
$retPol.MonthlySchedule.DurationCountInMonths = 1
$retPol.YearlySchedule.DurationCountInYears = 1
$pol= Get-AzureRmRecoveryServicesBackupProtectionPolicy -Name $BackupPolicy
Set-AzureRmRecoveryServicesBackupProtectionPolicy -Policy $pol  -RetentionPolicy $RetPol

#### TRIGGER A BACKUP ###
#### RUN ONE AT A TIME! CHECK JOB STATUS BEFORE STARTING A NEW JOB ####
 
### Check running jobs ####
$joblist = Get-AzureRmRecoveryservicesBackupJob
$joblist[0]
 
#### Start backupjob ####
$namedContainer = Get-AzureRmRecoveryServicesBackupContainer -ContainerType $WorkloadType -Status "Registered" -FriendlyName $VM
$item = Get-AzureRmRecoveryServicesBackupItem -Container $namedContainer -WorkloadType $WorkloadType
$job = Backup-AzureRmRecoveryServicesBackupItem -Item $item