A client of mine in Ohio called me on a Friday afternoon because their on-premises file server had finally run out of disk space, and their finance team couldn’t process month-end reports. They needed compute capacity that afternoon, not after a six-week hardware procurement cycle.
This is the exact situation where an Azure VM (Azure Virtual Machine) becomes the right tool. It gave that client a fully functional Windows Server instance, provisioned in about ten minutes, with room to scale as their data grew.
I’ve deployed hundreds of Azure VMs over the years for organizations ranging from five-person startups in Austin to multi-state healthcare networks, and I still see the same mistakes repeated: wide-open network security groups, VMs left running 24/7 that should have been shut down at night, and administrator credentials stored in plain text files.
This guide walks through everything I’ve learned building Azure virtual machine deployments that are secure, cost-aware, and easy for a small IT team to maintain long after I’ve moved on to the next project.
By the end of this article, you’ll be able to create an Azure VM using the Azure Portal, Azure CLI, and Bicep, configure its networking and identity correctly, secure remote access, and set up monitoring and backup so the VM doesn’t become a forgotten liability sitting on your monthly bill.
What Is an Azure VM and When Should You Use One?
An Azure VM is an on-demand, scalable computing resource in Microsoft Azure that gives you full control over the operating system, similar to a physical server, but without the hardware maintenance burden. You choose the operating system, size, storage, and networking, and Azure handles the underlying physical infrastructure.
I recommend an Azure VM instead of a platform-as-a-service option like Azure App Service when a client needs:
- Full control over the OS, including custom software installations or legacy applications that won’t run in a managed environment
- Specific compliance requirements that require OS-level configuration
- Lift-and-shift migrations of existing on-premises servers, similar to the kind of workload covered in how to migrate a VMware VM to Azure step by step
- Long-running background processes that don’t fit a serverless execution model
If your workload is a modern web application or API that doesn’t need OS-level control, I usually steer clients toward Azure App Service or Azure Functions instead, since those reduce the patching and maintenance burden significantly. I cover that trade-off in more detail in my comparison of Azure Functions vs. App Service.
Pro Tip: In my experience, half the “we need a bigger VM” requests I get are really “we need to redesign the application,” not “we need more compute.” Always ask why the workload needs full OS access before defaulting to a VM.
Planning Your Azure VM Architecture
Before you open the Azure Portal, a few architecture decisions will save you significant rework later.
Subscriptions and Resource Groups
An Azure subscription is the billing and governance boundary for all your Azure resources. If you’re running production and development workloads for the same organization, I typically recommend separating them into different subscriptions or, at minimum, different resource groups, which are logical containers for related Azure resources that share a lifecycle.
Grouping your VM, its virtual network, disks, and network security group into a single, well-named resource group makes it far easier to manage permissions and track cost. If you’re new to this concept, I’d point you toward what is resource group in Azure to see how it differs from a subscription.
I also strongly recommend following a consistent Azure resource group naming convention from day one. I learned this lesson the hard way on a project with three regional IT teams, each naming resource groups differently, which made cost reporting a nightmare six months later.
Choosing a Region and Availability Approach
Regions are the physical geographic locations where Azure runs its datacenters. For most U.S.-based organizations I work with, East US, West US 2, or Central US offer the best balance of latency and service availability. Within a supported region, availability zones are physically separate datacenters that protect your VM from a single datacenter failure.
If your Azure VM is business-critical, deploying it across availability zones (or using an availability set as a lower-cost alternative) is worth the added complexity.
Pro Tip: I always check availability zone support before committing to a region for a client’s production VM. Not every VM size is available in every zone, and how to check availability zone of Azure VM is a step I run before finalizing any deployment plan, since finding this out after deployment is a frustrating way to spend an afternoon.
Creating an Azure VM Step by Step
Here’s the general order of operations I follow with clients, whether I’m doing this through the portal or through code.
- Define the business requirement (operating system, expected load, compliance needs).
- Select the appropriate VM size and pricing model.
- Create the resource group and choose the region.
- Configure identity, permissions, and networking.
- Deploy the virtual machine.
- Store secrets securely and configure remote access.
- Add monitoring, backups, and alerts.
- Test normal, failure, and unauthorized-access scenarios.
- Review costs and document maintenance requirements.
Step 1: Create the Resource Group
az group create \
--name rg-finance-vm-prod \
--location eastusThis command creates a resource group named rg-finance-vm-prod in the East US region. Every resource related to this VM, its disk, network interface, and network security group, will live inside this resource group, giving your team a single management boundary for permissions, cost tracking, and cleanup. If you’d rather do this through the portal first, create a resource group in Azure walks through the same process visually.
Step 2: Create the Virtual Machine
az vm create \
--resource-group rg-finance-vm-prod \
--name vm-finance-app01 \
--image Win2022Datacenter \
--size Standard_D2s_v5 \
--admin-username azureadmin \
--generate-ssh-keys \
--public-ip-sku StandardLet me break down the important parameters here. The --image flag specifies Windows Server 2022 Datacenter, though you could swap this for an Ubuntu or Red Hat image depending on your workload. The --size flag sets the VM size, in this case Standard_D2s_v5, a general-purpose size with 2 vCPUs and 8 GB of RAM, suitable for a small line-of-business application.
The --public-ip-sku Standard flag ensures the public IP is zone-redundant and compatible with Standard load balancers, which matters if you expand this into a multi-VM setup later. The full command reference is available at az vm create if you need additional parameters for your scenario.
If you’d rather use the graphical interface, the walkthrough on how to create a virtual machine in Azure covers the portal-based process screen by screen, which I still recommend to clients who are new to Azure and want to see every configuration option before scripting it.
Pro Tip: I never use
Standard_Bburstable sizes for production database or application servers. They’re excellent for dev and test environments, but I’ve seen them throttle CPU credits at the worst possible moment during a month-end processing job.
Step 3: Create the VM with Azure PowerShell
Some of my clients’ IT teams are more comfortable in PowerShell, especially those coming from a Windows Server administration background.
$ResourceGroupName = "rg-finance-vm-prod"
$Location = "eastus"
$VMName = "vm-finance-app01"
$VMSize = "Standard_D2s_v5"
New-AzVM `
-ResourceGroupName $ResourceGroupName `
-Name $VMName `
-Location $Location `
-Size $VMSize `
-Image "Win2022Datacenter" `
-Credential (Get-Credential)The Get-Credential cmdlet prompts for an administrator username and password interactively rather than hardcoding it into the script, which is a small habit that prevents credentials from ending up in your command history or a shared script file.
The $ResourceGroupName, $Location, and $VMSize variables make the script reusable across environments simply by changing the values at the top. If PowerShell isn’t already installed and configured on your machine, the Azure PowerShell tutorial covers setup from scratch.
Step 4: Deploy Using Bicep for Repeatable Infrastructure
For any client running more than a handful of VMs, I push hard for infrastructure as code instead of manual portal clicks. Here’s a simplified Bicep template for a single VM deployment.
param location string = resourceGroup().location
param vmName string = 'vm-finance-app01'
param adminUsername string
@secure()
param adminPassword string
resource nic 'Microsoft.Network/networkInterfaces@2023-05-01' = {
name: '${vmName}-nic'
location: location
properties: {
ipConfigurations: [
{
name: 'ipconfig1'
properties: {
privateIPAllocationMethod: 'Dynamic'
}
}
]
}
}
resource vm 'Microsoft.Compute/virtualMachines@2023-09-01' = {
name: vmName
location: location
properties: {
hardwareProfile: {
vmSize: 'Standard_D2s_v5'
}
osProfile: {
computerName: vmName
adminUsername: adminUsername
adminPassword: adminPassword
}
networkProfile: {
networkInterfaces: [
{
id: nic.id
}
]
}
}
}Notice the @secure() decorator on the adminPassword parameter. This tells Azure Resource Manager, the deployment and management layer behind every Azure resource, to treat this value as sensitive and avoid logging it in deployment history.
You’d supply the actual password value through a parameter file or, better yet, pull it from Azure Key Vault during the pipeline run rather than typing it manually. Repeatable deployments like this eliminate the “it worked when I clicked through the portal but the script is different” problem I’ve run into more than once when handing off a project to an internal IT team.
Pro Tip: I keep a Bicep module library for common VM configurations across client engagements. It cuts deployment time roughly in half compared to starting from scratch every time.
Securing Your Azure VM
Security is where I see the most costly mistakes, usually from teams moving fast to hit a deadline.
Identity and Access Management
Never rely solely on local administrator accounts for ongoing access. Instead, integrate your VM with Microsoft Entra ID, the identity service used for authentication and access management across Azure, and assign permissions through role-based access control (RBAC) rather than handing out broad Owner or Contributor rights.
If a developer only needs to restart the VM, assign the Virtual Machine Contributor role scoped to that specific resource group, not subscription-wide access. The guide on Azure roles vs. Entra roles is worth reading if your team gets confused about which permission model applies where.
Where possible, use a managed identity, an Azure-managed identity that lets the VM authenticate to other Azure services like Key Vault or Storage without storing any credentials on the VM itself. I explain how this works in more depth in what is a managed identity in Azure. This single change eliminates an entire category of credential-leak incidents I’ve had to clean up for past clients.
Network Security
By default, I lock down inbound access using a network security group (NSG), which is a set of rules that allow or deny network traffic to your VM’s network interface or subnet. If you’re not familiar with how these rules are evaluated, what is NSG in Azure is a good primer, and the follow-up comparison of Azure NSG vs. ASG clarifies when application security groups make more sense than IP-based rules alone.
Here are the network exposure rules I follow on every VM deployment:
| Access Type | Recommendation | Why It Matters |
|---|---|---|
| RDP (port 3389) | Restrict to specific IP ranges or use Azure Bastion | Open RDP to the internet is one of the most common attack vectors I see scanned within minutes of deployment |
| SSH (port 22) | Restrict to specific IP ranges or a jump box | Same risk as RDP, just for Linux VMs |
| HTTP/HTTPS | Allow only if the VM hosts a public web app | Unnecessary open ports increase your attack surface for no benefit |
| Database ports | Never expose directly to the internet | Use a private endpoint or VNet-only access instead |
If you need to troubleshoot a specific rule, the guide on how to open ports on an Azure VM covers the exact CLI and portal steps for adding scoped, temporary rules rather than defaulting to “allow all.” For workloads that need private connectivity to platform services instead of public endpoints, review how to create a private endpoint in Azure.
Warning: Opening RDP or SSH to 0.0.0.0/0 (any source IP) is a step that immediately increases your exposure to brute-force attacks. I’ve inherited more than one client environment where this was left open for months, and it’s usually how ransomware initially gets a foothold.
Secrets and Configuration Data
Never store database connection strings, API keys, or passwords directly in application configuration files on the VM. Instead, use Azure Key Vault, a service purpose-built for securely storing secrets, keys, and certificates, and retrieve them at runtime using the VM’s managed identity.
If you’re setting this up for the first time, how does Azure Key Vault work, create a secret in Azure Key Vault, and the comparison of Key Vault Standard vs. Premium tiers will help you decide whether you need hardware security module-backed keys. Once it’s running, I also recommend reviewing Azure Key Vault best practices to make sure access policies aren’t left broader than necessary.
Pro Tip: I once found a production database password sitting in a
web.configfile that had been committed to a shared network drive accessible to the entire company. Moving that single secret into Key Vault took twenty minutes and closed a risk that had existed for over a year.
Disk, Storage, and Network Configuration
An Azure VM’s performance and reliability depend heavily on decisions outside the VM size itself.
Managed Disks
I always use managed disks rather than legacy unmanaged disks, since Azure handles the underlying storage account management automatically and simplifies backup and snapshot operations. If you inherit an older environment, how to check if disk is managed or unmanaged in Azure will help you audit existing VMs before making changes.
When you need to grow storage later, increase disk size in Azure VM covers the resize process without data loss.
For most production workloads, Premium SSD offers the best balance of performance and cost, while Standard SSD is a reasonable choice for dev and test environments. I rarely recommend Standard HDD for anything beyond archival or infrequently accessed data disks.
Virtual Network Design
Every Azure VM needs a network interface connected to a virtual network, the private network boundary that isolates your resources from the public internet by default. If your organization already has an on-premises network, you’ll want to review what is an Azure virtual network before deciding whether you need VNet peering or a VPN gateway to connect the two environments.
For multi-tier applications, I typically separate the web tier and database tier into different subnets within the same VNet, then use NSG rules to control traffic between them. This segmentation limits the blast radius if one tier is compromised.
Monitoring, Backup, and Disaster Recovery
A VM that isn’t monitored is a VM you’ll find out about only after it fails.
Setting Up Monitoring
Azure Monitor collects performance metrics, logs, and alerts across your Azure workloads, and I enable it on every VM I deploy, without exception. At minimum, configure alerts for CPU utilization above 85%, disk space below 10% free, and VM availability. The guide on what does Azure Monitor do is a solid starting point if your team hasn’t used it before, and what are Azure monitoring tools breaks down the broader ecosystem beyond just Azure Monitor itself.
If the VM hosts a custom application, adding Application Insights, a service focused on application-level performance and telemetry rather than infrastructure metrics, gives you visibility into slow database queries or failing dependencies that infrastructure monitoring alone won’t catch. The Azure Application Insights tutorial walks through instrumenting your first application.
Backup and Recovery Planning
I configure Azure Backup on every production VM using a Recovery Services vault, and I test the restore process at least once during the project, not just the backup job itself. Backups that have never been tested are a false sense of security.
The comparison of Azure VM snapshot vs. backup explains why snapshots alone aren’t a substitute for a proper backup policy, and Azure VM backup policy walks through setting retention periods that match your organization’s compliance requirements. If you ever need to roll back completely, Azure VM backup restore covers the recovery workflow step by step.
For business-critical workloads, I also evaluate Azure Site Recovery, which replicates the VM to a secondary region so you can fail over during a regional outage. This adds cost and complexity, so I only recommend it when the client has clearly identified the VM as critical to business continuity.
Azure VM Cost and Scaling Considerations
Cost is where I spend a surprising amount of client conversation time, mostly because VMs are billed for compute time regardless of whether anyone is using them.
The most common cost mistake I see is a development or test VM left running around the clock. Configuring Azure VM auto-shutdown for non-production VMs is one of the simplest changes you can make, and it often cuts a dev environment’s compute cost by 60% or more.
For teams that need scheduled start and stop across many VMs rather than a single shutdown timer, Azure Automation start-stop VMs with PowerShell is worth setting up. I also encourage clients to explore reservations or savings plans for VMs that truly run 24/7 in production, since committing to one or three years of usage in exchange for a discount makes sense once a workload’s baseline usage is well understood.
The comparison of Azure savings plan vs. reserved instances is worth reviewing before committing budget either way, alongside the broader Azure cost optimization best practices guide.
Right-sizing matters just as much as scheduling. I regularly find VMs sized for a launch-day traffic spike that never materialized, still running at that size a year later. Azure Advisor will flag underutilized VMs automatically, and reviewing those recommendations quarterly is a habit I build into every managed services engagement.
Setting up Azure budget alerts closes the loop so you find out about cost spikes immediately rather than at the end of the billing cycle.
Pro Tip: I set a budget alert on every client subscription the same day I create the first resource group. Catching a cost spike within 24 hours is far less painful than explaining a surprise bill at the end of the month.
Production Readiness Considerations
- Resource tags: Apply consistent Azure tags for environment, owner, and cost center from the moment the VM is created, since retrofitting tags across dozens of resources later is tedious and error-prone.
- Resource locks: Apply a delete lock to production VMs so a misclicked command in the portal or a CLI script doesn’t accidentally remove a business-critical server.
- Azure Policy: Use Azure Policy best practices to enforce standards automatically, such as requiring specific VM sizes, blocking public IP creation, or mandating encryption, rather than relying on manual code review to catch violations.
- Development versus production parity: Keep dev and test VM sizes smaller than production, but make sure the operating system version and critical configuration match closely enough that testing remains meaningful.
- Service quotas: Check your subscription’s vCPU quota before a large deployment, since hitting a regional quota limit mid-rollout is a frustrating and entirely avoidable delay.
- Governance at scale: Once you’re managing more than a few VMs across teams, review Azure governance best practices to keep naming, tagging, and access consistent as the environment grows.
Frequently Asked Questions
What is an Azure VM used for?
An Azure VM provides on-demand compute with full operating system control, making it suitable for legacy applications, lift-and-shift migrations, custom software installations, and workloads that don’t fit a managed platform-as-a-service model.
How much does an Azure VM cost?
Cost depends on the VM size, region, operating system licensing, storage type, and whether the VM runs continuously or on a schedule. Reviewing the breakdown on Azure virtual machine cost alongside Azure Advisor recommendations is the best way to estimate your specific scenario.
How do I secure remote access to an Azure VM?
Restrict RDP and SSH access using network security group rules scoped to specific IP addresses, or use Azure Bastion to avoid exposing those ports to the public internet entirely. Combine this with Microsoft Entra ID-based access control rather than relying only on local VM accounts.
Should I stop or deallocate my Azure VM to save money?
Deallocating a VM releases the compute resources and stops compute billing, while simply stopping it from within the operating system does not. The guide on does Azure charge for a stopped VM explains this distinction in detail, and start-stop VM using Azure CLI shows the correct commands to use.
What is the difference between an Azure VM and Azure App Service?
An Azure VM gives you full control over the operating system and everything installed on it, while Azure App Service is a managed platform for hosting web applications without managing the underlying OS. Choose App Service when you don’t need OS-level access, since it reduces patching and maintenance overhead significantly.
Creating an Azure VM is straightforward, but building one that’s genuinely secure, cost-aware, and maintainable requires deliberate decisions around identity, networking, backups, and monitoring from day one.
The single most important principle to carry forward is least-privilege access paired with proper secret management through Key Vault and managed identities, since that combination prevents the majority of incidents I’ve had to clean up in real client environments. I hope you found this article helpful.
You May Also Like
- What is a managed identity in Azure
- How does Azure Key Vault work
- Azure resource group best practices
- Azure security best practices
- How to find the IP address of an Azure VM
- Azure VM Backup Pricing

I am Rajkishore, and I am a Microsoft Certified IT Consultant. I have over 14 years of experience in Microsoft Azure and AWS, with good experience in Azure Functions, Storage, Virtual Machines, Logic Apps, PowerShell Commands, CLI Commands, Machine Learning, AI, Azure Cognitive Services, DevOps, etc. Not only that, I do have good real-time experience in designing and developing cloud-native data integrations on Azure or AWS, etc. I hope you will learn from these practical Azure tutorials. Read more.