Create an Azure Linux Virtual Machine with Terraform

I am a software engineer. Documenting my DevOps journey
Search for a command to run...

I am a software engineer. Documenting my DevOps journey
No comments yet. Be the first to comment.
Introduction SSH is method of securely connect to remote server and execute command on that server. To provide user access to remote server either password or SSH key needs to be shared. But this becomes cumbersome when there are many users as well a...

Introduction In this article, we ran a Python application in AWS Lambda using Docker. Now we want to add some licencing mechanism by keeping the access key or any secret key to another service or application to restrict the use of this application. H...

Introduction I have been using Ubuntu for a long time on Intel Core i5 system. The daily routine was to pull the code from the Git repositories, build docker images, push it to Dockerhub and run docker containers with those images in the production U...

Introduction In the last article, we discovered how to monitor a NodeJs application with Prometheus and Grafana. In that, we learned to collect metrics from the application like the rate of requests in the last 5 minutes, the rate of 5xx responses, b...

Introduction Application monitoring is essential in the production environment. Once the application is deployed, the traffic to the application starts increasing, after some time the application starts responding slowly or sometimes it gets failed. ...

In this blog, I'll tell you how to create an Azure Linux Virtual Machine using Terraform.
Azure subscription
Terraform installed
Azure CLI installed
An Azure subscription is mandatory when you are using Azure resources like a database, virtual network, storage account or virtual machine.
Terraform is an open-source infrastructure as code software tool that enables you to safely and predictably create, change, and improve infrastructure.
We will use this tool to create a simple Linux virtual machine to help you get started on your terraform learning journey.
cd ~
mkdir terraform-example
cd terraform-example
touch main.tf
Open up main.tf in your editor of choice and add the Azure provider to the top of the file.
provider "azurerm" {
features {}
}
Now let’s create our new resource group that everything will live inside. Select a region of your choice
resource "azurerm_resource_group" "main" {
name = "tfvmexample-rg"
location = "Central India"
}
Virtual Network enables Virtual Machine to securely communicate with the internet and on-premises networks.
# Create virtual network
resource "azurerm_virtual_network" "main" {
name = "tfvmexample-vnet"
address_space = ["10.0.0.0/16"]
location = azurerm_resource_group.main.location
resource_group_name = azurerm_resource_group.main.name
}
Subnets enable you to segment the Virtual Network into one or more sub-networks and allocate a portion of the virtual network's address space to each subnet. You can then deploy Azure Virtual Machine in a specific subnet.
# Create subnet
resource "azurerm_subnet" "internal" {
name = "tfvmexample-subnet"
resource_group_name = azurerm_resource_group.main.name
virtual_network_name = azurerm_virtual_network.main.name
address_prefixes = ["10.0.1.0/24"]
}
Public IP addresses enables Virtual Machine to communicate to Internet
# Create public IP
resource "azurerm_public_ip" "main" {
name = "tfvmexample-public-ip"
location = azurerm_resource_group.main.location
resource_group_name = azurerm_resource_group.main.name
allocation_method = "Static"
}
A network security group contains security rules that allow or deny inbound network traffic to, or outbound network traffic from Virtual Machine. Here 3 inbound rules have been defined for SSH, HTTP and TCP connections to be allowed with Virtual Machine.
# Create Network Security Group and rule
resource "azurerm_network_security_group" "main" {
name = "tfvmexample-network-security-group"
location = azurerm_resource_group.main.location
resource_group_name = azurerm_resource_group.main.name
security_rule {
name = "SSH"
priority = 300
direction = "Inbound"
access = "Allow"
protocol = "Tcp"
source_port_range = "*"
destination_port_range = "22"
source_address_prefix = "*"
destination_address_prefix = "*"
}
security_rule {
name = "HTTP"
priority = 310
direction = "Inbound"
access = "Allow"
protocol = "Tcp"
source_port_range = "*"
destination_port_range = "80"
source_address_prefix = "*"
destination_address_prefix = "*"
}
security_rule {
name = "CutomPort9000"
priority = 320
direction = "Inbound"
access = "Allow"
protocol = "Tcp"
source_port_range = "*"
destination_port_range = "9000"
source_address_prefix = "*"
destination_address_prefix = "*"
}
}
A virtual machine created with the Azure portal, has one network interface with default settings. You may change default settings also. Here Public address defined earlier is attached to Network Interface
# Create network interface
resource "azurerm_network_interface" "main" {
name = "tfvmexample-nic"
resource_group_name = azurerm_resource_group.main.name
location = azurerm_resource_group.main.location
ip_configuration {
name = "tfvmexample-nic-config"
subnet_id = azurerm_subnet.internal.id
private_ip_address_allocation = "Dynamic"
public_ip_address_id = azurerm_public_ip.main.id
}
}
Associate Security Group defined earlier to Network Interface
# Connect the security group to the network interface
resource "azurerm_network_interface_security_group_association" "main" {
network_interface_id = azurerm_network_interface.main.id
network_security_group_id = azurerm_network_security_group.main.id
}
Define Virtual Machine with parameters like name, admin username and password, size to handle the workload, OS image reference and disk.
Attach Network Interface Id defined earlier to Virtual Machine
# Create virtual machine
resource "azurerm_linux_virtual_machine" "main" {
name = "tfvmexample-vm"
resource_group_name = azurerm_resource_group.main.name
location = azurerm_resource_group.main.location
size = "Standard_D8s_v3"
admin_username = "adminuser"
admin_password = "Terraform@123"
disable_password_authentication = false
network_interface_ids = [
azurerm_network_interface.main.id,
]
source_image_reference {
publisher = "Canonical"
offer = "UbuntuServer"
sku = "18_04-lts-gen2"
version = "latest"
}
os_disk {
storage_account_type = "Premium_LRS"
caching = "ReadWrite"
}
}
The final main.tf file is as below
provider "azurerm" {
features {}
}
resource "azurerm_resource_group" "main" {
name = "tfvmexample-rg"
location = "Central India"
}
# Create virtual network
resource "azurerm_virtual_network" "main" {
name = "tfvmexample-vnet"
address_space = ["10.0.0.0/16"]
location = azurerm_resource_group.main.location
resource_group_name = azurerm_resource_group.main.name
}
# Create subnet
resource "azurerm_subnet" "internal" {
name = "tfvmexample-subnet"
resource_group_name = azurerm_resource_group.main.name
virtual_network_name = azurerm_virtual_network.main.name
address_prefixes = ["10.0.1.0/24"]
}
# Create public IP
resource "azurerm_public_ip" "main" {
name = "tfvmexample-public-ip"
location = azurerm_resource_group.main.location
resource_group_name = azurerm_resource_group.main.name
allocation_method = "Static"
}
# Create Network Security Group and rule
resource "azurerm_network_security_group" "main" {
name = "tfvmexample-network-security-group"
location = azurerm_resource_group.main.location
resource_group_name = azurerm_resource_group.main.name
security_rule {
name = "SSH"
priority = 300
direction = "Inbound"
access = "Allow"
protocol = "Tcp"
source_port_range = "*"
destination_port_range = "22"
source_address_prefix = "*"
destination_address_prefix = "*"
}
security_rule {
name = "HTTP"
priority = 310
direction = "Inbound"
access = "Allow"
protocol = "Tcp"
source_port_range = "*"
destination_port_range = "80"
source_address_prefix = "*"
destination_address_prefix = "*"
}
security_rule {
name = "CutomPort9000"
priority = 320
direction = "Inbound"
access = "Allow"
protocol = "Tcp"
source_port_range = "*"
destination_port_range = "9000"
source_address_prefix = "*"
destination_address_prefix = "*"
}
}
# Create network interface
resource "azurerm_network_interface" "main" {
name = "tfvmexample-nic"
resource_group_name = azurerm_resource_group.main.name
location = azurerm_resource_group.main.location
ip_configuration {
name = "tfvmexample-nic-config"
subnet_id = azurerm_subnet.internal.id
private_ip_address_allocation = "Dynamic"
public_ip_address_id = azurerm_public_ip.main.id
}
}
# Connect the security group to the network interface
resource "azurerm_network_interface_security_group_association" "main" {
network_interface_id = azurerm_network_interface.main.id
network_security_group_id = azurerm_network_security_group.main.id
}
# Create virtual machine
resource "azurerm_linux_virtual_machine" "main" {
name = "tfvmexample-vm"
resource_group_name = azurerm_resource_group.main.name
location = azurerm_resource_group.main.location
size = "Standard_D8s_v3"
admin_username = "adminuser"
admin_password = "Terraform@123"
disable_password_authentication = false
network_interface_ids = [
azurerm_network_interface.main.id,
]
source_image_reference {
publisher = "Canonical"
offer = "UbuntuServer"
sku = "18_04-lts-gen2"
version = "latest"
}
os_disk {
storage_account_type = "Premium_LRS"
caching = "ReadWrite"
}
}
Make sure you have the Azure CLI installed, then run:
az login
Which should bring up a browser window for you to log in to your Azure subscription.
Now that we have written our config file, let’s run these 👇🏼 commands to let Terraform do its job.
terraform init
This will download and install the AZURE plugins for the providers we used. It initializes the backend as well.

Run the below command to see the changes that will take place on the infrastructure.
terraform plan

As we can see above plan suggests 8 resources to be added to the infrastructure.
If everything looks alright, let’s apply the changes by running 👇🏼
terraform apply

As we can see above 1 Virtual Machine addition is completed.
Finally, you should be able to see the Azure Virtual Machine up and running in Azure Portal.

Destroy the virtual machine because it will cost you a lot if we keep it running for a longer time.
terraform destroy

As we can see above 8 resources were destroyed which were created along with Virtual Machine.
Terraform makes it easy for administrators to provision cloud resources in Azure. Using Terraform’s command files, you can automate provisioning to reduce the overhead of manually creating resources in the Azure portal.