DEV Community

Smallsun2025
Smallsun2025

Posted on

Deploy Azure VM from Custom Image using Terraform

πŸ—‚ Project Structure
This Terraform project consists of the following files:
azure-vm-from-image-demo/
β”œβ”€β”€ main.tf # Core infrastructure resources
β”œβ”€β”€ variables.tf # Input variables
β”œβ”€β”€ terraform.tfvars # Variable values (e.g., image ID, subnet ID)
β”œβ”€β”€ outputs.tf # Useful outputs (e.g., VM ID, IP)

πŸ”§ Terraform Configuration Explained

  1. Resource Group + Network Interface In main.tf, we start by creating a resource group and a network interface that connects to an existing subnet:

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

resource "azurerm_network_interface" "nic" {
name = "vm-from-image-nic"
location = azurerm_resource_group.rg.location
resource_group_name = azurerm_resource_group.rg.name

ip_configuration {
name = "internal"
subnet_id = var.subnet_id
private_ip_address_allocation = "Dynamic"
}
}

πŸ’‘ Explanation: This NIC connects the VM to the specified subnet. You’ll need to pass in an existing subnet ID (from a previous project or manual setup).

  1. Virtual Machine from Custom Image

resource "azurerm_linux_virtual_machine" "vm" {
name = var.vm_name
resource_group_name = azurerm_resource_group.rg.name
location = azurerm_resource_group.rg.location
size = "Standard_B1s"
admin_username = var.admin_username
admin_password = var.admin_password
network_interface_ids = [azurerm_network_interface.nic.id]
disable_password_authentication = false

source_image_id = var.custom_image_id

os_disk {
caching = "ReadWrite"
storage_account_type = "Standard_LRS"
}
}
πŸ’‘ Explanation: Instead of using a marketplace image, we’re referencing an existing custom image by its full resource ID (e.g., /subscriptions/.../images/demo-vm-image).

  1. Variables + tfvars To keep the project reusable and configurable, we use the following variables in variables.tf and set actual values in terraform.tfvars: variable "custom_image_id" { description = "The resource ID of the custom managed image" type = string }

variable "subnet_id" {
description = "Subnet ID for VM NIC"
type = string
}
And in terraform.tfvars:

custom_image_id = "/subscriptions/xxxxx/resourceGroups/xxx/providers/Microsoft.Compute/images/demo-vm-image"
subnet_id = "/subscriptions/xxxxx/resourceGroups/xxx/providers/Microsoft.Network/virtualNetworks/demo-vnet/subnets/demo-subnet"
πŸ›  You can get these IDs from previous deployments or from the Azure Portal.

  1. Outputs We output useful values like VM ID and private IP address: output "vm_id" { value = azurerm_linux_virtual_machine.vm.id }

output "private_ip" {
value = azurerm_network_interface.nic.private_ip_address
}

πŸš€ Deployment Steps
To deploy this project, follow these steps:

az login
terraform init
terraform plan
terraform apply

βœ… Summary
This post showed how to:

Deploy a VM from a custom managed image in Azure

Use Terraform to automate the setup

Connect the VM to an existing subnet

Maintain modular, reusable code using variables and outputs

Top comments (0)

Some comments may only be visible to logged-in visitors. Sign in to view all comments.