> ## Content Index
> Fetch the complete content index at: https://codeisahighway.com/llms.txt
> Use this file to discover other available public pages before exploring further.

# How to create and deploy a development machine on Azure using Azure Resource Manager template in Visual Studio
- URL: https://codeisahighway.com/how-to-create-and-deploy-a-development-machine-on-azure-using-azure-resource-manager-template-in-visual-studio/
- Published: 2015-07-07T12:22:00.000Z
- Updated: 2026-07-31T19:44:52.000Z
- Author: Stephane Lapointe
- Tags: DevOps, Automation, Visual Studio 2015, Microsoft Azure, Azure Resource Manager, HowTo, #Import 2023-07-11 16:44, #Import 2026-09-04 10:31, #Import 2026-09-04 13:56

Azure Resource manager have been around for a while now and it made provisioning quite easy and convenient. A couple of persons have asked me how to create and manage development machines when I speak about dev/tests environment in Azure, I'll explain you one way of doing this.

If you follow this step by step guide, at the end, you'll get a development box running Visual Studio 2015 community edition. Your VM will be running on Azure Premium Storage.

> We'll use a premium storage account in our VM template. It is not that expensive for a 127GB disk and we'll have greater performance compared with standard storage.

## Pre-requisites

- An Azure subscription
- Visual Studio 2015 and Azure SDK 2.6 or later

> This article is not an introduction to Azure Resource Manager, if you need to catch up or learn on ARM, please see the *References* section at the end of the article.

## Steps to create and customize your ARM template

### Step 1

Launch Visual Studio 2015 and create a new *Azure Resource Group Project*.  
![Create Azure Resource Group project](https://codeisahighway.com/content/images/2015/07/NewResourceGroupProject.png)

### Step 2

Choose the *Windows Virtual Machine template* and click OK  
![ARM Windows virtual machine template](https://codeisahighway.com/content/images/2015/07/ChooseWindowsVirtualMachineTemplate.png)

This will create you a project in Visual Studio with a couple of files. The most important files are the one under the *Templates* folder, your deployment template and deployment parameters files.

![Files created by Azure Resource Group project](https://codeisahighway.com/content/images/2015/07/AfterARMProjectCreation.png)

### Step 3

Open the template file named: *WindowsVirtualMachine.json*

### Step 4

Locate the *windowsOSVersion* parameter and replace the whole parameter with the following:

```json
"imageSku": {
    "type": "string",
    "defaultValue": "VS-2015-Community-AzureSDK-2.7-WS2012R2",
    "allowedValues": [
        "VS-2015-Community-AzureSDK-2.7-WS2012R2",
        "VS-2015-Enterprise-AzureSDK-2.7-WS2012R2"
    ],
    "metadata": {
        "description": "The Visual Studio version for the VM. This will pick a fully patched image of this Visual Studio version. Allowed values: VS-2015-Community-AzureSDK-2.7-WS2012R2, VS-2015-Enterprise-AzureSDK-2.7-WS2012R2."
    }
}

```

Add the following parameter at the end of the parameters section:

```
"resourcesLocation": {
  "type": "string",
  "defaultValue": "East US 2",
  "allowedValues": [
    "West US",
    "East US 2",
    "West Europe",
    "East China",
    "Southeast Asia",
    "West Japan",
    "Australia East"
  ],
  "metadata": {
    "description": "The location of resources created in this template. Default value is East US 2."
  }
}

```

### Step 5

Change the values of the following variables:

```json
"vmName": "MyDevBoxVM"
"location": "[parameters('resourcesLocation')]"
"OSDiskName": "osdisk-devbox"
"imageOffer": "VisualStudio"
"imagePublisher": "MicrosoftVisualStudio"
"nicName": "devBoxNic"
"publicIPAddressName": "devBoxPublicIP"
"storageAccountType": "Premium_LRS"
"vmName": "MyVS2015DevBoxVM"
"vmSize": "Standard_DS2"

```

The important changes to understand in the variables above are:

- **imagePublisher**: We changed this because we want to use the Visual Studio images instead of Windows images
- **ImageOffer**: Again, we want to use a Visual Studio image offering
- **storageAccountType**: We use a premium storage account instead of a regular storage account
- **vmSize**: We need to use a DS serie VM, only them at the moment support premium storage.
- **location**: At the time of writing this article (July 2015), Premium Storage is not available in all Azure locations, see *Important Things to Know About Premium Storage* in *References* section for more information.

### Step 6

Replace the *imageReference* section of the virtual machine resource with the following:

```json
"imageReference": {
  "publisher": "[variables('imagePublisher')]",
  "offer": "[variables('imageOffer')]",
  "sku": "[parameters('imageSku')]",
  "version": "latest"
}

```

### Resulting template

You should end up with the following result for your template:

```json
{
  "$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#",
  "contentVersion": "1.0.0.0",
  "parameters": {
    "adminPassword": {
      "metadata": {
        "description": "Password for the Virtual Machine."
      },
      "type": "securestring"
    },
    "adminUsername": {
      "metadata": {
        "description": "Username for the Virtual Machine."
      },
      "type": "string"
    },
    "dnsNameForPublicIP": {
      "metadata": {
        "description": "Unique DNS Name for the Public IP used to access the Virtual Machine."
      },
      "type": "string"
    },
    "imageSku": {
      "allowedValues": [
        "VS-2015-Community-AzureSDK-2.7-WS2012R2",
        "VS-2015-Enterprise-AzureSDK-2.7-WS2012R2"
      ],
      "defaultValue": "VS-2015-Community-AzureSDK-2.7-WS2012R2",
      "metadata": {
        "description": "The Visual Studio version for the VM. This will pick a fully patched image of this Visual Studio version. Allowed values: VS-2015-Community-AzureSDK-2.7-WS2012R2, VS-2015-Enterprise-AzureSDK-2.7-WS2012R2."
      },
      "type": "string"
    },
    "newStorageAccountName": {
      "metadata": {
        "description": "Unique DNS Name for the Storage Account where the Virtual Machine's disks will be placed."
      },
      "type": "string"
    },
    "resourcesLocation": {
      "allowedValues": [
        "West US",
        "East US 2",
        "West Europe",
        "East China",
        "Southeast Asia",
        "West Japan",
        "Australia East"
      ],
      "defaultValue": "East US 2",
      "metadata": {
        "description": "The location of resources created in this template. Default value is East US 2."
      },
      "type": "string"
    }
  },
  "resources": [
    {
      "apiVersion": "2015-05-01-preview",
      "location": "[variables('location')]",
      "name": "[parameters('newStorageAccountName')]",
      "properties": {
        "accountType": "[variables('storageAccountType')]"
      },
      "tags": {
        "displayName": "StorageAccount"
      },
      "type": "Microsoft.Storage/storageAccounts"
    },
    {
      "apiVersion": "2015-05-01-preview",
      "location": "[variables('location')]",
      "name": "[variables('publicIPAddressName')]",
      "properties": {
        "dnsSettings": {
          "domainNameLabel": "[parameters('dnsNameForPublicIP')]"
        },
        "publicIPAllocationMethod": "[variables('publicIPAddressType')]"
      },
      "tags": {
        "displayName": "PublicIPAddress"
      },
      "type": "Microsoft.Network/publicIPAddresses"
    },
    {
      "apiVersion": "2015-05-01-preview",
      "location": "[variables('location')]",
      "name": "[variables('virtualNetworkName')]",
      "properties": {
        "addressSpace": {
          "addressPrefixes": [
            "[variables('addressPrefix')]"
          ]
        },
        "subnets": [
          {
            "name": "[variables('subnetName')]",
            "properties": {
              "addressPrefix": "[variables('subnetPrefix')]"
            }
          }
        ]
      },
      "tags": {
        "displayName": "VirtualNetwork"
      },
      "type": "Microsoft.Network/virtualNetworks"
    },
    {
      "apiVersion": "2015-05-01-preview",
      "dependsOn": [
        "[concat('Microsoft.Network/publicIPAddresses/', variables('publicIPAddressName'))]",
        "[concat('Microsoft.Network/virtualNetworks/', variables('virtualNetworkName'))]"
      ],
      "location": "[variables('location')]",
      "name": "[variables('nicName')]",
      "properties": {
        "ipConfigurations": [
          {
            "name": "ipconfig1",
            "properties": {
              "privateIPAllocationMethod": "Dynamic",
              "publicIPAddress": {
                "id": "[resourceId('Microsoft.Network/publicIPAddresses',variables('publicIPAddressName'))]"
              },
              "subnet": {
                "id": "[variables('subnetRef')]"
              }
            }
          }
        ]
      },
      "tags": {
        "displayName": "NetworkInterface"
      },
      "type": "Microsoft.Network/networkInterfaces"
    },
    {
      "apiVersion": "2015-05-01-preview",
      "dependsOn": [
        "[concat('Microsoft.Storage/storageAccounts/', parameters('newStorageAccountName'))]",
        "[concat('Microsoft.Network/networkInterfaces/', variables('nicName'))]"
      ],
      "location": "[variables('location')]",
      "name": "[variables('vmName')]",
      "properties": {
        "hardwareProfile": {
          "vmSize": "[variables('vmSize')]"
        },
        "networkProfile": {
          "networkInterfaces": [
            {
              "id": "[resourceId('Microsoft.Network/networkInterfaces',variables('nicName'))]"
            }
          ]
        },
        "osProfile": {
          "adminPassword": "[parameters('adminPassword')]",
          "adminUsername": "[parameters('adminUsername')]",
          "computername": "[variables('vmName')]"
        },
        "storageProfile": {
          "imageReference": {
            "offer": "[variables('imageOffer')]",
            "publisher": "[variables('imagePublisher')]",
            "sku": "[parameters('imageSku')]",
            "version": "latest"
          },
          "osDisk": {
            "caching": "ReadWrite",
            "createOption": "FromImage",
            "name": "osdisk",
            "vhd": {
              "uri": "[concat('http://',parameters('newStorageAccountName'),'.blob.core.windows.net/',variables('vmStorageAccountContainerName'),'/',variables('OSDiskName'),'.vhd')]"
            }
          }
        }
      },
      "tags": {
        "displayName": "VirtualMachine"
      },
      "type": "Microsoft.Compute/virtualMachines"
    }
  ],
  "variables": {
    "OSDiskName": "osdisk-devbox",
    "addressPrefix": "10.0.0.0/16",
    "imageOffer": "VisualStudio",
    "imagePublisher": "MicrosoftVisualStudio",
    "location": "[parameters('resourcesLocation')]",
    "nicName": "devBoxNic",
    "publicIPAddressName": "devBoxPublicIP",
    "publicIPAddressType": "Dynamic",
    "storageAccountType": "Premium_LRS",
    "subnetName": "Subnet",
    "subnetPrefix": "10.0.0.0/24",
    "subnetRef": "[concat(variables('vnetID'),'/subnets/',variables('subnetName'))]",
    "virtualNetworkName": "MyVNET",
    "vmName": "MyDevBoxVM",
    "vmSize": "Standard_DS2",
    "vmStorageAccountContainerName": "vhds",
    "vnetID": "[resourceId('Microsoft.Network/virtualNetworks',variables('virtualNetworkName'))]"
  }
}

```

### Step 8

Right-click your project node in Visual studio and choose *Deploy* / *New Deployment...*  
![New ARM template deployment from Visual Studio](https://codeisahighway.com/content/images/2015/07/NewTemplateDeploymentFromVS.png)

- Choose your Azure subscription
- Select and existing or a create a new resource group. (**Ensure your resource group location support Premium storage**)  
![Create resource group](https://codeisahighway.com/content/images/2015/07/CreateResourceGroup.png)

![Deploy to Resource group dialog](https://codeisahighway.com/content/images/2015/07/DeployToResourceGroupDialog.png)

- Click Deploy

You'll get prompted for parameters values, specially the *adminPassword* if you don't click the "save passwords" checkbox.

- Enter the information and click save.

> Pay special attention to the format you use for the dnsNameForPublicIP and newStorageAccountName parameters. **They need to be alphanumeric only and lowercase**

![Deployment parameters](https://codeisahighway.com/content/images/2015/07/DeploymentParameters.png)

In 4-8 minutes, you'll get a development machine on Azure!

Have fun developing in the cloud!  
[Download the Visual Studio 2015 project](https://github.com/slapointe/BlogSamples/blob/master/ARM-DevelopmentMachine/?ref=codeisahighway.com)

## References

- [Azure - Free one-month trial](http://azure.microsoft.com/en-us/pricing/free-trial/?ref=codeisahighway.com)
- [Azure Resource Manager Overview](https://azure.microsoft.com/en-us/documentation/articles/resource-group-overview/?ref=codeisahighway.com)
- [Premium storage](http://azure.microsoft.com/en-us/services/storage/premium-storage/?ref=codeisahighway.com)
- [Important Things to Know About Premium Storage](https://azure.microsoft.com/en-us/documentation/articles/storage-premium-storage-preview-portal/?ref=codeisahighway.com#important-things-to-know-about-premium-storage)
- [Microsoft Azure PowerShell](https://github.com/Azure/azure-powershell/releases?ref=codeisahighway.com)