{"id":101,"date":"2026-01-28T12:00:00","date_gmt":"2026-01-28T12:00:00","guid":{"rendered":"https:\/\/rezachegini.com\/?p=101"},"modified":"2026-10-30T07:01:58","modified_gmt":"2026-10-30T07:01:58","slug":"azure-virtual-machines-complete-arm-template-guide","status":"publish","type":"post","link":"https:\/\/rezachegini.com\/?p=101","title":{"rendered":"Azure Virtual Machines: Complete ARM Template Guide"},"content":{"rendered":"<h3 class=\"wp-block-heading\">Why VMs Are Complex<\/h3><p class=\"wp-block-paragraph\">Hello everyone! Today I want to share my experience deploying Azure Virtual Machines with ARM templates. This was my biggest challenge because one VM needs many resources working together.<\/p><p class=\"wp-block-paragraph\">When I deployed my first VM, I thought &#8220;just create one resource&#8221;. But I was wrong! A VM needs:<\/p><ol class=\"wp-block-list\"><li>Virtual Network &#8211; Where the VM lives<\/li><li>Subnet &#8211; A section inside the network<\/li><li>Network Security Group &#8211; Firewall rules<\/li><li>Public IP Address &#8211; To access from internet<\/li><li>Network Interface &#8211; Like a network card<\/li><li>Storage Account &#8211; For diagnostics<\/li><li>The VM itself &#8211; The actual computer<\/li><\/ol><p class=\"wp-block-paragraph\">Think of it like building a house. You need the neighborhood (VNet), the street (Subnet), security gate (NSG), address (Public IP), front door (Network Interface), mailbox (Storage), and the house itself (VM).<\/p><p class=\"wp-block-paragraph\">All these must be created in the correct order. Let me show you my code!<\/p><h3 class=\"wp-block-heading\">My Complete VM Template<\/h3><p class=\"wp-block-paragraph\">Here is my full template:<\/p><pre class=\"wp-block-code\"><code>{\n    \"$schema\": \"https:\/\/schema.management.azure.com\/schemas\/2019-04-01\/deploymentTemplate.json#\",\n    \"contentVersion\": \"1.0.0.0\",\n    \"parameters\": {},\n    \"functions\": [],\n    \"variables\": {},\n    \"resources\": [\n        {\n            \"name\": \"appnetwork\",\n            \"type\": \"Microsoft.Network\/virtualNetworks\",\n            \"apiVersion\": \"2020-11-01\",\n            \"location\": \"North Europe\",\n            \"properties\": {\n                \"addressSpace\": {\n                    \"addressPrefixes\": [\"10.0.0.0\/16\"]\n                },\n                \"subnets\": [\n                    {\n                        \"name\": \"SubnetA\",\n                        \"properties\": {\n                            \"addressPrefix\": \"10.0.0.0\/24\",\n                            \"networkSecurityGroup\": {\n                                \"id\": \"[resourceId('Microsoft.Network\/networkSecurityGroups', 'app-nsg')]\"\n                            }\n                        }\n                    },\n                    {\n                        \"name\": \"SubnetB\",\n                        \"properties\": {\n                            \"addressPrefix\": \"10.0.1.0\/24\"\n                        }\n                    }\n                ]\n            }\n        },\n        {\n            \"name\": \"app-ip\",\n            \"type\": \"Microsoft.Network\/publicIPAddresses\",\n            \"apiVersion\": \"2020-11-01\",\n            \"location\": \"North Europe\",\n            \"properties\": {\n                \"publicIPAllocationMethod\": \"Dynamic\"\n            }\n        },\n        {\n            \"name\": \"app-interface\",\n            \"type\": \"Microsoft.Network\/networkInterfaces\",\n            \"apiVersion\": \"2020-11-01\",\n            \"location\": \"North Europe\",\n            \"properties\": {\n                \"ipConfigurations\": [\n                    {\n                        \"name\": \"ipConfig1\",\n                        \"properties\": {\n                            \"privateIPAllocationMethod\": \"Dynamic\",\n                            \"publicIPAddress\": {\n                                \"id\": \"[resourceId('Microsoft.Network\/publicIPAddresses', 'app-ip')]\"\n                            },\n                            \"subnet\": {\n                                \"id\": \"[resourceId('Microsoft.Network\/virtualNetworks\/subnets', 'appnetwork', 'SubnetA')]\"\n                            }\n                        }\n                    }\n                ]\n            },\n            \"dependsOn\": [\n                \"[resourceId('Microsoft.Network\/publicIPAddresses', 'app-ip')]\",\n                \"[resourceId('Microsoft.Network\/virtualNetworks', 'appnetwork')]\"\n            ]\n        },\n        {\n            \"name\": \"rezastore8677676\",\n            \"type\": \"Microsoft.Storage\/storageAccounts\",\n            \"apiVersion\": \"2021-04-01\",\n            \"location\": \"[resourceGroup().location]\",\n            \"sku\": {\n                \"name\": \"Standard_LRS\"\n            },\n            \"kind\": \"StorageV2\"\n        },\n        {\n            \"name\": \"app-nsg\",\n            \"type\": \"Microsoft.Network\/networkSecurityGroups\",\n            \"apiVersion\": \"2020-11-01\",\n            \"location\": \"[resourceGroup().location]\",\n            \"properties\": {\n                \"securityRules\": [\n                    {\n                        \"name\": \"Allow-RDP\",\n                        \"properties\": {\n                            \"description\": \"Allow RDP\",\n                            \"protocol\": \"Tcp\",\n                            \"sourcePortRange\": \"*\",\n                            \"destinationPortRange\": \"3389\",\n                            \"sourceAddressPrefix\": \"*\",\n                            \"destinationAddressPrefix\": \"*\",\n                            \"access\": \"Allow\",\n                            \"priority\": 100,\n                            \"direction\": \"Inbound\"\n                        }\n                    }\n                ]\n            }\n        },\n        {\n            \"name\": \"appvm\",\n            \"type\": \"Microsoft.Compute\/virtualMachines\",\n            \"apiVersion\": \"2021-03-01\",\n            \"location\": \"[resourceGroup().location]\",\n            \"dependsOn\": [\n                \"[resourceId('Microsoft.Storage\/storageAccounts', toLower('rezastore8677676'))]\",\n                \"[resourceId('Microsoft.Network\/networkInterfaces', 'app-interface')]\"\n            ],\n            \"properties\": {\n                \"hardwareProfile\": {\n                    \"vmSize\": \"Standard_D2s_v3\"\n                },\n                \"osProfile\": {\n                    \"computerName\": \"appvm\",\n                    \"adminUsername\": \"demousr\",\n                    \"adminPassword\": \"Azure@123\"\n                },\n                \"storageProfile\": {\n                    \"imageReference\": {\n                        \"publisher\": \"MicrosoftWindowsServer\",\n                        \"offer\": \"WindowsServer\",\n                        \"sku\": \"2019-Datacenter\",\n                        \"version\": \"latest\"\n                    },\n                    \"osDisk\": {\n                        \"name\": \"windowsVM1OSDisk\",\n                        \"caching\": \"ReadWrite\",\n                        \"createOption\": \"FromImage\"\n                    },\n                    \"dataDisks\": [\n                        {\n                            \"name\":\"vm-data-disk\",\n                            \"diskSizeGB\":16,\n                            \"createOption\": \"Empty\",\n                            \"lun\":0\n                        }\n                    ]\n                },\n                \"networkProfile\": {\n                    \"networkInterfaces\": [\n                        {\n                            \"id\": \"[resourceId('Microsoft.Network\/networkInterfaces', 'app-interface')]\"\n                        }\n                    ]\n                },\n                \"diagnosticsProfile\": {\n                    \"bootDiagnostics\": {\n                        \"enabled\": true,\n                        \"storageUri\": \"[reference(resourceId('Microsoft.Storage\/storageAccounts\/', toLower('rezastore8677676'))).primaryEndpoints.blob]\"\n                    }\n                }\n            }\n        }\n    ],\n    \"outputs\": {}\n}<\/code><\/pre><p class=\"wp-block-paragraph\">This is a big template! Let me explain the important parts.<\/p><h3 class=\"wp-block-heading\">Understanding Virtual Network<\/h3><pre class=\"wp-block-code\"><code>{\n    \"name\": \"appnetwork\",\n    \"type\": \"Microsoft.Network\/virtualNetworks\",\n    \"properties\": {\n        \"addressSpace\": {\n            \"addressPrefixes\": [\"10.0.0.0\/16\"]\n        },\n        \"subnets\": [\n            {\n                \"name\": \"SubnetA\",\n                \"properties\": {\n                    \"addressPrefix\": \"10.0.0.0\/24\"\n                }\n            }\n        ]\n    }\n}<\/code><\/pre><p class=\"wp-block-paragraph\">Virtual Network (VNet) is like your private network in Azure.<\/p><p class=\"wp-block-paragraph\">IP addressing explained:<\/p><ul class=\"wp-block-list\"><li>10.0.0.0\/16 = 65,536 IP addresses available (the whole network)<\/li><li>10.0.0.0\/24 = 256 IP addresses available (one subnet)<\/li><\/ul><p class=\"wp-block-paragraph\">Why \/16 and \/24?<\/p><p class=\"wp-block-paragraph\">The number after \/ tells how many IP addresses you get:<\/p><ul class=\"wp-block-list\"><li>\/16 = 65,536 addresses (10.0.0.0 to 10.0.255.255)<\/li><li>\/24 = 256 addresses (10.0.0.0 to 10.0.0.255)<\/li><\/ul><p class=\"wp-block-paragraph\">Azure reserves 5 addresses:<\/p><ul class=\"wp-block-list\"><li>10.0.0.0 &#8211; Network address<\/li><li>10.0.0.1 &#8211; Default gateway<\/li><li>10.0.0.2 &#8211; DNS server<\/li><li>10.0.0.3 &#8211; DNS server<\/li><li>10.0.0.255 &#8211; Broadcast address<\/li><\/ul><p class=\"wp-block-paragraph\">So SubnetA actually has 251 usable IP addresses (256 &#8211; 5).<\/p><p class=\"wp-block-paragraph\">My VM will get IP like 10.0.0.4 or 10.0.0.5.<\/p><p class=\"wp-block-paragraph\">Why two subnets?<\/p><ul class=\"wp-block-list\"><li>SubnetA: For web servers<\/li><li>SubnetB: For database servers (future use)<\/li><\/ul><p class=\"wp-block-paragraph\">This separates different types of servers for security.<\/p><h3 class=\"wp-block-heading\">Understanding Public IP<\/h3><pre class=\"wp-block-code\"><code>{\n    \"name\": \"app-ip\",\n    \"type\": \"Microsoft.Network\/publicIPAddresses\",\n    \"properties\": {\n        \"publicIPAllocationMethod\": \"Dynamic\"\n    }\n}<\/code><\/pre><p class=\"wp-block-paragraph\">Public IP lets me connect to the VM from the internet.<\/p><p class=\"wp-block-paragraph\">Dynamic vs Static:<\/p><ul class=\"wp-block-list\"><li>Dynamic: IP changes when VM stops\/starts &#8211; FREE<\/li><li>Static: IP never changes &#8211; costs $3\/month<\/li><\/ul><p class=\"wp-block-paragraph\">I use Dynamic for learning to save money. For production, use Static.<\/p><h3 class=\"wp-block-heading\">Understanding Network Interface<\/h3><pre class=\"wp-block-code\"><code>{\n    \"name\": \"app-interface\",\n    \"type\": \"Microsoft.Network\/networkInterfaces\",\n    \"properties\": {\n        \"ipConfigurations\": [\n            {\n                \"name\": \"ipConfig1\",\n                \"properties\": {\n                    \"privateIPAllocationMethod\": \"Dynamic\",\n                    \"publicIPAddress\": {\n                        \"id\": \"[resourceId('Microsoft.Network\/publicIPAddresses', 'app-ip')]\"\n                    },\n                    \"subnet\": {\n                        \"id\": \"[resourceId('Microsoft.Network\/virtualNetworks\/subnets', 'appnetwork', 'SubnetA')]\"\n                    }\n                }\n            }\n        ]\n    },\n    \"dependsOn\": [\n        \"[resourceId('Microsoft.Network\/publicIPAddresses', 'app-ip')]\",\n        \"[resourceId('Microsoft.Network\/virtualNetworks', 'appnetwork')]\"\n    ]\n}<\/code><\/pre><p class=\"wp-block-paragraph\">Network Interface is like a network card. It connects VM to the network.<\/p><p class=\"wp-block-paragraph\">Important parts:<\/p><ul class=\"wp-block-list\"><li>privateIPAllocationMethod: Dynamic &#8211; Azure gives IP automatically<\/li><li>publicIPAddress &#8211; Links to the public IP I created<\/li><li>subnet &#8211; Connects to SubnetA<\/li><\/ul><p class=\"wp-block-paragraph\">dependsOn is critical!<\/p><p class=\"wp-block-paragraph\">The Network Interface needs two things first:<\/p><ol class=\"wp-block-list\"><li>Public IP must exist<\/li><li>Virtual Network must exist<\/li><\/ol><p class=\"wp-block-paragraph\">Without dependsOn, deployment fails!<\/p><h3 class=\"wp-block-heading\">Understanding Storage Account<\/h3><pre class=\"wp-block-code\"><code>{\n    \"name\": \"rezastore8677676\",\n    \"type\": \"Microsoft.Storage\/storageAccounts\",\n    \"sku\": {\n        \"name\": \"Standard_LRS\"\n    },\n    \"kind\": \"StorageV2\"\n}<\/code><\/pre><p class=\"wp-block-paragraph\">Why does VM need storage?<\/p><p class=\"wp-block-paragraph\">For boot diagnostics &#8211; screenshots and logs when VM has problems.<\/p><p class=\"wp-block-paragraph\">Standard_LRS means:<\/p><ul class=\"wp-block-list\"><li>Standard = Uses hard drives (cheaper than SSD)<\/li><li>LRS = Locally Redundant Storage (3 copies in same datacenter)<\/li><\/ul><p class=\"wp-block-paragraph\">This is the cheapest option, good for diagnostics.<\/p><p class=\"wp-block-paragraph\">Note: VM&#8217;s actual disk is separate! This storage is only for troubleshooting.<\/p><h3 class=\"wp-block-heading\">Understanding Network Security Group<\/h3><pre class=\"wp-block-code\"><code>{\n    \"name\": \"app-nsg\",\n    \"type\": \"Microsoft.Network\/networkSecurityGroups\",\n    \"properties\": {\n        \"securityRules\": [\n            {\n                \"name\": \"Allow-RDP\",\n                \"properties\": {\n                    \"protocol\": \"Tcp\",\n                    \"sourcePortRange\": \"*\",\n                    \"destinationPortRange\": \"3389\",\n                    \"sourceAddressPrefix\": \"*\",\n                    \"destinationAddressPrefix\": \"*\",\n                    \"access\": \"Allow\",\n                    \"priority\": 100,\n                    \"direction\": \"Inbound\"\n                }\n            }\n        ]\n    }\n}<\/code><\/pre><p class=\"wp-block-paragraph\">NSG is like a firewall. It controls what traffic can reach the VM.<\/p><p class=\"wp-block-paragraph\">Understanding the rule:<\/p><ul class=\"wp-block-list\"><li>protocol: Tcp &#8211; Rule for TCP traffic<\/li><li>sourcePortRange: &#8220;*&#8221; &#8211; Allow from any port (client side)<\/li><li>destinationPortRange: 3389 &#8211; Allow to port 3389 (RDP port)<\/li><li>sourceAddressPrefix: &#8220;*&#8221; &#8211; Allow from any IP address<\/li><li>access: Allow &#8211; Let the traffic through<\/li><li>priority: 100 &#8211; Lower number = checked first<\/li><li>direction: Inbound &#8211; Traffic coming TO the VM<\/li><\/ul><p class=\"wp-block-paragraph\">Security Warning!<\/p><p class=\"wp-block-paragraph\">sourceAddressPrefix: &#8220;*&#8221; means anyone can try to connect! This is only OK for home lab testing.<\/p><p class=\"wp-block-paragraph\">For production, change to:<\/p><pre class=\"wp-block-code\"><code>\"sourceAddressPrefix\": \"1.2.3.4\"  \/\/ Your IP only<\/code><\/pre><h3 class=\"wp-block-heading\">Understanding the Virtual Machine<\/h3><p class=\"wp-block-paragraph\">Now the main part &#8211; the VM itself!<\/p><h3 class=\"wp-block-heading\">Hardware Profile<\/h3><pre class=\"wp-block-code\"><code>\"hardwareProfile\": {\n    \"vmSize\": \"Standard_D2s_v3\"\n}<\/code><\/pre><p class=\"wp-block-paragraph\">Standard_D2s_v3 means:<\/p><ul class=\"wp-block-list\"><li>2 vCPUs<\/li><li>8 GB RAM<\/li><li>Uses SSD (the &#8216;s&#8217; means SSD)<\/li><li>Costs ~$70\/month if running 24\/7<\/li><\/ul><p class=\"wp-block-paragraph\">For cheaper option, use Standard_B2s (~$30\/month).<\/p><h3 class=\"wp-block-heading\">OS Profile<\/h3><pre class=\"wp-block-code\"><code>\"osProfile\": {\n    \"computerName\": \"appvm\",\n    \"adminUsername\": \"demousr\",\n    \"adminPassword\": \"Azure@123\"\n}<\/code><\/pre><p class=\"wp-block-paragraph\">computerName &#8211; VM hostname<\/p><p class=\"wp-block-paragraph\">adminUsername and adminPassword &#8211; Login credentials<\/p><p class=\"wp-block-paragraph\">My password is weak! Only for learning. Use strong passwords in production.<\/p><h3 class=\"wp-block-heading\">Storage Profile &#8211; OS Disk<\/h3><pre class=\"wp-block-code\"><code>\"storageProfile\": {\n    \"imageReference\": {\n        \"publisher\": \"MicrosoftWindowsServer\",\n        \"offer\": \"WindowsServer\",\n        \"sku\": \"2019-Datacenter\",\n        \"version\": \"latest\"\n    },\n    \"osDisk\": {\n        \"name\": \"windowsVM1OSDisk\",\n        \"caching\": \"ReadWrite\",\n        \"createOption\": \"FromImage\"\n    }\n}<\/code><\/pre><p class=\"wp-block-paragraph\">imageReference tells Azure what OS to install:<\/p><ul class=\"wp-block-list\"><li>publisher: MicrosoftWindowsServer<\/li><li>offer: WindowsServer<\/li><li>sku: 2019-Datacenter<\/li><li>version: latest<\/li><\/ul><p class=\"wp-block-paragraph\">osDisk:<\/p><ul class=\"wp-block-list\"><li>caching: ReadWrite &#8211; Cache reads and writes for better performance<\/li><li>createOption: FromImage &#8211; Create new disk from the Windows image<\/li><\/ul><p class=\"wp-block-paragraph\">Azure automatically creates 127 GB disk for Windows Server.<\/p><h3 class=\"wp-block-heading\">Storage Profile &#8211; Data Disk<\/h3><pre class=\"wp-block-code\"><code>\"dataDisks\": [\n    {\n        \"name\":\"vm-data-disk\",\n        \"diskSizeGB\":16,\n        \"createOption\": \"Empty\",\n        \"lun\":0\n    }\n]<\/code><\/pre><p class=\"wp-block-paragraph\">This creates an extra 16 GB disk for data.<\/p><p class=\"wp-block-paragraph\">lun = Logical Unit Number (like drive letter in Windows)<\/p><ul class=\"wp-block-list\"><li>lun:0 = First data disk<\/li><li>lun:1 = Second data disk (if you add more)<\/li><\/ul><p class=\"wp-block-paragraph\">createOption: Empty means the disk is blank. After VM starts, I need to format it in Windows.<\/p><h3 class=\"wp-block-heading\">Network Profile<\/h3><pre class=\"wp-block-code\"><code>\"networkProfile\": {\n    \"networkInterfaces\": [\n        {\n            \"id\": \"[resourceId('Microsoft.Network\/networkInterfaces', 'app-interface')]\"\n        }\n    ]\n}<\/code><\/pre><p class=\"wp-block-paragraph\">This connects the VM to the Network Interface we created.<\/p><h3 class=\"wp-block-heading\">Boot Diagnostics<\/h3><pre class=\"wp-block-code\"><code>\"diagnosticsProfile\": {\n    \"bootDiagnostics\": {\n        \"enabled\": true,\n        \"storageUri\": \"[reference(resourceId('Microsoft.Storage\/storageAccounts\/', toLower('rezastore8677676'))).primaryEndpoints.blob]\"\n    }\n}<\/code><\/pre><p class=\"wp-block-paragraph\">What is this complex line?<\/p><pre class=\"wp-block-code\"><code>\"[reference(resourceId('Microsoft.Storage\/storageAccounts\/', toLower('rezastore8677676'))).primaryEndpoints.blob]\"<\/code><\/pre><p class=\"wp-block-paragraph\">Let me break it down:<\/p><ol class=\"wp-block-list\"><li>resourceId(&#8216;Microsoft.Storage\/storageAccounts\/&#8217;, toLower(&#8216;rezastore8677676&#8217;)) &#8211; Get the storage account<\/li><li>reference(&#8230;) &#8211; Get properties of the storage account<\/li><li>.primaryEndpoints.blob &#8211; Get the blob URL<\/li><\/ol><p class=\"wp-block-paragraph\">Result: https:\/\/rezastore8677676.blob.core.windows.net\/<\/p><p class=\"wp-block-paragraph\">This is where Azure saves VM screenshots and logs.<\/p><h3 class=\"wp-block-heading\">How I Deployed This<\/h3><pre class=\"wp-block-code\"><code># Create resource group\naz group create \\\n  --name vm-test-grp \\\n  --location \"North Europe\"\n\n# Deploy the template\naz deployment group create \\\n  --resource-group vm-test-grp \\\n  --template-file 03-AzureVirtualMachines.json<\/code><\/pre><p class=\"wp-block-paragraph\">Deployment took about 7 minutes.<\/p><h3 class=\"wp-block-heading\">What Happens During Deployment<\/h3><p class=\"wp-block-paragraph\">Azure creates resources in this order:<\/p><ol class=\"wp-block-list\"><li>Network Security Group (no dependencies)<\/li><li>Storage Account (no dependencies)<\/li><li>Virtual Network (needs NSG)<\/li><li>Public IP (no dependencies)<\/li><li>Network Interface (needs VNet and Public IP)<\/li><li>Virtual Machine (needs Network Interface and Storage)<\/li><\/ol><p class=\"wp-block-paragraph\">ARM is smart &#8211; it figures out the order automatically based on dependsOn!<\/p><h3 class=\"wp-block-heading\">Testing My VM<\/h3><p class=\"wp-block-paragraph\">After deployment:<\/p><ol class=\"wp-block-list\"><li>Get public IP from Azure portal<\/li><li>Open Remote Desktop Connection<\/li><li>Enter IP address<\/li><li>Login: demousr \/ Azure@123<\/li><li>Connected!<\/li><\/ol><p class=\"wp-block-paragraph\">Inside the VM:<\/p><ul class=\"wp-block-list\"><li>C: drive = OS Disk (127 GB)<\/li><li>D: drive = Temp disk (comes with VM)<\/li><li>Data disk not visible yet<\/li><\/ul><p class=\"wp-block-paragraph\">To use data disk, I opened Disk Management in Windows:<\/p><ol class=\"wp-block-list\"><li>Initialize disk<\/li><li>Create partition<\/li><li>Format as NTFS<\/li><li>Assign drive letter E:<\/li><\/ol><p class=\"wp-block-paragraph\">Now I have E: drive with 16 GB!<\/p><h3 class=\"wp-block-heading\">My Mistakes and Fixes<\/h3><h3 class=\"wp-block-heading\">Mistake 1: Wrong subnet resourceId<\/h3><pre class=\"wp-block-code\"><code>\"subnet\": {\n    \"id\": \"[resourceId('Microsoft.Network\/subnets', 'SubnetA')]\"\n}<\/code><\/pre><p class=\"wp-block-paragraph\">Error: &#8220;Resource not found&#8221;<\/p><p class=\"wp-block-paragraph\">Fix: Use parent\/child format:<\/p><pre class=\"wp-block-code\"><code>\"subnet\": {\n    \"id\": \"[resourceId('Microsoft.Network\/virtualNetworks\/subnets', 'appnetwork', 'SubnetA')]\"\n}<\/code><\/pre><h3 class=\"wp-block-heading\">Mistake 2: Storage account name uppercase<\/h3><pre class=\"wp-block-code\"><code>\"name\": \"RezaStore8677676\"<\/code><\/pre><p class=\"wp-block-paragraph\">Error: &#8220;Storage account name must be lowercase&#8221;<\/p><p class=\"wp-block-paragraph\">Fix: Use lowercase only: rezastore8677676<\/p><h3 class=\"wp-block-heading\">Mistake 3: Forgot VM dependency on NIC<\/h3><pre class=\"wp-block-code\"><code>\"dependsOn\": [\n    \"[resourceId('Microsoft.Storage\/storageAccounts', 'rezastore8677676')]\"\n]<\/code><\/pre><p class=\"wp-block-paragraph\">Error: &#8220;Network interface does not exist&#8221;<\/p><p class=\"wp-block-paragraph\">Fix: Add NIC to dependsOn:<\/p><pre class=\"wp-block-code\"><code>\"dependsOn\": [\n    \"[resourceId('Microsoft.Storage\/storageAccounts', 'rezastore8677676')]\",\n    \"[resourceId('Microsoft.Network\/networkInterfaces', 'app-interface')]\"\n]<\/code><\/pre><h3 class=\"wp-block-heading\">Mistake 4: Forgot to format data disk<\/h3><p class=\"wp-block-paragraph\">After deployment, I couldn&#8217;t see E: drive!<\/p><p class=\"wp-block-paragraph\">Issue: Empty disks need formatting.<\/p><p class=\"wp-block-paragraph\">Fix: Used Disk Management in Windows to initialize and format the disk.<\/p>","protected":false},"excerpt":{"rendered":"<p>Why VMs Are Complex Hello everyone! Today I want to share my experience deploying Azure Virtual Machines with ARM templates. This was&hellip;<\/p>\n","protected":false},"author":2,"featured_media":123,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_rezaops_part":"3","_rezaops_linkedin_url":"https:\/\/www.linkedin.com\/pulse\/azure-virtual-machines-complete-arm-template-guide-reza-chegini-ue4tc\/","footnotes":""},"categories":[50,10],"tags":[53,52,8,55,57],"series":[51],"class_list":["post-101","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-azure","category-devops","tag-arm-templates","tag-azure","tag-devops","tag-iac","tag-virtual-machines","series-azure-arm-templates"],"jetpack_featured_media_url":"https:\/\/rezachegini.com\/wp-content\/uploads\/2026\/10\/azure-virtual-machines-arm-guide-cover.png","_links":{"self":[{"href":"https:\/\/rezachegini.com\/index.php?rest_route=\/wp\/v2\/posts\/101","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/rezachegini.com\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/rezachegini.com\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/rezachegini.com\/index.php?rest_route=\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/rezachegini.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=101"}],"version-history":[{"count":1,"href":"https:\/\/rezachegini.com\/index.php?rest_route=\/wp\/v2\/posts\/101\/revisions"}],"predecessor-version":[{"id":102,"href":"https:\/\/rezachegini.com\/index.php?rest_route=\/wp\/v2\/posts\/101\/revisions\/102"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/rezachegini.com\/index.php?rest_route=\/wp\/v2\/media\/123"}],"wp:attachment":[{"href":"https:\/\/rezachegini.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=101"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/rezachegini.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=101"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/rezachegini.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=101"},{"taxonomy":"series","embeddable":true,"href":"https:\/\/rezachegini.com\/index.php?rest_route=%2Fwp%2Fv2%2Fseries&post=101"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}