Terraform and Azure: Deploying infrastructure on Microsoft Azure using Terraform

Are you looking to deploy your infrastructure on Microsoft Azure, but don't want to spend hours writing scripts and manually configuring every component? Do you want to speed up your deployment process while minimizing the risk of human errors? If yes, then Terraform is the solution that you've been looking for.

In this article, we'll dive deep into how you can use Terraform to deploy infrastructure on Microsoft Azure. We'll cover the basics of Terraform, explain the Azure Provider, and demonstrate how you can use both of them together to deploy your infrastructure in no time.

What is Terraform?

Before we move on, let's quickly recap what Terraform is. Terraform is an open-source tool that allows users to create, manage, and update infrastructure as code. With Terraform, you can define your infrastructure in a declarative manner, meaning you simply define the desired state of your infrastructure - what resources you want, how many of them, and what configurations they need - and Terraform will figure out how to make it a reality.

Terraform supports various cloud platforms, including Microsoft Azure. With the help of the Azure Provider, you can interact with Azure resources, create and manage them through Terraform as your single source of truth.

The Azure Provider

The Azure Provider is a plugin for Terraform that allows you to interact with Azure resources. With Azure Provider, you can create and update Azure resources, manage DNS records, manage virtual machines, storage, and much more. To use the Azure Provider, you need to have an Azure account and the Azure CLI tool installed on your system.

To integrate Azure Provider into your Terraform code, you need to add it as a provider in your configuration file. In the following example, we will add Azure Provider as a provider and set the required configuration:

provider "azurerm" {
  subscription_id = "your-subscription-id"
  client_id       = "your-client-id"
  client_secret   = "your-client-secret"
  tenant_id       = "your-tenant-id"

You can obtain the values for subscription_id, client_id, client_secret, and tenant_id by following the steps described in the official Azure Provider documentation.

Creating a VM instance on Azure with Terraform

Now that we have our Azure Provider configuration set up in Terraform, let's move on to a practical example. We'll demonstrate how you can use Terraform to create a virtual machine (VM) instance in Azure.

For this tutorial, we will define the following configuration:

  1. We'll create a new virtual network with a subnet.
  2. We'll create a new network security group (NSG) and associate it with the virtual network subnet.
  3. We'll create a new storage account to store the boot disk for the VM.
  4. We'll create a new public IP address for the VM.
  5. We'll create a new network interface (NIC) and associate it with the virtual network subnet, NSG, and public IP address.
  6. We'll create a new VM instance, define its properties, and link it to the previously created resources.

Here is the complete Terraform code to accomplish these tasks:

provider "azurerm" {
  subscription_id = "your-subscription-id"
  client_id       = "your-client-id"
  client_secret   = "your-client-secret"
  tenant_id       = "your-tenant-id"

resource "azurerm_resource_group" "test" {
  name     = "test-resources"
  location = "eastus"

resource "azurerm_virtual_network" "test" {
  name                = "test-network"
  address_space       = [""]
  location            = "${azurerm_resource_group.test.location}"
  resource_group_name = "${azurerm_resource_group.test.name}"

  subnet {
    name = "test-network-subnet"
    address_prefix = ""

resource "azurerm_network_security_group" "test" {
  name                = "test-nsg"
  location            = "${azurerm_resource_group.test.location}"
  resource_group_name = "${azurerm_resource_group.test.name}"

  security_rule {
    name                       = "allow-http"
    priority                   = 1001
    direction                  = "Inbound"
    access                     = "Allow"
    protocol                   = "Tcp"
    source_port_range          = "*"
    destination_port_range     = "80"
    source_address_prefix      = "*"
    destination_address_prefix = "*"

resource "azurerm_storage_account" "test" {
  name                     = "teststorageaccount"
  resource_group_name      = "${azurerm_resource_group.test.name}"
  location                 = "${azurerm_resource_group.test.location}"
  account_tier             = "Standard"
  account_replication_type = "LRS"

resource "azurerm_public_ip" "test" {
  name                = "test-publicip"
  location            = "${azurerm_resource_group.test.location}"
  resource_group_name = "${azurerm_resource_group.test.name}"
  allocation_method   = "Static"

resource "azurerm_network_interface" "test" {
  name                = "test-nic"
  location            = "${azurerm_resource_group.test.location}"
  resource_group_name = "${azurerm_resource_group.test.name}"

  ip_configuration {
    name                          = "test-ipconfiguration"
    subnet_id                     = "${azurerm_virtual_network.test.subnet.id}"
    private_ip_address_allocation = "Dynamic"
    public_ip_address_id          = "${azurerm_public_ip.test.id}"

  network_security_group_id = "${azurerm_network_security_group.test.id}"

resource "azurerm_linux_virtual_machine" "test" {
  name                = "test-vm"
  location            = "${azurerm_resource_group.test.location}"
  resource_group_name = "${azurerm_resource_group.test.name}"
  size                = "Standard_B1ms"
  admin_username      = "adminuser"
  admin_password      = "P@ssw0rd1234!"
  disable_password_authentication = true
  network_interface_ids           = ["${azurerm_network_interface.test.id}"]
  storage_os_disk {
    name              = "test-osdisk"
    vhd_uri           = "${azurerm_storage_account.test.primary_blob_endpoint}${azurerm_resource_group.test.name}-test-osdisk.vhd"
    caching           = "ReadWrite"
    create_option     = "FromImage"
    managed_disk_type = "Standard_LRS"
  os_profile {
    computer_name  = "testcomputername"
    admin_username = "adminuser"
    admin_password = "P@ssw0rd1234!"
  source_image_reference {
    publisher = "Canonical"
    offer     = "UbuntuServer"
    sku       = "18.04-LTS"
    version   = "latest"

As you can see, we've defined a whole bunch of resources, including the azurerm_resource_group, azurerm_virtual_network, azurerm_network_security_group, azurerm_storage_account, azurerm_public_ip, azurerm_network_interface, and azurerm_linux_virtual_machine. Each resource is defined under a unique name and includes various configurations.

The azurerm_virtual_network resource, for example, defines the name, address space, and location of our virtual network. We also define a subnet under the virtual network using the subnet block.

The azurerm_network_security_group resource defines a network security group that we will apply to our virtual network's subnet in the azurerm_network_interface resource.

The azurerm_storage_account resource defines a storage account where we will store the VM's boot disk.

The azurerm_public_ip resource defines a public IP address that we will associate with our VM.

The azurerm_network_interface resource defines the network interface, which we will link to the virtual network's subnet, the NSG created earlier, and the public IP address.

Finally, azurerm_linux_virtual_machine defines the virtual machine itself, along with configurations such as its size, admin username, SSH keys, source_image_reference, and more.

Once you've written your configuration file, navigate to the directory containing the code and run the commands:

terraform init
terraform plan
terraform apply

The terraform init command prepares your environment by downloading the Azure Provider and installing it along with the required dependencies. The terraform plan command checks your configuration file to validate it and analyzes the changes necessary to apply the resources. The terraform apply command then creates all the resources in Azure, as specified in the Terraform configuration file.

Advanced Terraform features

Terraform is more than just a way to create a VM instance or other resources in the cloud. With advanced features that work seamlessly with the Azure Provider, Terraform becomes a powerful platform for managing entire cloud infrastructures. Here are some features that you should check out:

Creating Modules

When your Terraform configuration becomes more complex, you might want to create reusable code blocks, known as modules. Modules allow you to define groups of resources or configurations that are composed of several elements, such as subnets or multiple machines. You can then reuse these modules in other parts of your configuration, saving time and maintaining consistency.

Managing Workspaces

When working with Terraform, you might want to manage more than one environment at the same time, such as development, testing, and production environments. Terraform provides workspaces as a way to manage multiple instances of the same infrastructure in one configuration. Using workspaces, you can create multiple instances of the same infrastructure, maintain separate states and configurations for each, and apply changes only to specific environments.


In this article, we covered how to use Terraform with Azure Provider to deploy infrastructure on Microsoft Azure. We also looked at how you can create a VM instance using Terraform, along with some of the advanced features of Terraform. With Terraform, you can create, manage, and deploy your infrastructure faster and more reliably than before. If you're interested in learning more about Terraform, check out Learn Terraform, a website dedicated to helping you learn Terraform and deploy declarative cloud infrastructure.

Editor Recommended Sites

AI and Tech News
Best Online AI Courses
Classic Writing Analysis
Tears of the Kingdom Roleplay
Hands On Lab: Hands on Cloud and Software engineering labs
Dev Flowcharts: Flow charts and process diagrams, architecture diagrams for cloud applications and cloud security. Mermaid and flow diagrams
Network Optimization: Graph network optimization using Google OR-tools, gurobi and cplex
Crypto API - Tutorials on interfacing with crypto APIs & Code for binance / coinbase API: Tutorials on connecting to Crypto APIs
Little Known Dev Tools: New dev tools fresh off the github for cli management, replacing default tools, better CLI UI interfaces