Following on from my last TerraForm post, my next task is to deploy a VM with the tool. This is more complex than it sounds, as a ‘VM’ requires a number of components (network interface, disk) in addition to the VM as well as me wanting to configure it to do some initial boot-strapping on first start.

I started, as I have done with some of the previous components, by importing an existing example to use as a template - once that example is fully represented in the configuration it can be turned into a module and reused (at least, that’s my long-term plan).

First thing to create is the network interface:

resource "azurerm_resource_group" "vms" {
    name = "RG-MY_VMS-001"
    location = "West Europe"
    tags = merge(var.base_tags, var.tags_live)

resource "azurerm_network_interface" "vm-1-nic" {
  name                = "NIC-${regex("^SNET-(P<name>.*)-[0-9]+$",}-001"
  location            = azurerm_resource_group.vms.location
  resource_group_name =

  ip_configuration {
    name                          = "ipconfig1"
    subnet_id                     =
    private_ip_address_allocation = "Static"
    private_ip_address = ""

  tags = merge(var.base_tags, var.tags_live

Then I can create the virtual machine:

resource "azurerm_linux_virtual_machine" "vm-1" {
  name                = "VM-001"
  resource_group_name =
  location            = azurerm_resource_group.vms.location
  size                = "Standard_D4s_v3"
  admin_username      = "azureuser"
  admin_password      = "<somepassword>"
  disable_password_authentication = false

  admin_ssh_key {
      public_key = "ssh-rsa ....."
      username = "azureuser"

  # This can be used to pass cloud-init
  #custom_data = ""

  boot_diagnostics {}

  identity {
      type = "SystemAssigned"

  network_interface_ids = [,

  os_disk {
    caching              = "ReadWrite"
    storage_account_type = "Premium_LRS"
    name  = "DSK-VM-001"

  plan {
      name = "cis-centos7-l1"
      product = "cis-centos-7-v2-1-1-l1"
      publisher = "center-for-internet-security-inc"

  # Custom image from shared image gallery
  #source_image_id = "/subscriptions/$subid/resourceGroups/RG-SHIMG-001/providers/Microsoft.Compute/galleries/SHA_IG_001/images/VM-BASE-IMAGE/versions/1.0.3"
  # or for a market place image
  source_image_reference {
     publisher = "center-for-internet-security-inc"
     offer = "cis-centos-7-v2-1-1-l1"
     sku = "cis-centos7-l1"
     version = "latest"

  tags = merge(var.base_tags, var.tags_live

See the Microsoft documentation for how to find Azure Marketplace image information.

Two tasks are outstanding with this:

  1. Get the password for the administrator from the Azure KeyVault (instead of hard-coding it)
  2. Use cloud-init to kick off the initial configuration of the VM