Terraform script to build an Ubuntu VM in Azure

This is a write-up for creating a linux virtual machine in Azure Cloud using Terraform. Pre-requisites: Azure cloud account, Azure CLI installed on local machine, Azure configure with required access to build and manage vm in Azure cloud, Azure provider.

We will create an ubuntu virtual machine with public IP access to ssh and http port 80 for viewing default apache home page.

  1. Azure resource group

     resource "azurerm_resource_group" "vmtask" {
       name     = "rg-task4"
       location = "eastus2"
     }
    
    1. Azure Public IP

       resource "azurerm_public_ip" "vmtask" {
           name = "vmtask-public-ip"
           resource_group_name = azurerm_resource_group.vmtask.name
           location = azurerm_resource_group.vmtask.location
           allocation_method = "Static"
      
           tags = {
             environment = "demo"
           }
       }
      
    2. Azure virtual network

       resource "azurerm_virtual_network" "vmtask" {
         name                = "vnet-task4"
         address_space       = ["10.0.0.0/16"]
         location            = azurerm_resource_group.vmtask.location
         resource_group_name = azurerm_resource_group.vmtask.name
       }
      
       resource "azurerm_subnet" "vmtask" {
         name                 = "subnet-task4"
         resource_group_name  = azurerm_resource_group.vmtask.name
         virtual_network_name = azurerm_virtual_network.vmtask.name
         address_prefixes     = ["10.0.2.0/24"]
       }
      
      1. Network Security Group: Below snippet will create two security rules to open port 22 and port 80.

         resource "azurerm_network_security_group" "vmtask" {
           name = "vmtasknsg"
           resource_group_name = azurerm_resource_group.vmtask.name
           location = azurerm_resource_group.vmtask.location
        
           security_rule {
             name = "SSH"
             priority = 100
             direction = "Inbound"
             access = "Allow"
             protocol = "Tcp"
             source_port_range = "*"
             destination_port_range = "22"
             source_address_prefix = "*"
             destination_address_prefix = "*"
           }
           security_rule {
             name = "http"
             priority = 101
             direction = "Inbound"
             access = "Allow"
             protocol = "Tcp"
             source_port_range = "*"
             destination_port_range = "80"
             source_address_prefix = "*"
             destination_address_prefix = "*"
           }
        
           tags = {
             environment = "demo"
           }
         }
        
      2. Network Security Group association:

         resource "azurerm_subnet_network_security_group_association" "vmtask" {
           subnet_id                 = azurerm_subnet.vmtask.id
           network_security_group_id = azurerm_network_security_group.vmtask.id
         }
        
      3. Network interface:

         resource "azurerm_network_interface" "vmtask" {
           name                = "vmtask-nic"
           location            = azurerm_resource_group.vmtask.location
           resource_group_name = azurerm_resource_group.vmtask.name
        
           ip_configuration {
             name                          = "internal"
             subnet_id                     = azurerm_subnet.vmtask.id
             private_ip_address_allocation = "Dynamic"
             public_ip_address_id = azurerm_public_ip.vmtask.id
           }
         }
        
      4. Create virtual machine

         resource "azurerm_linux_virtual_machine" "vmtask" {
           name                = "vmtask-ubuntu"
           resource_group_name = azurerm_resource_group.vmtask.name
           location            = azurerm_resource_group.vmtask.location
           size                = "Standard_F2"
           admin_username      = "adminuser"
           admin_password      = "********"
           disable_password_authentication = false
           network_interface_ids = [
             azurerm_network_interface.vmtask.id,
           ]
           os_disk {
             caching              = "ReadWrite"
             storage_account_type = "Standard_LRS"
           }
           source_image_reference {
             publisher = "Canonical"
             offer     = "0001-com-ubuntu-server-jammy"
             sku       = "22_04-lts"
             version   = "latest"
           }
         }
        
      5. Output Public IP

         output "public_ip_address" {
           value = azurerm_public_ip.vmtask.ip_address
           description = "The public IP address of the virtual machine" 
         }
        

        Terraform's declarative syntax makes it easy to define complex infrastructure setups and manage them efficiently.