Create a Linux Virtual Machine using Terraform

Create a Linux Virtual Machine using Terraform

To create a Linux VM using Terraform on any cloud provider (e.g., Azure, AWS, or Google Cloud), the steps generally follow this process. This article uses Azure as the provider but the logic is similar for other Providers.

Prerequisite

1. Install Terraform

Ensure Terraform is installed on your system. You can download it from Terraform's official site. When you are done installing, check the installed version.

terraform -v  # Check the installed version

2. Set up Azure CLI and Authentication

Install and configure Azure CLI if you haven't already, and authenticate with your Azure account:

az login

Implement Terraform

Step 1: Create Directory for Terraform Configuration File

Make a new directory terraform-linuxVM and move into the it. Replace terraform-linuxVM with a name of your choice.

mkdir terraform-linuxVM
cd terraform-linuxVM

Step 2: Create a Terraform Configuration File

In the directory, create terraform configuration file. Create main.tf file and insert the corresponding codes.

provider "azurerm" {
  features {}
  subscription_id = "azure account id"


}


resource "azurerm_resource_group" "my_rg" {
  name     = "my-terraform-rg"
  location = "East US"
}


resource "azurerm_virtual_network" "my_vnet" {
  name                = "my-vnet"
  location            = azurerm_resource_group.my_rg.location
  resource_group_name = azurerm_resource_group.my_rg.name
  address_space       = ["10.0.0.0/16"]
}


resource "azurerm_subnet" "my_subnet" {
  name                 = "my-subnet"
  resource_group_name  = azurerm_resource_group.my_rg.name
  virtual_network_name = azurerm_virtual_network.my_vnet.name
  address_prefixes     = ["10.0.1.0/24"]
}


resource "azurerm_network_security_group" "ssh_sg" {
  name                = "ssh-nsg"
  location            = azurerm_resource_group.my_rg.location
  resource_group_name = azurerm_resource_group.my_rg.name


  security_rule {
    name                       = "allow-ssh"
    priority                   = 100
    direction                  = "Inbound"
    access                     = "Allow"
    protocol                   = "Tcp"
    source_port_range          = "*"
    destination_port_range     = "22"
    source_address_prefix      = "*"
    destination_address_prefix = "*"
  }


  # Allow HTTP traffic
  security_rule {
    name                       = "allow-http"
    priority                   = 110
    direction                  = "Inbound"
    access                     = "Allow"
    protocol                   = "Tcp"
    source_port_range          = "*"
    destination_port_range     = "80"
    source_address_prefix      = "*"
    destination_address_prefix = "*"
  }


  # Allow HTTPS traffic
  security_rule {
    name                       = "allow-https"
    priority                   = 120
    direction                  = "Inbound"
    access                     = "Allow"
    protocol                   = "Tcp"
    source_port_range          = "*"
    destination_port_range     = "443"
    source_address_prefix      = "*"
    destination_address_prefix = "*"
  }
}


# Create a Public IP
resource "azurerm_public_ip" "my_public_ip" {
  name                         = "my-public-ip"
  location                     = azurerm_resource_group.my_rg.location
  resource_group_name          = azurerm_resource_group.my_rg.name
  allocation_method            = "Static"
  sku                          = "Basic"
}


# Create Network Interface with Public IP association
resource "azurerm_network_interface" "my_nic" {
  name                = "my-nic"
  location            = azurerm_resource_group.my_rg.location
  resource_group_name = azurerm_resource_group.my_rg.name


  ip_configuration {
    name                          = "my-ip-config"
    subnet_id                     = azurerm_subnet.my_subnet.id
    private_ip_address_allocation = "Dynamic"
    public_ip_address_id          = azurerm_public_ip.my_public_ip.id  # Associate Public IP
  }


}


# Create a Linux VM
resource "azurerm_linux_virtual_machine" "my_vm" {
  name                = "my-linux-vm"
  resource_group_name = azurerm_resource_group.my_rg.name
  location            = azurerm_resource_group.my_rg.location
  size                = "Standard_B1s"
  admin_username      = "azureuser"
  network_interface_ids = [
    azurerm_network_interface.my_nic.id
  ]


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


  source_image_reference {
    publisher = "Canonical"
    offer     = "UbuntuServer"
    sku       = "18.04-LTS"
    version   = "latest"
  }


  os_disk {
    caching              = "ReadWrite"
    storage_account_type = "Standard_LRS"
  }


  tags = {
    Environment = "Terraform"
  }
}
  • replace azure account id in the code with your account id

  • To get your account id, run

      az account list
    

Step3: Initialize Terraform

In your project directory, run the following command to initialize Terraform. This will download and upgrades the necessary provider plugins (in this case, Azure).

terraform init -upgrade

Step4: Create an Execution Plan

Run the plan command to check if the configuration is correct.

terraform plan

Step5: Apply Terraform Execution Plan

If the plan is successful, apply it to create your VM and associated resources.

terraform apply

Terraform will prompt you to confirm. Type yes to proceed. After the apply command completes, your Linux VM will be created.

Verify the Results

  1. Once the VM is created, get the public IP address of the VM.

      az vm show -d -g my-terraform-rg -n my-linux-vm --query publicIps -o tsv
    
  2. you can SSH into it using the public IP address generated by Terraform.

     ssh azureuser@<Public_IP_Address>
    

    replace <Public_IP_Address> with your VM public IP address generated and type yes when prompted for fingerprint.

  3. You can also login to your account on azure portal to view resources created.

You have successfully deployed a Linux VM using Terraform.

Clean up Resources(Optional)

Delete the resources you created if it is for practice only to avoid incurring cost. To delete, run the code below:

  •   terraform destroy
    

This will remove all the infrastructure created by Terraform.