DEV Community

Bolarinwa Olayinka
Bolarinwa Olayinka

Posted on

How to Deploy an Azure Linux Virtual Machine Using Terraform

Architecture Overview

+---------------------------+
| Resource Group | <-- Logical container for all resources
| (myresourcegroup) |
+---------------------------+
|
| contains
v
+---------------------------+
| Virtual Network | <-- Custom address space: 10.0.0.0/16
| (mynetwork) |
+---------------------------+
|
| contains subnet
v
+---------------------------+
| Subnet | <-- Internal subnet: 10.0.2.0/24
| (internal) |
+---------------------------+
|
| connected to
v
+---------------------------+ +-------------------------+
| Network Interface (NIC) | <------> | Public IP Address | <-- Static, Standard SKU public IP
| (mynic) | | (mypip) |
+---------------------------+ +-------------------------+
|
| attached to
v
+---------------------------+
| Linux Virtual Machine | <-- Ubuntu 22.04 LTS VM
| (myvm) |
+---------------------------+
Introduction

In this guide, I’ll walk you through how to deploy a Linux Virtual Machine (VM) on Microsoft Azure using Terraform — an Infrastructure as Code (IaC) tool.

This example sets up:

A Resource Group

Virtual Network

Subnet

Public IP

Network Interface

Linux VM
Prerequisites
Before you begin, ensure you have:

Azure CLI installed and logged in

Terraform installed

An active Azure subscription

Terraform Configuration

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

provider "azurerm" {
  features {}
}
Enter fullscreen mode Exit fullscreen mode

Use environment variables or a secret manager for production

  subscription_id = "<your-subscription-id>"
  tenant_id       = "<your-tenant-id>"
  client_id       = "<your-client-id>"
  client_secret   = "<your-client-secret>"
}

variable "prefix" {
  default = "ybeedigital"
}
Enter fullscreen mode Exit fullscreen mode

Infrastructure Resources

  1. Resource Group
resource"azurerm_resource_group" "myrg" {
  name     = "${var.prefix}-resources"
  location = "UK South"
}

2. Virtual Network and Subnet

resource "azurerm_virtual_network" "main" {
  name                = "${var.prefix}-network"
  address_space       = ["10.0.0.0/16"]
  location            = azurerm_resource_group.myrg.location
  resource_group_name = azurerm_resource_group.myrg.name
}
Enter fullscreen mode Exit fullscreen mode
resource "azurerm_subnet" "internal" {
  name                 = "internal"
  resource_group_name  = azurerm_resource_group.myrg.name
  virtual_network_name = azurerm_virtual_network.main.name
  address_prefixes     = ["10.0.2.0/24"]
}
3. Public IP

resource "azurerm_public_ip" "main" {
  name                = "${var.prefix}-pip"
  location            = azurerm_resource_group.myrg.location
  resource_group_name = azurerm_resource_group.myrg.name
  allocation_method   = "Static"
  sku                 = "Standard"
  idle_timeout_in_minutes = 30

  tags = {
    environment = "staging"
  }
}

Enter fullscreen mode Exit fullscreen mode
  1. Network Interface
resource"azurerm_network_interface" "main" {
  name                = "${var.prefix}-nic"
  location            = azurerm_resource_group.myrg.location
  resource_group_name = azurerm_resource_group.myrg.name

  ip_configuration {
    name                          = "internal"
    subnet_id                     = azurerm_subnet.internal.id
    private_ip_address_allocation = "Dynamic"
    public_ip_address_id          = azurerm_public_ip.main.id
  }
}

Enter fullscreen mode Exit fullscreen mode
  1. Linux Virtual Machine
resource"azurerm_linux_virtual_machine" "main" {
  name                  = "${var.prefix}-vm"
  location              = azurerm_resource_group.myrg.location
  resource_group_name   = azurerm_resource_group.myrg.name
  network_interface_ids = [azurerm_network_interface.main.id]
  size                  = "Standard_B1s"
  admin_username        = "adminuser"
  admin_password        = "P@ssw0rd123!"  # Replace in production with SSH keys

  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"
  }

  computer_name                  = "${var.prefix}-vm"
  disable_password_authentication = false

  tags = {
    environment = "staging"
  }
}

Enter fullscreen mode Exit fullscreen mode

Optional: SSH Authentication (Recommended)
Instead of a password, use an SSH key:

admin_ssh_key {
  username   = "adminuser"
  public_key = file("~/.ssh/id_rsa.pub")
}

disable_password_authentication = true

Enter fullscreen mode Exit fullscreen mode

How to Deploy
Initialize Terraform

terraform init
Preview the changes

terraform plan
Apply the configuration

terraform apply

Conclusion
Using Terraform to deploy infrastructure on Azure automates your setup process and ensures consistency, repeatability, and easy scalability.

This guide showed you how to provision a Linux Virtual Machine along with essential networking components, all managed as code. As your infrastructure grows, you can extend this foundation with services like:

Azure Key Vault

Azure Monitor

Managed PostgreSQL/MySQL databases

Load Balancers

VM Scale Sets

Embrace Infrastructure as Code with Terraform to streamline your cloud operations and accelerate deployment. Happy building!

Top comments (0)