Stand up an Azure VM with Terraform, batteries included
An Azure virtual machine is never just one resource — it needs a network to live in. This builder generates the complete dependency chain (resource group, virtual network, subnet, NIC) plus the azurerm_linux_virtual_machine itself, with the cross-references already wired so terraform apply works first time.
How it works
Terraform creates Azure resources in dependency order using interpolated references. The VM references its network interface ID, the NIC references the subnet, the subnet references the virtual network, and everything references the resource group’s name and location. By chaining azurerm_resource_group.<id>.name style references, Terraform builds the correct graph and provisions resources in the right sequence.
For authentication, the recommended SSH path injects an admin_ssh_key block that reads your public key with file("~/.ssh/id_rsa.pub"). The password path sets disable_password_authentication = false and pulls the secret from a sensitive Terraform variable, so the credential never appears in your committed HCL.
What gets generated
The output contains six resource blocks in dependency order:
azurerm_resource_group— logical container with name and Azure region.azurerm_virtual_network— the private address space (for example10.0.0.0/16).azurerm_subnet— a slice of that space for the VM (for example10.0.1.0/24).azurerm_network_interface— connects the VM to the subnet with a private IP.azurerm_linux_virtual_machine— the compute resource itself, referencing the NIC ID and declaring the OS disk.- Either an
admin_ssh_keyblock or asensitivevariable for password credentials.
No public IP or network security group is included by default, so the VM is private until you add those blocks.
Choosing a VM size
Azure sizes follow a naming convention: Standard_B2s is a burstable 2-core VM suited for dev work; Standard_D4s_v5 is a general-purpose 4-core instance good for web workloads; Standard_E8s_v5 is memory-optimised. For a dev or staging VM on a tight budget, Standard_B2s or Standard_B4ms keep cost low. For production, prefer the v5 Dsv5 or Esv5 families which offer better performance-per-dollar.
Common mistakes
- Forgetting the NIC ID reference. Omitting
network_interface_idscauses a plan error. The builder wires this automatically. - Hardcoding the admin password. Any string literal in HCL ends up in
.tfstatein plaintext. Always use asensitivevariable or a key vault reference. - Missing the
gen2suffix on the image. Ubuntu 22.04 on Azure requiresgen2in the SKU for most modern VM sizes; older SKUs fail on select hardware families.
Tips and notes
- Prefer SSH keys — they avoid password brute-forcing and don’t leak into state as readable strings.
- The OS image is pinned to Ubuntu 22.04 LTS gen2; change the
source_image_referenceblock if you need a different distro. - Choose
Premium_LRSfor production disks andStandard_LRSto minimise cost on dev VMs. - Add a
azurerm_network_security_groupand aazurerm_public_ipif the VM needs inbound access — this template keeps it internal-only by default.