Terraform on Azure

Terraform on Azure

Today we are going to learn about Terraform.

What is Terraform and why do you care?

Hashicorp’s Terraform is an Infrastructure as Code (IaC) tool designed for creating, managing, updating, and versioning reproducible application infrastructure.

Terraform enables you to safely and predictably create, change, and improve production infrastructure. It is an open source tool that codifies APIs into declarative configuration files that can be shared amongst team members, treated as code, edited, reviewed, and versioned.

First of all, there are a lot of ways in which you can create your image, Packer being a great option, but I’m just going to show you the simple, manual way because I think it gives you a good idea of what’s happening. Then we’re going to build a virtual machine in Terraform from that image.


The basic outline:

1.Create Source VM
2. Deprovision / Sysprep
4. Generalize
5. Create Image
6. Create Virtual Machine with Terraform

1. Create your Source Virtual Machine

This is totally up to you. Provision this bad boy however you want. Just know that you’re not going to actually use this machine, just use it to make an image from it. Also, this post is about creating a VM with unmanaged disks, so if you want to follow along, you’ll need to specify –use-unmanaged-disk in the az vm create command or in the Azure Portal. Default is to use managed disks, so be aware.

Make sure you note what your osdisk name is. You’ll need this later.


Terraform it up!

Now for the fun stuff! Okay, so we have our image sitting there in our resource group, and now we have a couple of options. If we want to use managed disks (after the issue is resolved, then we can use an image from one resource group and create a VM in another resource group (but still in the same subscription).

For this example, as I said, though, I’m going to use unmanaged disks. This exampleis nice and easy to walk through because it does exactly what we’re wanting to do. Let’s take a look at the azurerm_virtual_machine block of the main.tf.

resource "azurerm_virtual_machine" "vm" {
  name                  = "${var.hostname}"
  location              = "${var.location}"
  resource_group_name   = "${azurerm_resource_group.rg.name}"
  vm_size               = "${var.vm_size}"
  network_interface_ids = ["${azurerm_network_interface.nic.id}"]

  storage_os_disk {
    name          = "${var.hostname}-osdisk1"
    image_uri     = "${var.image_uri}"
    vhd_uri       = "https://${var.storage_account_name}.blob.core.windows.net/vhds/${var.hostname}-osdisk.vhd"
    os_type       = "${var.os_type}"
    caching       = "ReadWrite"
    create_option = "FromImage"

  os_profile {
    computer_name  = "${var.hostname}"
    admin_username = "${var.admin_username}"
    admin_password = "${var.admin_password}"

  os_profile_linux_config {
    disable_password_authentication = false


First of all, if you’re comparing this VM block to building a virtual machine not from an image you’ll notice that a we’re missing a storage_image_reference block. This is neglected because the image provides that information. On the other hand, vm_size is required, and it must be the same size as the image.

In the storage_os_disk block the two things we’ll look at are the image_uri and the vhd_uri.


The image that you just made has a VHD, and you need the uri to this VHD. There are a couple of ways to find out the image_uri. First, you can simply look in the portal. You can see in the screenshot below that I have a resource group called “permanent” with an image called “customImage”.In the overview of the image resource, I can see the “Source Blob Uri” that I need.


VM from Custom Image








Another way I can find that is to use Azure CLI 2.0 to find out the names of my resource group (az group list), storage account (az resource list -g <ResourceGroupName> -o table), and os disk (if you’re not using managed disks, then I don’t know of a command to find this name – create an issue if you do, so I hope you saved it from when you created it). If I have those things, then I can build the uri like this:


The only change would be if you changed the default name of the vhds directory. Otherwise, this should work.


Since this example does not have us using managed disks, we’re going to have to put our new vhd into our existing storage account. Therefore, the storage_account_name variable that you see there is for the existing storage account in which your image’s vhd resides (the one we used for the image_uri).

And that’s it! If you want to create a VM with managed disks, it’s not too different, but I’ll show you after that issue gets resolved. You can also check out these other examples of creating VMs from images:

Share this post

Share on facebook
Share on google
Share on twitter
Share on linkedin
Share on pinterest
Share on print
Share on email

Leave A Comment

This site uses Akismet to reduce spam. Learn how your comment data is processed.