How to Create a Virtual Machine on Azure Using a Reusable Terraform Script
Deploying infrastructure shouldn't be a copy-paste headache. Here's how to make your Azure VM setup repeatable and clean using Terraform. When I started using Terraform to manage infrastructure on Azure, one thing became clear very quickly: writing the same Terraform config every time gets old fast. In this blog, I'm going to show you how to create an Azure Virtual Machine using a reusable Terraform script. By the end of this post, you'll have a modular setup you can use across projects—without rewriting the whole thing each time. What You’ll Need Before we begin, make sure you’ve got the following: An Azure account Terraform installed Azure CLI installed and logged in (az login) Step 1: Create the Folder Structure Let’s keep things clean. mkdir terraform-azure-vm cd terraform-azure-vm mkdir modules mkdir modules/vm We’ll keep our reusable VM code inside modules/vm and the environment-specific code in the root folder. Step 2: Build the Reusable VM Module Inside modules/vm/, create these files: main.tf resource "azurerm_network_interface" "nic" { name = "${var.vm_name}-nic" location = var.location resource_group_name = var.resource_group_name ip_configuration { name = "internal" subnet_id = var.subnet_id private_ip_address_allocation = "Dynamic" } } resource "azurerm_windows_virtual_machine" "vm" { name = var.vm_name resource_group_name = var.resource_group_name location = var.location size = var.vm_size admin_username = var.admin_username admin_password = var.admin_password network_interface_ids = [azurerm_network_interface.nic.id] os_disk { caching = "ReadWrite" storage_account_type = "Standard_LRS" } source_image_reference { publisher = "MicrosoftWindowsServer" offer = "WindowsServer" sku = "2019-Datacenter" version = "latest" } } variables.tf variable "vm_name" {} variable "resource_group_name" {} variable "location" {} variable "subnet_id" {} variable "vm_size" {} variable "admin_username" {} variable "admin_password" {} Step 3: Use the Module in Your Environment Go to the root folder and create: main.tf provider "azurerm" { features {} } module "vm" { source = "./modules/vm" vm_name = "dev-vm" resource_group_name = azurerm_resource_group.rg.name location = azurerm_resource_group.rg.location subnet_id = azurerm_subnet.subnet.id vm_size = "Standard_B1s" admin_username = "azureuser" admin_password = "MySecureP@ssw0rd123" } resource "azurerm_resource_group" "rg" { name = "dev-rg" location = "East US" } resource "azurerm_virtual_network" "vnet" { name = "dev-vnet" address_space = ["10.0.0.0/16"] location = azurerm_resource_group.rg.location resource_group_name = azurerm_resource_group.rg.name } resource "azurerm_subnet" "subnet" { name = "dev-subnet" resource_group_name = azurerm_resource_group.rg.name virtual_network_name = azurerm_virtual_network.vnet.name address_prefixes = ["10.0.1.0/24"] } Step 4: Don’t Forget the Backend (Optional but recommended) For team use or remote state management, configure a backend.tf file using Azure Storage Account. Step 5: Deploy It! terraform init terraform plan terraform apply Done! Your Azure VM is up and running. Wrapping Up With this modular approach, the next time you need a VM? Just tweak a few inputs. No more rewriting long scripts or fighting with syntax every time. Let me know in the comments if you'd like to see a Linux version, auto-shutdown scripts, or cost-saving tricks next! Happy Terraforming!

Deploying infrastructure shouldn't be a copy-paste headache. Here's how to make your Azure VM setup repeatable and clean using Terraform.
When I started using Terraform to manage infrastructure on Azure, one thing became clear very quickly: writing the same Terraform config every time gets old fast.
In this blog, I'm going to show you how to create an Azure Virtual Machine using a reusable Terraform script. By the end of this post, you'll have a modular setup you can use across projects—without rewriting the whole thing each time.
What You’ll Need
Before we begin, make sure you’ve got the following:
- An Azure account
- Terraform installed
- Azure CLI installed and logged in (
az login
)
Step 1: Create the Folder Structure
Let’s keep things clean.
mkdir terraform-azure-vm
cd terraform-azure-vm
mkdir modules
mkdir modules/vm
We’ll keep our reusable VM code inside modules/vm
and the environment-specific code in the root folder.
Step 2: Build the Reusable VM Module
Inside modules/vm/
, create these files:
main.tf
resource "azurerm_network_interface" "nic" {
name = "${var.vm_name}-nic"
location = var.location
resource_group_name = var.resource_group_name
ip_configuration {
name = "internal"
subnet_id = var.subnet_id
private_ip_address_allocation = "Dynamic"
}
}
resource "azurerm_windows_virtual_machine" "vm" {
name = var.vm_name
resource_group_name = var.resource_group_name
location = var.location
size = var.vm_size
admin_username = var.admin_username
admin_password = var.admin_password
network_interface_ids = [azurerm_network_interface.nic.id]
os_disk {
caching = "ReadWrite"
storage_account_type = "Standard_LRS"
}
source_image_reference {
publisher = "MicrosoftWindowsServer"
offer = "WindowsServer"
sku = "2019-Datacenter"
version = "latest"
}
}
variables.tf
variable "vm_name" {}
variable "resource_group_name" {}
variable "location" {}
variable "subnet_id" {}
variable "vm_size" {}
variable "admin_username" {}
variable "admin_password" {}
Step 3: Use the Module in Your Environment
Go to the root folder and create:
main.tf
provider "azurerm" {
features {}
}
module "vm" {
source = "./modules/vm"
vm_name = "dev-vm"
resource_group_name = azurerm_resource_group.rg.name
location = azurerm_resource_group.rg.location
subnet_id = azurerm_subnet.subnet.id
vm_size = "Standard_B1s"
admin_username = "azureuser"
admin_password = "MySecureP@ssw0rd123"
}
resource "azurerm_resource_group" "rg" {
name = "dev-rg"
location = "East US"
}
resource "azurerm_virtual_network" "vnet" {
name = "dev-vnet"
address_space = ["10.0.0.0/16"]
location = azurerm_resource_group.rg.location
resource_group_name = azurerm_resource_group.rg.name
}
resource "azurerm_subnet" "subnet" {
name = "dev-subnet"
resource_group_name = azurerm_resource_group.rg.name
virtual_network_name = azurerm_virtual_network.vnet.name
address_prefixes = ["10.0.1.0/24"]
}
Step 4: Don’t Forget the Backend (Optional but recommended)
For team use or remote state management, configure a backend.tf
file using Azure Storage Account.
Step 5: Deploy It!
terraform init
terraform plan
terraform apply
Done! Your Azure VM is up and running.
Wrapping Up
With this modular approach, the next time you need a VM? Just tweak a few inputs. No more rewriting long scripts or fighting with syntax every time.
Let me know in the comments if you'd like to see a Linux version, auto-shutdown scripts, or cost-saving tricks next!
Happy Terraforming!