This article will show you step-by-step instructions on how to migrate a single physical server to Azure VM.

This is a possible scenario where you can use these step-by-step instructions.

  • Small Business which  has a single Small Business Server
  • Single Web server sitting in a rack which is hosted with some ISP
  • Any other scenario where is difficult to set up a second Windows 2012 R2 to be a configuration server to use Azure Recovery Services Vault

We can also use Azure Recovery Services Vault,  but that will require the setup of another configuration server to manage migration which in many cases is impossible.

Here is the requirement for Recovery Services Vault

Instead of using Recovery Services Vault, we will use the free Disk2VHD tool to convert the server to VHD file and use Add-AzureRmVhd PowerShell to upload the file to Azure.


  • Azure Subscription
  • Free Disk2VHD tool
  • External USB drive
  • Access to the Internet from the host system

System Hosted On-premise

  • Windows 2008 R2 Server
  • Single C drive
  • Web Server (example)

This is a diagram of our configuration.

Overview of migration

  • Create Virtual Network and Subnet in the Azure Portal
  • Run the Powershell script to adjust the server configuration for the AZURE VM. For example, the script will enable RDP access, DHCP services are running and etc.
  • Install Azure Agent on an on-premise server
  • Install Disk2VHD tool to convert physical C drive to VHD drive on On-premise
  • Install the PowerShell Module for Azure on-premise
  • Run the Disk2VHD tool and convert the C drive to a VHD file on an on-premise server
  • Upload VHD drive to Azure using Add-AzureRmVhd commands
  • Create VM using uploaded VHD  drive
  • Start Azure VM
  • Switch DNS records to point to Azure IP address.
  • Decommission on-premises Server

Disk2vhd Tool

Disk2vhd is a utility that creates VHD (Virtual Hard Disk) versions of physical disks.

We can run Disk2vhd on a system that’s online. Disk2vhd uses Volume Shadow Copy Service capability to create point-in-time snapshots of the volumes you want to include in a conversion. We can use  Disk2vhd to create the VHDs on local volumes, even ones being converted

Add-AzureRMVhd cmdlet
We are going to use  Add-AzureRMVhd cmdlet for uploading VHD files to Azure.

Add-AzureRMVhd will

  • Check the file you are uploading and make sure it’s a proper Azure-compatible VHD,
  • Calculate an MD5 hash to validate proper file transfer validity.
  • Detect empty blocks and don’t upload them, saving transfer time

Azure doesn’t support dynamic so the tool will convert your disk to a fixed disk if needed.
If the disk you are uploading is fixed, Azure will check the disk for unused space, and won’t transfer that data.

Create a Virtual Network and Subnet in the Azure Portal

Login to

We will need to create the following object  in Azure

  • Resource Group
  • Storage Account
  • Virtual Network

Navigate to Resource Group Container and clicking Add button to add new Resource Group.

Navigate to newly created Resource Group and add new Virtual Network

You can use the same subnet what are used on the local network
In our case, Virtual Network and Subnet use the same network.

Add a new Storage Account 

Search for Storage Account and add Storage Account

Fill up Storage Account properties

Storage Account has been successfully created.

When you navigate to Resource Group, you should have Storage Account and Virtual Network listed.

Prepare On-Premises Server

Install the Powershell ISE tool

We are enabling the PowerShell ISE tool provided with Windows 2008 R2 Server running two commands in PowerShell.

Import-Module ServerManager 
Add-WindowsFeature PowerShell-ISE

Run Powershell ISE  from an on-premises server. We recommend using Powershell ISE for the rest of the installation.

Upgrade Existing PowerShell version

Check the PowerShell Version  using the following commands

You can download the new version here

We recommend to Install a 5.1 version

Install Azure PowerShell on Windows

Run the following command to install Azure PowerShell

Install-Module -Name AzureRM -AllowClobber
Set-ExecutionPolicy unrestricted

Reset some of the settings on an on-premises server

Run the following Powershell commands in Powershell ISE  to prepare an on-premises server for the Azure VM environment.
These commands will reset some RDP properties and enable the same services to prepare a server for the Azure VM environment

netsh winhttp reset proxy
san policy=onlineall

Set-ItemProperty -Path 'HKLM:\SYSTEM\CurrentControlSet\Control\TimeZoneInformation' -name "RealTimeIsUniversal" 1 -Type DWord

Set-Service -Name w32time -StartupType Auto
powercfg /setactive SCHEME_MIN

Set-Service -Name bfe -StartupType Automatic
Set-Service -Name dhcp -StartupType Automatic
Set-Service -Name dnscache -StartupType Automatic
Set-Service -Name IKEEXT -StartupType Automatic
Set-Service -Name iphlpsvc -StartupType Automatic
Set-Service -Name netlogon -StartupType Manual
Set-Service -Name netman -StartupType Manual
Set-Service -Name nsi -StartupType Automatic
Set-Service -Name termService -StartupType Manual
Set-Service -Name MpsSvc -StartupType Automatic
Set-Service -Name RemoteRegistry -StartupType Automatic

Set-ItemProperty -Path 'HKLM:\SYSTEM\CurrentControlSet\Control\Terminal Server' -name "fDenyTSConnections" -Value 0 -Type DWord
Set-ItemProperty -Path 'HKLM:\SOFTWARE\Policies\Microsoft\Windows NT\Terminal Services' -name "fDenyTSConnections" -Value 0 -Type DWord
Set-ItemProperty -Path 'HKLM:\SYSTEM\CurrentControlSet\Control\Terminal Server\Winstations\RDP-Tcp' -name "PortNumber" 3389 -Type DWord
Set-ItemProperty -Path 'HKLM:\SYSTEM\CurrentControlSet\Control\Terminal Server\Winstations\RDP-Tcp' -name "LanAdapter" 0 -Type DWord
Set-ItemProperty -Path 'HKLM:\SYSTEM\CurrentControlSet\Control\Terminal Server\WinStations\RDP-Tcp' -name "UserAuthentication" 1 -Type DWord
Set-ItemProperty -Path 'HKLM:\SYSTEM\CurrentControlSet\Control\Terminal Server\WinStations\RDP-Tcp' -name "SecurityLayer" 1 -Type DWord
Set-ItemProperty -Path 'HKLM:\SYSTEM\CurrentControlSet\Control\Terminal Server\WinStations\RDP-Tcp' -name "fAllowSecProtocolNegotiation" 1 -Type DWord
Set-ItemProperty -Path 'HKLM:\SOFTWARE\Policies\Microsoft\Windows NT\Terminal Services' -name "KeepAliveEnable" 1 -Type DWord
Set-ItemProperty -Path 'HKLM:\SOFTWARE\Policies\Microsoft\Windows NT\Terminal Services' -name "KeepAliveInterval" 1 -Type DWord
Set-ItemProperty -Path 'HKLM:\SYSTEM\CurrentControlSet\Control\Terminal Server\Winstations\RDP-Tcp' -name "KeepAliveTimeout" 1 -Type DWord
Set-ItemProperty -Path 'HKLM:\SOFTWARE\Policies\Microsoft\Windows NT\Terminal Services' -name "fDisableAutoReconnect" 0 -Type DWord
Set-ItemProperty -Path 'HKLM:\SYSTEM\CurrentControlSet\Control\Terminal Server\Winstations\RDP-Tcp' -name "fInheritReconnectSame" 1 -Type DWord
Set-ItemProperty -Path 'HKLM:\SYSTEM\CurrentControlSet\Control\Terminal Server\Winstations\RDP-Tcp' -name "fReconnectSame" 0 -Type DWord
Set-ItemProperty -Path 'HKLM:\SYSTEM\CurrentControlSet\Control\Terminal Server\Winstations\RDP-Tcp' -name "MaxInstanceCount" 3000 -Type DWord

Remove-ItemProperty -Path 'HKLM:\SYSTEM\CurrentControlSet\Control\Terminal Server\WinStations\RDP-Tcp' -name "SSLCertificateSHA1Hash"

Set-ItemProperty -Path 'HKLM:\SYSTEM\CurrentControlSet\services\SharedAccess\Parameters\FirewallPolicy\DomainProfile' -name "EnableFirewall" -Value 1 -Type DWord
Set-ItemProperty -Path 'HKLM:\SYSTEM\CurrentControlSet\services\SharedAccess\Parameters\FirewallPolicy\PublicProfile' -name "EnableFirewall" -Value 1 -Type DWord
Set-ItemProperty -Path 'HKLM:\SYSTEM\CurrentControlSet\services\SharedAccess\Parameters\FirewallPolicy\Standardprofile' -name "EnableFirewall" -Value 1 -Type DWord

Enable-PSRemoting -force
netsh advfirewall firewall set rule dir=in name="Windows Remote Management (HTTP-In)" new enable=yes
netsh advfirewall firewall set rule dir=in name="Windows Remote Management (HTTP-In)" new enable=yes

netsh advfirewall firewall set rule group="Remote Desktop" new enable=yes
netsh advfirewall firewall set rule dir=in name="File and Printer Sharing (Echo Request - ICMPv4-In)" new enable=yes

Install Azure VM Agent on the local On-premises Server

Download and Install Azure VM agent on the local on-premises server

Install Disk2VHD Tool on local On-premises Server

Plug the local USB drive into a server. The drive has to be bigger than C drive which we are migrating.
Download and unpack Disk2VHD tool on a local USB Drive

Capture Image from Server

After we capture the image, all changes on-premises server will NOT  be reflected in the migrated server.

  • Run the Disk2VHD tool.
  • Pick up a boot volume and C drive.
  • Save the VHD file to a USB drive.
  • Do not use VHDX
  • Use Volume Shadow Copy


Run the Create button and the image will be captured and saved in a couple of minutes.


In our case, it took around 10 min for the content of  (C drive 20 Gb) to be copied to the VHD file on the USB drive.

Upload VHD file to Azure Storage Account

Configure storage account and retrieve Storage URL

Login back to Azure Portal, navigate to your storage account – Blobs and add a new container. We will call it VHD.

After you create a container,  navigate to the properties of the VHD container and write down the URL.

You will need this ($destinationVhd  variable) when you start uploading VHD to Azure.

Upload the VHD file to Azure and configure the VM

Run the following commands to upload the VHD file to the Azure Storage Account and configure the VM
In our case, It took almost 5 hours to move 22 Gb VHD files to Azure storage. Our maximum upload speed is 10 Mbps and PowerShell is using it all.

Run the following Powershell commands
# Import the module into the PowerShell session
Import-Module AzureRM

# Connect to Azure with an interactive dialogue for sign-in

# Setup all parameters
$resourceGroupName = “WebFarm”
$myVHD = “D:\VHD\WEB1.VHD”
$virtualNetworkName = “WEB-vnet”
$locationName = “CanadaCentral”
$destinationVhd =””
Get-AzureRmVMSize $locationName | Out-GridView

# Decide which VM size to use
Get-AzureRmVMSize $locationName | Out-GridView

#Upload “VHD drive to Azure
Add-AzureRmVhd -ResourceGroupName $resourceGroupName -Destination $destinationVhd -LocalFilePath $myVHD

# Configure Azure Network
$virtualNetwork = Get-AzureRmVirtualNetwork -ResourceGroupName $resourceGroupName -Name $virtualNetworkName
$publicIp = New-AzureRmPublicIpAddress -Name $PIPName -ResourceGroupName $ResourceGroupName -Location $locationName -AllocationMethod Dynamic
$networkInterface = New-AzureRmNetworkInterface -ResourceGroupName $resourceGroupName -Name $NICName -Location $locationName -SubnetId $virtualNetwork.Subnets[0].Id -PublicIpAddressId $publicIp.Id

# Configure VM
$vmConfig = New-AzureRmVMConfig -VMName $VMname -VMSize $VMSize
$vmConfig = Set-AzureRmVMOSDisk -VM $vmConfig -Name $OSDisk -VhdUri $destinationVhd -CreateOption Attach -Windows
$vmConfig = Add-AzureRmVMNetworkInterface -VM $vmConfig -Id $networkInterface.Id

#Create VM
$vm = New-AzureRmVM -VM $vmConfig -Location $locationName -ResourceGroupName $resourceGroupName

Check running VM in Azure.

After finishing the last command, the VM is created and started.
Login to
Navigate to your resource group. You will see a newly created VM which is already running

Connect to VM

Also, Notice that Network Properties are reset during VM creation and DHCP is enabled on VM.

Change public DNS.

At this moment web1 VM is migrated and it is running in Azure
Now you will need to change the Public DNS record for a website to point to the Public IP of Azure VM.

The End

By Dan Djurasovic

Dan is an Azure Technical Advisor, with over a dozen years of IT experience, specializing in Microsoft Office 365, Exchange Server Azure IaaS and Active Directory..

4 thought on “Migrate physical server to Azure VM using Disk2VHD tool and Add-AzureRmVhd command”

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.