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!

Apr 20, 2025 - 10:34
 0
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:

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!