Azure Website Setup with Terraform

Table of Contents

Setting up our Environment

Initial Setup

Create main.tf and add Azure Provider

# "../resource/terraform/main.tf"
provider "azurerm" {
  features {}
}

Create variables.tf file

We are going to be using variables, so lets get that setup.

# "../resource/terraform/variables.tf"
variable "prefix" {
  description = "The prefix which should be used for all resources in this example"
  default     = "terraform-test"
}

variable "location" {
  description = "The Azure Region in which all resources in this example should be created."
  default     = "eastus2"
}

Add Resource Group

Then we create a resource group for our project.

# "../resource/terraform/main.tf"
resource "azurerm_resource_group" "rg" {
  name     = "${var.prefix}-rg"
  location = var.location
}

Add variable for the VNET address space

We are going to want to separate our project from the rest of our projects in it's own virtual network. We will want to add a variable because we will want to make sure our address space doesn't conflict with any of our other projects.

# "../resource/terraform/variables.tf"
variable "vnet__address_space" {
  description = "The address space to use for the virtual network."
  default     = ["0.0.16.0/20"]
}

Add VNET

Now we can add our virtual network.

# "../resource/terraform/main.tf"
resource "azurerm_virtual_network" "vnet" {
  name                = "${var.prefix}-vnet"
  location            = var.location
  resource_group_name = azurerm_resource_group.rg.name
  address_space       = var.vnet__address_space
}

Add Key Vault and Secret for User Password

Get Current Client config for our Tenant Id

# "../resource/terraform/main.tf"
data "azurerm_client_config" "current" {
}

Create Key Vault

# "../resource/terraform/main.tf"
resource "azurerm_key_vault" "kv" {
  name                = "${var.prefix}-key-vault"
  resource_group_name = azurerm_resource_group.rg.name
  location            = azurerm_resource_group.rg.location
  tenant_id           = data.azurerm_client_config.current.tenant_id
  sku_name            = "standard"
  access_policy {
    tenant_id = data.azurerm_client_config.current.tenant_id
    object_id = data.azurerm_client_config.current.object_id
    key_permissions = ["create", "get"]
    secret_permissions = ["set", "get", "delete", "list"]
  }
}

Add The Random Provider So We can generate a password

# "../resource/terraform/main.tf"
provider "random" {
  version = "2.2.1"
}

Generate the Random Password

# "../resource/terraform/main.tf"
resource "random_password" "webvm_password" {
  length = 16
  special = true
  override_special = "_%@`"
}

Add the password as a Secret

# "../resource/terraform/main.tf"
resource "azurerm_key_vault_secret" "webvm" {
  name  = "${var.prefix}-webvm-password"
  value = random_password.webvm_password.result
  key_vault_id = azurerm_key_vault.kv.id
}

Add a Virtual Machine for our Web Server

Add a subnet for our web servers

Add a new variable for our web server subnet.

# "../resource/terraform/variables.tf"
variable "subnet__web__address_space" {
  description = "The address space to use for our web servers subnet."
  default     = "0.0.16.0/24"
}

Add our subnet to our virtual network.

# "../resource/terraform/main.tf"
resource "azurerm_subnet" "web" {
  name                 = "web"
  resource_group_name  = azurerm_resource_group.rg.name
  virtual_network_name = azurerm_virtual_network.vnet.name
  address_prefix       = var.subnet__web__address_space
}

Add a Public IP to access our Web Server

# "../resource/terraform/main.tf"
resource "azurerm_public_ip" "web" {
  name                = "${var.prefix}-web-pip"
  resource_group_name = azurerm_resource_group.rg.name
  location            = azurerm_resource_group.rg.location
  allocation_method   = "Dynamic"
}

Add a Network Interface With Private Dynamic IP and our Public IP for our Web Server

# "../resource/terraform/main.tf"
resource "azurerm_network_interface" "web" {
  name                = "${var.prefix}-web-nic"
  resource_group_name = azurerm_resource_group.rg.name
  location            = azurerm_resource_group.rg.location

  ip_configuration {
    name                          = "web"
    subnet_id                     = azurerm_subnet.web.id
    private_ip_address_allocation = "Dynamic"
    public_ip_address_id          = azurerm_public_ip.web.id
  }
}

Add a Network Security Group (NSG) for our Web Server Subnet

We are also adding a security rule to allow https access.

# "../resource/terraform/main.tf"
resource "azurerm_network_security_group" "web" {
  name                = "${var.prefix}-web-nsg"
  resource_group_name = azurerm_resource_group.rg.name
  location            = azurerm_resource_group.rg.location
  security_rule {
    access                     = "Allow"
    direction                  = "Inbound"
    name                       = "tls"
    priority                   = 100
    protocol                   = "Tcp"
    source_port_range          = "*"
    source_address_prefix      = "*"
    destination_port_range     = "443"
    destination_address_prefix = azurerm_network_interface.web.private_ip_address
   }
}

Associate NSG with Subnet via our Network Interface

# "../resource/terraform/main.tf"
resource "azurerm_subnet_network_security_group_association" "web" {
  subnet_id = azurerm_subnet.web.id
  network_security_group_id = azurerm_network_security_group.web.id
}

Add the Virtual Machine

Currently getting errors when adding the VM… not sure why yet…

# "../resource/terraform/main.tf"
resource "azurerm_linux_virtual_machine" "web" {
  name                            = "${var.prefix}-vm"
  resource_group_name             = azurerm_resource_group.rg.name
  location                        = azurerm_resource_group.rg.location
  size                            = "Standard_B1ms"
  admin_username                  = "adminuser"
  admin_password                  = random_password.webvm_password.result
  disable_password_authentication = false
  network_interface_ids = [
    azurerm_network_interface.web.id
  ]

  source_image_reference {
    publisher = "Canonical"
    offer     = "UbuntuServer"
    sku       = "18.04-LTS"
    version   = "latest"
  }

  os_disk {
    storage_account_type = "StandardSSD_LRS"
    caching              = "ReadWrite"
  }
}

Terraform CLI Cheat Sheet

Init project first

terraform init

see the plan

terraform plan

apply the plan

terraform apply

show state

terraform show

save plan to file

terraform plan -out=newplan
terraform apply "newplan"

destroy resources

terraform destroy