Create an Azure VM using Terraform.

Terraform is currently one of the most popular infrastructure automation tool to manage multi cloud environment. This blog post will show case using Terraform to create a resource and Virtual Machine in Azure.

This configuration file will create following resources in Azure.

  • 1. Resourcegroup
  • 2. Virtual Network
  • 3. Subnet
  • 4. Network Security Group
  • 5. Virtual Machine

mian.tf

terraform {
  required_providers {
    azurerm = {
      source = "hashicorp/azurerm"
      version = ">=2.6"
    }
  }
}

provider "azurerm" {
    version         =   ">=2.6"
    client_id       =   "var.client_id"
    client_secret   =   "var.client_secret"
    subscription_id =   "var.subscription_id"
    tenant_id       =   "var.tenant_id"
    
    features {}
}


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


resource "azurerm_virtual_network" "vnet" {
    name                  =   "LearnTerraform-Vnet"
    resource_group_name   =   azurerm_resource_group.rg.name
    location              =   azurerm_resource_group.rg.location
    address_space         =   [var.vnet_address_range]
    
}

resource "azurerm_subnet" "web" {
    name                  =   "LearnTerraform-subnet"
    resource_group_name   =   azurerm_resource_group.rg.name
    virtual_network_name  =   azurerm_virtual_network.vnet.name
    address_prefixes      =   [var.subnet_address_range]
}

resource "azurerm_network_security_group" "nsg" {
    name                        =       "LearnTerraform-nsg"
    resource_group_name         =       azurerm_resource_group.rg.name
    location                    =       azurerm_resource_group.rg.location
    
    security_rule {
    name                        =       "Allow_RDP"
    priority                    =       1000
    direction                   =       "Inbound"
    access                      =       "Allow"
    protocol                    =       "Tcp"
    source_port_range           =       "*"
    destination_port_range      =       3389
    source_address_prefix       =       "10.0.1.10"
    destination_address_prefix  =       "*"
    
    }
}


resource "azurerm_subnet_network_security_group_association" "subnet-nsg" {
subnet_id                    =       azurerm_subnet.web.id
network_security_group_id    =       azurerm_network_security_group.nsg.id
}

resource "azurerm_public_ip" "pip" {
name                         = "winvm-public-    
resource_group_name          = azurerm_resource_group.rg.name
location                     = azurerm_resource_group.rg.location
allocation_method            = var.allocation_method[0]
  
}


resource "azurerm_network_interface" "nic" {
name                              =  "LearnTerraform-wimvm-nic"
resource_group_name               =   azurerm_resource_group.rg.name
location                          =   azurerm_resource_group.rg.location
   
    ip_configuration                  {
        name                          =  "wimvm-nic-ipconfig"
        subnet_id                     =   azurerm_subnet.web.id
        public_ip_address_id          =   azurerm_public_ip.pip.id
        private_ip_address_allocation =   var.allocation_method[1]
    }
}

resource "azurerm_windows_virtual_machine" "vm" {
  name                              =   "LearnTerraform-winvm"
  resource_group_name               =   azurerm_resource_group.rg.name
  location                          =   azurerm_resource_group.rg.location
  network_interface_ids             =   [azurerm_network_interface.nic.id]
  size                              =   var.virtual_machine_size
  computer_name                     =   var.computer_name
  admin_username                    =   var.admin_username
  admin_password                    =   var.admin_password

    os_disk  {
        name                          =   "winvm-os-disk"
        caching                       =   var.os_disk_caching
        storage_account_type          =   var.os_disk_storage_account_type
        disk_size_gb                  =   var.os_disk_size_gb
    }

    source_image_reference {
        publisher                     =   var.publisher
        offer                         =   var.offer
        sku                           =   var.sku
        version                       =   var.vm_image_version
    }

    
}

variables.tf

variable "client_id" {
    description =   "This is the application id from the service principal in Azure AD"
    type        =   string
}

variable "client_secret" {
    description =   "This is the secret for the service principal in Azure AD"
    type        =   string
}

variable "subscription_id" {
    description =   "The guid for the subscription id"
    type        =   string
}

variable "tenant_id" {
    description =   "This is the tenant id for your Azure AD instance"
    type        =   string
}

# Resource Group

variable "location" {
    description =   "Location of the resource group"
    type        =   string
    default     =   "australiaeast"
}

# Vnet and Subnet

variable "vnet_address_range" {
    description =   "IP Range of the virtual network"
    type        =   string
    default     =   "10.0.0.0/16"
}

variable "subnet_address_range" {
    description =   "IP Range of the virtual network"
    type        =   string
    default     =   "10.0.1.0/24"
}

# Public IP and NIC Allocation Method

variable "allocation_method" {
    description =   "Allocation method for Public IP Address and NIC Private ip address"
    type        =   list(string)
    default     =   ["Static", "Dynamic"]
}


# VM 

variable "virtual_machine_size" {
    description =   "Size of the VM"
    type        =   string
    default     =   "Standard_B1s"
}

variable "computer_name" {
    description =   "Computer name"
    type        =   string
    default     =   "Win10vm"
}

variable "admin_username" {
    description =   "Username to login to the VM"
    type        =   string
    default     =   "winadmin"
}

variable "admin_password" {
    description =   "Password to login to the VM"
    type        =   string
    default     =   "P@$$w0rD2021*"
}

variable "os_disk_caching" {
    default     =       "ReadWrite"
}

variable "os_disk_storage_account_type" {
    default     =       "StandardSSD_LRS"
}

variable "os_disk_size_gb" {
    default     =       128
}

variable "publisher" {
    default         =       "MicrosoftWindowsDesktop"
}

variable "offer" {
    default         =       "Windows-10"
}

variable "sku" {
    default         =       "rs5-pro-g2"
}

variable "vm_image_version" {
    default         =       "latest"
}

output.tf

output "resource-names" {
    description     =   "Print the names of the resources"
    value           =   {
        "Resource-Group-Name" =  azurerm_resource_group.rg.name
        "Vnet-Name"           =  azurerm_virtual_network.vnet.name
        "Subnet-Name"         =  azurerm_subnet.web.name
        "NSG-Name"            =  azurerm_network_security_group.nsg.name
        "NIC-Name"            =  azurerm_network_interface.nic.name
    }
}


output "public_ip_address" {
    value           =   azurerm_public_ip.pip.ip_address
}

output "vm_login" {
    description     =      "Credentials to login to the VM"
    
    value           = {
        "VM-Name"   =   azurerm_windows_virtual_machine.vm.name
        "Username"  =   azurerm_windows_virtual_machine.vm.admin_username
        "Password"  =   azurerm_windows_virtual_machine.vm.admin_password
    }  
    sensitive= true
}

In this article I learned to develop terraform configuration file and deploy Azure resources.