--- title: Create VM in Azure with Terraform url: https://devopstales.github.io/cloud/azure-terraform/ date: 2023-05-03 keywords: terraform, Azure --- In this post I will show you how how you can create a VM in Azure with Terraform. <!--more--> With Azure we can use Azure blob storage as a shared storage for the Terraform states. So firs we need to create a storage account for this purpose: ```bash az group create --name tf-state-rg \ --location westeurope export STORAGE_ACCOUNT_NAME=tfstatesa$(dd bs=4 count=1 if=/dev/urandom 2>/dev/null | xxd -p) echo $STORAGE_ACCOUNT_NAME tfstatesa273b9cdf az storage account create --name $STORAGE_ACCOUNT_NAME \ --location westeurope \ --resource-group tf-state-rg az storage container create --account-name $STORAGE_ACCOUNT_NAME \ --name tfstate \ --public-access off az storage account key list --resource-group tf-state-rg --account-name $STORAGE_ACCOUNT_NAME ``` Create provider config: ```json nano providers.tf terraform { required_version = ">=0.12" required_providers { azurerm = { source = "hashicorp/azurerm" version = "~>2.0" } } backend "azurerm" { resource_group_name = "tf-state-rg" storage_account_name = "tfstatesa273b9cdf" container_name = "tfstate" key = "terraform.tfstate" } } provider "azurerm" { features {} } ``` Create output config: ```json nano outputs.tf output "resource_group_name" { value = azurerm_resource_group.rg.name } output "public_ip_address" { value = azurerm_linux_virtual_machine.my_terraform_vm.public_ip_address } ``` Create variable config: ```json nano variables.tf variable "resource_group_location" { type = string default = "westeurope" description = "Location of the resource group." } variable "resource_group_name" { type = string default = "egis-terraform-demo" description = "Name of the resource group." } variable "ssh_key" { default = "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABA..." } ``` Create the main Terraform config file vit the resource definitions: ```json nano main.tf resource "azurerm_resource_group" "rg" { location = var.resource_group_location name = var.resource_group_name } # Create virtual network resource "azurerm_virtual_network" "my_terraform_network" { name = "myVnet" address_space = ["10.0.0.0/16"] location = azurerm_resource_group.rg.location resource_group_name = azurerm_resource_group.rg.name } # Create subnet resource "azurerm_subnet" "my_terraform_subnet" { name = "mySubnet" resource_group_name = azurerm_resource_group.rg.name virtual_network_name = azurerm_virtual_network.my_terraform_network.name address_prefixes = ["10.0.1.0/24"] } # Create public IPs resource "azurerm_public_ip" "my_terraform_public_ip" { name = "myPublicIP" location = azurerm_resource_group.rg.location resource_group_name = azurerm_resource_group.rg.name allocation_method = "Dynamic" } # Create Network Security Group and rule resource "azurerm_network_security_group" "my_terraform_nsg" { name = "myNetworkSecurityGroup" location = azurerm_resource_group.rg.location resource_group_name = azurerm_resource_group.rg.name security_rule { name = "SSH" priority = 1001 direction = "Inbound" access = "Allow" protocol = "Tcp" source_port_range = "*" destination_port_range = "22" source_address_prefix = "*" destination_address_prefix = "*" } } # Create network interface resource "azurerm_network_interface" "my_terraform_nic" { name = "myNIC" location = azurerm_resource_group.rg.location resource_group_name = azurerm_resource_group.rg.name ip_configuration { name = "my_nic_configuration" subnet_id = azurerm_subnet.my_terraform_subnet.id private_ip_address_allocation = "Dynamic" public_ip_address_id = azurerm_public_ip.my_terraform_public_ip.id } } # Connect the security group to the network interface resource "azurerm_network_interface_security_group_association" "example" { network_interface_id = azurerm_network_interface.my_terraform_nic.id network_security_group_id = azurerm_network_security_group.my_terraform_nsg.id } # Generate random text for a unique storage account name resource "random_id" "random_id" { keepers = { # Generate a new ID only when a new resource group is defined resource_group = azurerm_resource_group.rg.name } byte_length = 8 } # Create storage account for boot diagnostics resource "azurerm_storage_account" "my_storage_account" { name = "diag${random_id.random_id.hex}" location = azurerm_resource_group.rg.location resource_group_name = azurerm_resource_group.rg.name account_tier = "Standard" account_replication_type = "LRS" } # Create virtual machine resource "azurerm_linux_virtual_machine" "my_terraform_vm" { name = "myVM" location = azurerm_resource_group.rg.location resource_group_name = azurerm_resource_group.rg.name network_interface_ids = [azurerm_network_interface.my_terraform_nic.id] size = "Standard_DS1_v2" os_disk { name = "myOsDisk" caching = "ReadWrite" storage_account_type = "Premium_LRS" } source_image_reference { publisher = "Canonical" offer = "0001-com-ubuntu-server-jammy" sku = "22_04-lts-gen2" version = "latest" } computer_name = "myvm" admin_username = "azureuser" disable_password_authentication = true admin_ssh_key { username = "azureuser" public_key = var.ssh_key } boot_diagnostics { storage_account_uri = azurerm_storage_account.my_storage_account.primary_blob_endpoint } } ``` Now we can create the VM: ```bash az login # init modules terraform init -upgrade # plan creation terraform plan -out main.tfplan # apply plan terraform apply main.tfplan # cleanup terraform plan -destroy -out main.destroy.tfplan terraform apply main.destroy.tfplan ```