---
title: "Automating VM Deployment in Azure with PowerShell"
description: "Learn how to automate the deployment of a Windows VM on Azure using PowerShell. This guide covers network setup, NSG rules, and IIS installation."
canonical: "https://adamtheautomator.com/automating-azure-vm/"
---

# Automating VM Deployment in Azure with PowerShell

> Learn how to automate the deployment of a Windows VM on Azure using PowerShell. This guide covers network setup, NSG rules, and IIS installation.

Source: https://adamtheautomator.com/automating-azure-vm/

---

ATA Learning

Tap to hide

[

ATA Learning

](/)

*   [Home](/)
*   [Tutorials](/tutorials/)
*   [Instructors](/author/)
*   [Advertising](/advertising/)
*   [Recommended Resources](/resources/)
*   [About Adam](/about-adam/)

Search for:  

*   [](https://twitter.com/adbertram)
*   [](https://github.com/Adam-the-Automator)
*   [](https://www.linkedin.com/company/adam-the-automator-llc)
*   [](/feed/)

![Automating VM Deployment in Azure with PowerShell](https://adamtheautomator.com/wp-content/uploads/2024/09/DALL·E-2024-09-28-09.26.52-A-simple-image-representing-cloud-automation-in-Azure.-A-cloud-icon-with-gears-inside-a-server-and-a-command-prompt-symbol-all-connected-with-lines.webp)

# Automating VM Deployment in Azure with PowerShell

[![](https://secure.gravatar.com/avatar/d0b9d42e21e5622713f8b693aa5c0f9244d5f7dd200ed29b8398f52dee5de337?s=192&d=mm&r=g)Adam Bertram](https://adamtheautomator.com/author/adam-bertram/)18 October 20244 min. read

Categories: [Cloud](/category/cloud/)

Tags:[Azure](/tag/azure/)[Azure PowerShell](/tag/azure-powershell/)[PowerShell](/tag/powershell/)

Table of Contents

*   [Why Automate VM Deployment?](#why-automate-vm-deployment)
*   [Conclusion](#conclusion)

Automating tasks in Azure can save significant time and effort, especially when deploying resources like virtual machines (VMs). In this blog post, we’ll walk through automating the deployment of a Windows VM in Azure using PowerShell. We’ll configure networking, security, and install IIS for a web server all in one script.

#### Why Automate VM Deployment?

Automating tasks such as virtual machine deployment ensures consistency, reduces errors, and accelerates the setup process. With PowerShell, you can define all the necessary parameters and let the script handle the deployment, instead of manually creating each resource via the Azure Portal.

Here’s a step-by-step breakdown of the PowerShell script used to deploy an Azure VM, configure networking, set security rules, and install IIS.

Here’s the script if you just want to download it.

```
[CmdletBinding()]
param(
    [Parameter(Mandatory)]
    [string]$ResourceGroupName = 'Admissions',

    [Parameter(Mandatory)]
    [string]$Location = 'East US',

    [Parameter(Mandatory)]
    [string]$VMName = 'ADMISSIONSWEB',

    [Parameter(Mandatory)]
    [string]$VMSize = 'Standard_DS3_v2',

    [Parameter(Mandatory)]
    [string]$PublicIPName = 'Admissions-PubIp',

    [Parameter(Mandatory)]
    [string]$NICName = 'Admissions-vNIC',

    [Parameter(Mandatory)]
    [string]$OSDiskName = 'Admissions-OSDisk',

    [Parameter(Mandatory)]
    [string]$NSGName = 'ADMISSIONSWEB-NSG',

    [Parameter(Mandatory)]
    [string]$AdminUsername = 'adam',

    [Parameter(Mandatory)]
    [SecureString]$AdminPassword = (ConvertTo-SecureString 'P@$$w0rd12' -AsPlainText -Force)
)

$ErrorActionPreference = 'Stop'

function CreateAzResource {
    param(
        [Parameter(Mandatory)]
        [string]$ResourceType,
        
        [Parameter(Mandatory)]
        [string]$Name,
        
        [Parameter(Mandatory)]
        [hashtable]$NewParameter
    )
    
    try {
        $resource = & "Get-Az$ResourceType" -Name $Name -ResourceGroupName $NewParameter.ResourceGroupName
    } catch {
        if ($_.Exception.Message -match "under resource group '.*' was not found") {
            $resource = & "New-Az$ResourceType" @NewParameter
        } else {
            throw $_
        }
    } finally {
        $resource
    }
}

#region VM Configuration
$vmconfig = New-AzVMConfig -VMName $VMName -VMSize $VMSize
#endregion

#region Public IP Creation
$newPublicIpParams = @{
    Name              = $PublicIPName
    ResourceGroupName = $ResourceGroupName
    AllocationMethod  = 'Static'
    Location          = $Location
}
$publicIp = CreateAzResource -ResourceType PublicIpAddress -Name $PublicIPName -NewParameter $newPublicIpParams
#endregion

#region Network Interface Configuration
$vNet = Get-AzVirtualNetwork -ResourceGroupName $ResourceGroupName
$subnetId = $vNet.Subnets[0].Id

$newVNicParams = @{
    Name              = $NICName
    ResourceGroupName = $ResourceGroupName
    Location          = $Location
    SubnetId          = $subnetId
    PublicIpAddressId = $publicIp.Id
}
$vNic = CreateAzResource -ResourceType NetworkInterface -Name $NICName -NewParameter $newVNicParams
#endregion

#region OS Configuration
$cred = New-Object System.Management.Automation.PSCredential ($AdminUsername, $AdminPassword)
$newVmOsParams = @{
    Windows          = $true
    ComputerName     = $VMName
    Credential       = $cred
    EnableAutoUpdate = $true
    VM               = $vmconfig
}
$vm = Set-AzVMOperatingSystem @newVmOsParams
#endregion

#region Image Configuration
$newSourceImageParams = @{
    PublisherName = 'MicrosoftWindowsServer'
    Offer         = 'WindowsServer'
    Skus          = '2019-Datacenter'
    Version       = 'latest'
    VM            = $vm
}
$vm = Set-AzVMSourceImage @newSourceImageParams
#endregion

#region Disk Configuration
$vm = Set-AzVMOSDisk -VM $vm -Name $OSDiskName -CreateOption FromImage
#endregion

#region Network Interface Attachment
$vm = Add-AzVMNetworkInterface -VM $vm -Id $vNic.Id
#endregion

#region NSG Configuration
$newNsgParams = @{
    ResourceGroupName = $ResourceGroupName
    Location          = $Location
    Name              = $NSGName
}
$nsg = CreateAzResource -ResourceType NetworkSecurityGroup -Name $NSGName -NewParameter $newNsgParams

$ruleExists = $nsg.SecurityRules.Name -contains "Allow-RDP"
if (-not $ruleExists) {
    $ip = Invoke-RestMethod -Uri "https://api.ipify.org"
    $rdpRule = New-AzNetworkSecurityRuleConfig -Name "Allow-RDP" -Description "Allow RDP" -Access Allow -Protocol Tcp -Direction Inbound -Priority 1000 -SourceAddressPrefix $ip -SourcePortRange * -DestinationAddressPrefix * -DestinationPortRange 3389
    $nsg.SecurityRules.Add($rdpRule)
    $nsg | Set-AzNetworkSecurityGroup
}
#endregion

#region Web Traffic Rule Configuration
$webRuleExists = $nsg.SecurityRules.Name -contains "Allow-Web"
if (-not $webRuleExists) {
    $webRule = New-AzNetworkSecurityRuleConfig -Name "Allow-Web" -Description "Allow HTTP" -Access Allow -Protocol Tcp -Direction Inbound -Priority 200 -SourceAddressPrefix * -SourcePortRange * -DestinationAddressPrefix * -DestinationPortRange 80
    $nsg.SecurityRules.Add($webRule)
    $nsg | Set-AzNetworkSecurityGroup
}
#endregion

$vNic.NetworkSecurityGroup = $nsg
$vNic | Set-AzNetworkInterface

#region VM Creation
$newVmParams = @{
    ResourceGroupName = $ResourceGroupName
    VM                = $vm
    Location          = $Location
}
CreateAzResource -ResourceType VM -Name $VMName -NewParameter $newVmParams
#endregion

#region IIS Installation
$installIIS = {
    Install-WindowsFeature -Name Web-Server -IncludeManagementTools
}
$installScript = [scriptblock]::create($installIIS)
Invoke-AzVMRunCommand -ResourceGroupName $ResourceGroupName -VMName $VMName -CommandId 'RunPowerShellScript' -ScriptString $installScript
#endregion

#region Output Public IP
$publicIp.IpAddress
```

**Define Parameters**

The script starts by defining parameters that will be used throughout the deployment. These include basic information such as resource group, VM name, location, and admin credentials. Using parameters ensures the script is flexible and can be reused for different environments.

```
param(
    [Parameter(Mandatory)]
    [string]$ResourceGroupName = 'Admissions',
    [Parameter(Mandatory)]
    [string]$Location = 'East US',
    [Parameter(Mandatory)]
    [string]$VMName = 'ADMISSIONSWEB',
    [Parameter(Mandatory)]
    [string]$VMSize = 'Standard_DS3_v2',
    [Parameter(Mandatory)]
    [string]$PublicIPName = 'Admissions-PubIp',
    [Parameter(Mandatory)]
    [string]$NICName = 'Admissions-vNIC',
    [Parameter(Mandatory)]
    [string]$OSDiskName = 'Admissions-OSDisk',
    [Parameter(Mandatory)]
    [string]$NSGName = 'ADMISSIONSWEB-NSG',
    [Parameter(Mandatory)]
    [string]$AdminUsername = 'adam',
    [Parameter(Mandatory)]
    [SecureString]$AdminPassword = (ConvertTo-SecureString 'P@$$w0rd12' -AsPlainText -Force)
)
```

**Creating Azure Resources**

The \`CreateAzResource\` function helps create various Azure resources like public IPs, network interfaces, and network security groups (NSGs). It attempts to get a resource and creates it if it doesn’t exist, making the process more efficient.

```
function CreateAzResource {
    param(
        [Parameter(Mandatory)]
        [string]$ResourceType,
        [Parameter(Mandatory)]
        [string]$Name,
        [Parameter(Mandatory)]
        [hashtable]$NewParameter
    )
    
    try {
        $resource = & "Get-Az$ResourceType" -Name $Name -ResourceGroupName $NewParameter.ResourceGroupName
    } catch {
        if ($_.Exception.Message -match "not found") {
            $resource = & "New-Az$ResourceType" @NewParameter
        } else {
            throw $_
        }
    } finally {
        $resource
    }
}
```

**VM Configuration and Networking Setup**

Once resources like public IP and virtual networks are created, the script configures a virtual machine (VM) using \`New-AzVMConfig\`, attaches a network interface, and sets up the operating system and disk.

```
$vmconfig = New-AzVMConfig -VMName $VMName -VMSize $VMSize

$vNic = CreateAzResource -ResourceType NetworkInterface -Name $NICName -NewParameter $newVNicParams
$vm = Set-AzVMOperatingSystem @newVmOsParams
$vm = Set-AzVMSourceImage @newSourceImageParams
$vm = Set-AzVMOSDisk -VM $vm -Name $OSDiskName -CreateOption FromImage
```

**Configuring Network Security Rules**

The script adds security rules to the NSG to allow inbound RDP (Remote Desktop) and web traffic on port 80 (HTTP). This is critical for managing the VM and hosting web applications.

```
$ruleExists = $nsg.SecurityRules.Name -contains "Allow-RDP"
if (-not $ruleExists) {
    $ip = Invoke-RestMethod -Uri "https://api.ipify.org"
    $rdpRule = New-AzNetworkSecurityRuleConfig -Name "Allow-RDP" -Access Allow -Protocol Tcp -SourceAddressPrefix $ip -DestinationPortRange 3389
    $nsg.SecurityRules.Add($rdpRule)
    $nsg | Set-AzNetworkSecurityGroup
}
```

**Installing IIS**

After the VM is created, the script installs IIS (Internet Information Services), which will allow the VM to act as a web server. This is done by executing a PowerShell command on the VM.

```
$installIIS = {
    Install-WindowsFeature -Name Web-Server -IncludeManagementTools
}
Invoke-AzVMRunCommand -ResourceGroupName $ResourceGroupName -VMName $VMName -CommandId 'RunPowerShellScript' -ScriptString $installIIS
```

**Output the Public IP**

Finally, the public IP of the VM is outputted for easy access to the web server.

```
$publicIp.IpAddress
```

#### Conclusion

With this PowerShell script, deploying a Windows VM on Azure with configured networking, security, and IIS setup becomes seamless. This level of automation is invaluable for repetitive tasks and ensures that your infrastructure is set up consistently.

By following this guide, you can deploy VMs quickly and focus more on configuring applications rather than spending time manually setting up resources.

Share this article

[Share on X](https://twitter.com/intent/tweet?url=https%3A%2F%2Fadamtheautomator.com%2Fautomating-azure-vm%2F&text=Automating%20VM%20Deployment%20in%20Azure%20with%20PowerShell)[Share on Facebook](https://www.facebook.com/sharer/sharer.php?u=https%3A%2F%2Fadamtheautomator.com%2Fautomating-azure-vm%2F)[Share on LinkedIn](https://www.linkedin.com/sharing/share-offsite/?url=https%3A%2F%2Fadamtheautomator.com%2Fautomating-azure-vm%2F)

## Related Posts

![](https://adamtheautomator.com/wp-content/uploads/2024/09/edab50b1-3d77-415f-92b8-7e487a332ac2.webp)

### [How to Create Azure Service Principals in PowerShell](/powershell-service-principals/)

Learn how to create Azure service principals using PowerShell, enabling secure automation for managing Azure resources like virtual machines.

![](https://adamtheautomator.com/wp-content/uploads/2026/08/featured_image-3.webp)

### [Build an Azure Home Lab for Certs Without Overspending](/azure-home-lab-certification-practice/)

Build a nested Azure Hyper-V home lab with budget alerts, a domain controller, and Azure Arc mapped to AZ-900, AZ-104, and AZ-305 exams.

![](https://adamtheautomator.com/wp-content/uploads/2026/04/featured_image-15.webp)

### [Fix Azure Cost Reporting with a FinOps Tagging Strategy](/fix-azure-cost-reporting-finops-tagging-strategy-3/)

Build an Azure resource tagging taxonomy, enforce it with Azure Policy, and automate remediation of untagged resources to enable accurate FinOps cost allocation and chargebacks.

## Categories

*   [IT Ops](/category/it-ops/)
*   [Cloud](/category/cloud/)
*   [DevOps](/category/devops/)
*   [Home Ops](/category/home-ops/)
*   [Information Security](/category/infosec/)
*   [Software Development](/category/software-development/)

## Site

*   [Home](/)
*   [Tutorials](/tutorials/)
*   [Instructors](/author/)
*   [Advertising](/advertising/)
*   [Recommended Resources](/resources/)
*   [About Adam](/about-adam/)

Copyright 2026© ATA Learning | [Privacy Policy](/privacy/)
