Skip to main content

Virtual Machine IaC

We can use Terraform and various other languages to create a virtual machine.

# Azure Provider
# In this case we're using the credentials from the logged-in account
# We're not concerned about where the state file is.
provider "azurerm" {
features {}
}

variable "resource_group_name" {
description = "Resource group name"
type = string
default = "test-rg"
}

variable "location" {
description = "Azure region where resources will be created"
type = string
default = "eastus"
}

variable "vm_name" {
description = "Virtual machine name"
type = string
default = "test"
}

variable "vnet_name" {
description = "Virtual Network name"
type = string
default = "test"
}

# Resource Group
resource "azurerm_resource_group" "rg" {
name = var.resource_group_name
location = var.location
}

# Virtual Network
resource "azurerm_virtual_network" "vnet" {
name = "${var.vnet_name}_vnet"
# We could use the variable, but if you can get it from the resource group it's always better, avoids errors
location = azurerm_resource_group.rg.location
resource_group_name = azurerm_resource_group.rg.name
address_space = ["10.0.0.0/16"]
}

# Subnet
resource "azurerm_subnet" "subnet" {
name = "${var.vnet_name}_subnet"
resource_group_name = azurerm_resource_group.rg.name
virtual_network_name = azurerm_virtual_network.vnet.name
address_prefixes = ["10.0.1.0/24"]
}

# A VM needs a network interface
resource "azurerm_network_interface" "nic" {
name = "${var.vm_name}_nic"
location = azurerm_resource_group.rg.location
resource_group_name = azurerm_resource_group.rg.name

ip_configuration {
name = "ip-configuration"
subnet_id = azurerm_subnet.subnet.id
private_ip_address_allocation = "Dynamic" # Any IP from the subnet above
}
}

# VM
resource "azurerm_virtual_machine" "vm" {
name = "${var.vm_name}_vm"
location = azurerm_resource_group.rg.location
resource_group_name = azurerm_resource_group.rg.name
network_interface_ids = [azurerm_network_interface.nic.id]
vm_size = "Standard_D2pls_v5"

storage_os_disk {
name = "my-osdisk"
caching = "ReadWrite"
create_option = "FromImage"
managed_disk_type = "Standard_LRS"
}

storage_image_reference {
publisher = "Canonical"
offer = "ubuntu-24_04-lts"
sku = "server-arm64"
version = "latest"
}

os_profile {
computer_name = "${var.vm_name}"
admin_username = "adminuser"
admin_password = "SuperSecurePassword123"
}

os_profile_linux_config {
disable_password_authentication = false
}
}

# Output
output "ip_address" {
value = azurerm_network_interface.nic.private_ip_address
}