Create Windows VM Using Bicep

This blog post will show you how to create a Windows Virtual Machine on Microsoft Azure using Bicep.

In this post, we are using an open-source Azure quick template to create the VM. The only difference we have made to the template is deploying the latest version of the Windows Server 2022 Azure image.

A few things about the deployment: when deploying the VM using Azure CLI, you will be prompted to enter a username and password.

  • To set the VM name, modify line 102.
  • To set the computer name, modify line 213.

Bicep Template

Below is our modified template, you can either copy it use the original available on GitHub.

To deploy the template, we are using the following Azure CLI command.

az deployment group create  --template-file 19.Windows_VM.bicep --resource-group biceplab --parameters adminUsername=vmadminname adminPassword=SETSTRONGPASSWORD  --verbose

When running the code with parameters make sure you set a strong password otherwise the deployment will fail.

Please create a resource group before deploying the VM.

@description('Username for the Virtual Machine.')
param adminUsername string

@description('Password for the Virtual Machine.')
param adminPassword string

@description('Unique DNS Name for the Public IP used to access the Virtual Machine.')
param dnsLabelPrefix string = toLower('${vmName}-${uniqueString(resourceGroup().id, vmName)}')

@description('Name for the Public IP used to access the Virtual Machine.')
param publicIpName string = 'myPublicIP'

@description('Allocation method for the Public IP used to access the Virtual Machine.')
param publicIPAllocationMethod string = 'Dynamic'

@description('SKU for the Public IP used to access the Virtual Machine.')
param publicIpSku string = 'Basic'

@description('The Windows version for the VM. This will pick a fully patched image of this given Windows version.')
param OSVersion string = '2022-datacenter-azure-edition'

@description('Size of the virtual machine.')
param vmSize string = 'Standard_B2s'

@description('Location for all resources.')
param location string = resourceGroup().location

@description('Name of the virtual machine.')
param vmName string = 'simple-vm'

var storageAccountName = 'bootdiags${uniqueString(resourceGroup().id)}'
var nicName = 'myVMNic'
var addressPrefix = ''
var subnetName = 'Subnet'
var subnetPrefix = ''
var virtualNetworkName = 'MyVNET'
var networkSecurityGroupName = 'default-NSG'

resource stg 'Microsoft.Storage/storageAccounts@2021-04-01' = {
  name: storageAccountName
  location: location
  sku: {
    name: 'Standard_LRS'
  kind: 'Storage'

resource pip 'Microsoft.Network/publicIPAddresses@2021-02-01' = {
  name: publicIpName
  location: location
  sku: {
    name: publicIpSku
  properties: {
    publicIPAllocationMethod: publicIPAllocationMethod
    dnsSettings: {
      domainNameLabel: dnsLabelPrefix

resource securityGroup 'Microsoft.Network/networkSecurityGroups@2021-02-01' = {
  name: networkSecurityGroupName
  location: location
  properties: {
    securityRules: [
        name: 'default-allow-3389'
        properties: {
          priority: 1000
          access: 'Allow'
          direction: 'Inbound'
          destinationPortRange: '3389'
          protocol: 'Tcp'
          sourcePortRange: '*'
          sourceAddressPrefix: '*'
          destinationAddressPrefix: '*'

resource vn 'Microsoft.Network/virtualNetworks@2021-02-01' = {
  name: virtualNetworkName
  location: location
  properties: {
    addressSpace: {
      addressPrefixes: [
    subnets: [
        name: subnetName
        properties: {
          addressPrefix: subnetPrefix
          networkSecurityGroup: {

resource nic 'Microsoft.Network/networkInterfaces@2021-02-01' = {
  name: nicName
  location: location
  properties: {
    ipConfigurations: [
        name: 'ipconfig1'
        properties: {
          privateIPAllocationMethod: 'Dynamic'
          publicIPAddress: {
          subnet: {
            id: resourceId('Microsoft.Network/virtualNetworks/subnets',, subnetName)

resource vm 'Microsoft.Compute/virtualMachines@2021-03-01' = {
  name: vmName
  location: location
  properties: {
    hardwareProfile: {
      vmSize: vmSize
    osProfile: {
      computerName: vmName
      adminUsername: adminUsername
      adminPassword: adminPassword
    storageProfile: {
      imageReference: {
        publisher: 'MicrosoftWindowsServer'
        offer: 'WindowsServer'
        sku: OSVersion
        version: 'latest'
      osDisk: {
        createOption: 'FromImage'
        managedDisk: {
          storageAccountType: 'StandardSSD_LRS'
      dataDisks: [
          diskSizeGB: 1023
          lun: 0
          createOption: 'Empty'
    networkProfile: {
      networkInterfaces: [
    diagnosticsProfile: {
      bootDiagnostics: {
        enabled: true

output hostname string =

Success! You're on the list.

Leave a Comment

This site uses Akismet to reduce spam. Learn how your comment data is processed.