Building an Azure infrastructure with Terraform!

Building Azure infrastructure with Terraform!


In my last blog I described how and why you want to use Terraform to manage your different clouds and on-premises environments. In this blog I will describe how you can create and make a virtual machine with its underlying networking in the Microsoft Azure Cloud with Terraform. I will also give some information about how to use the Hashicorp Language (HCL), with some of its quirks and features!

Let’s start building Azure infrastructure!

Let’s make some infrastructure on the Azure platform. In this blog we are going to create a virtual machine with all the needed network essentials in Azure. These essentials include the following: a virtual network, a subnet, a NIC and the virtual machine itself.


To start creating resources we need to provide the “azurerm” provider with the needed information in the block, as explained in part 1.

Virtual network

After that we are first going to create a virtual network in Azure by adding the “azurerm_virtual_network” block with the name “main” as displayed below:

When you go to the documentation of this block in the Terraform docs as in this link:

Here you will find everything you can or need to declare in this block. In this block this is: name, resource_group_name, address_space and location. There are more optional arguments that could be declared, but that is outside of the scope of this blog. When you enter the essentials, it should look something like this:


Next, we are going to make a subnet on the network made. In this example it is the “network-metis”, again you can find very good documentation on the Terraform website:


For the machine to need to create a NIC (Network Interface Card) to couple the virtual machine with the previous subnet. In this block we are using something new, which is calling the id of the previous made subnet. The connection to this subnet is based on an ID and is only made after creation of the subnet. As you can see, we are calling the ${ variable}. Based on the following:

Network interface block:


Virtual machine

Now we are creating the virtual machine. As you can see there is a lot to be declared for creating a virtual machine. Mainly because there are a lot of choices to be made such as images, disks, networks and diagnostics. Again, to show all changes possible look at the documentation:

Full script

Under here you will find the full script with all above snippets of code combined, so you can copy and paste this for own use:

provider "azurerm" {
subscription_id = "0976"
client_id = "4ee8"
client_secret = "cff3"
tenant_id = "f8ee"

resource "azurerm_virtual_network" "main" {
name                = "network-metis"
resource_group_name = "Terraform"
location            = "westeurope"
address_space       = [""]

resource "azurerm_subnet" "internal" {
name                    = "testsubnet"
resource_group_name     = "Terraform"
virtual_network_name    = "${}"
address_prefix          = ""

resource "azurerm_network_interface" "main" {
name                = "vm-01-nic"
location            = "westeurope"
resource_group_name = "Terraform"

    ip_configuration {
    name                          = "ip-vm-01"
    private_ip_address_allocation = "Static"
    private_ip_address            = ""
    subnet_id                     = "${}"

resource "azurerm_virtual_machine" "main" {
name                                = "vm-01"
location                            = "westeurope"
resource_group_name                 = "Terraform"
network_interface_ids               = ["${}"]
vm_size                             = "Standard_DS1_v2"
delete_os_disk_on_termination       = true
delete_data_disks_on_termination    = true

    storage_image_reference {
    publisher = "Canonical"
    offer     = "UbuntuServer"
    sku       = "16.04-LTS"
    version   = "latest"

    storage_os_disk {
    name              = "vm-01-osdisk"
    caching           = "ReadWrite"
    create_option     = "FromImage"
    managed_disk_type = "Standard_LRS"

    os_profile {
    computer_name  = "vm-01"
    admin_username = "testadmin"
    admin_password = "Password1234!"

    os_profile_linux_config {
    disable_password_authentication = false


Running the script

As explained in my previous blog deploying with Terraform has three steps. These steps are: “terraform init”, “terraform plan”, “terraform apply” and to destroy it there is “terraform destroy”.

For the infrastructure to deploy we are going to use the script that we made above. This script will create a network and virtual machine on the Microsoft Azure platform. Save this file as an .tf file.

To run a terraform script you must also download the terraform executable, and save this executable in your path to be able to run terraform everywhere on your Windows/Linux/Mac machine. Follow the steps documented on the following webpage from Terraform to be able to do this:

Terraform init

As you can see in this step, we are initializing the directory of the location of our script. It is checking all the providers mentioned in the script, and downloading the files needed to run the script.

Terraform plan

After we run our terraform plan command you will see lots of output of which is displayed in your terminal/command prompt. Under here you can find a small snippet of this output. Some output is known after applying which means the following:

    1. You didn’t specify it in your code.
    2. It is given after deployment, in our case by Azure.

Terraform apply

In this step you are applying your changes. Firstly, you get another overview of your changes, just like the terraform plan command. But now you also get the option to perform the actions. When you agree with the changes, you enter “yes”, and your infrastructure will be made in the Azure platform. In your output you will find the progress that is made, time taken to deploy and at completion you will get an output with the information that your apply is successful or unsuccessful.

Checking creation of the infrastructure

We got the message that our apply is complete and that new resources are added, but is this valid? To check this, we go to our azure account and view the Terraform resource group. In here our changes were made, so let’s see!

As you can see there are 4 resources: a virtual network, a virtual machine, a network interface and a Disk. These are all resources defined in our terraform code. And thus, our deployment is complete and successful. 😊

Closing words

Terraform is a strong and mature tool for managing resources. It has many strengths and has a clear use-case for multi-cloud environments, as it enables managing these environments with only one tool instead of gluing scripts or tools together. It also has a clear focus which is infrastructure and is very well defined in how it works. Terraform supports over 100 providers which are supported by engineers from their own providers, but it also has over 100 community providers. With all these combined it enables enterprises to flourish in complex environments.


21 oktober 2019
Ramon de Goede