TerraformPilot

Terraform

How to Use Terraform with Azure - Complete Setup Guide

Set up Terraform with Microsoft Azure from scratch. Covers Azure CLI login, service principal, provider configuration, resource groups, and first deployment.

LLuca Berton1 min read

Quick Answer

#

Install Terraform, authenticate with Azure (CLI or service principal), configure the azurerm provider, and deploy. Service principals are recommended for CI/CD; Azure CLI login works for local development.

Prerequisites

#
# Install Azure CLI
curl -sL https://aka.ms/InstallAzureCLIDeb | sudo bash
 
# Login to Azure
az login
 
# Set your subscription
az account set --subscription "My Subscription"
az account show

Authentication Methods

#

Method 1: Azure CLI (Local Development)

#
provider "azurerm" {
  features {}
  # Uses your az login session automatically
}
#
# Create a service principal
az ad sp create-for-rbac --name "terraform-sp" \
  --role Contributor \
  --scopes "/subscriptions/YOUR_SUBSCRIPTION_ID"
provider "azurerm" {
  features {}
  subscription_id = var.subscription_id
  client_id       = var.client_id
  client_secret   = var.client_secret
  tenant_id       = var.tenant_id
}
# Set as environment variables (preferred over hardcoding)
export ARM_SUBSCRIPTION_ID="your-sub-id"
export ARM_CLIENT_ID="your-client-id"
export ARM_CLIENT_SECRET="your-client-secret"
export ARM_TENANT_ID="your-tenant-id"

Method 3: Managed Identity (Azure VMs/Pipelines)

#
provider "azurerm" {
  features {}
  use_msi = true
}

First Azure Resource

#
terraform {
  required_providers {
    azurerm = {
      source  = "hashicorp/azurerm"
      version = "~> 3.90"
    }
  }
}
 
provider "azurerm" {
  features {}
}
 
resource "azurerm_resource_group" "main" {
  name     = "myapp-prod-rg"
  location = "East US"
}
 
resource "azurerm_virtual_network" "main" {
  name                = "myapp-vnet"
  address_space       = ["10.0.0.0/16"]
  location            = azurerm_resource_group.main.location
  resource_group_name = azurerm_resource_group.main.name
}
 
resource "azurerm_subnet" "app" {
  name                 = "app-subnet"
  resource_group_name  = azurerm_resource_group.main.name
  virtual_network_name = azurerm_virtual_network.main.name
  address_prefixes     = ["10.0.1.0/24"]
}
terraform init
terraform plan
terraform apply

Remote State with Azure Blob

#
# Create storage account for state
az storage account create --name myapptfstate --resource-group myapp-rg \
  --sku Standard_LRS --encryption-services blob
 
az storage container create --name tfstate --account-name myapptfstate
terraform {
  backend "azurerm" {
    resource_group_name  = "myapp-rg"
    storage_account_name = "myapptfstate"
    container_name       = "tfstate"
    key                  = "prod.terraform.tfstate"
  }
}

Common Azure Resources

#
# Linux VM
resource "azurerm_linux_virtual_machine" "web" {
  name                = "web-vm"
  resource_group_name = azurerm_resource_group.main.name
  location            = azurerm_resource_group.main.location
  size                = "Standard_B2s"
  admin_username      = "azureuser"
 
  network_interface_ids = [azurerm_network_interface.web.id]
 
  admin_ssh_key {
    username   = "azureuser"
    public_key = file("~/.ssh/id_rsa.pub")
  }
 
  os_disk {
    caching              = "ReadWrite"
    storage_account_type = "Standard_LRS"
  }
 
  source_image_reference {
    publisher = "Canonical"
    offer     = "0001-com-ubuntu-server-jammy"
    sku       = "22_04-lts"
    version   = "latest"
  }
}

Azure vs AWS Terraform Comparison

#
ConceptAWSAzure
Account isolationAWS AccountResource Group
NetworkingVPCVirtual Network
IdentityIAMAzure AD + RBAC
StorageS3Blob Storage
ComputeEC2Virtual Machines
Providerhashicorp/awshashicorp/azurerm
Auth env varsAWS_ACCESS_KEY_IDARM_CLIENT_ID

Troubleshooting

#
ErrorFix
AuthorizationFailedAssign Contributor role to SP
SubscriptionNotFoundCheck ARM_SUBSCRIPTION_ID
features {} requiredAdd empty features {} block to provider
MissingSubscriptionSet subscription: az account set
#

Conclusion

#

Terraform with Azure works best with service principals for CI/CD and Azure CLI for local development. Start with a resource group, add networking, then build up. Use Azure Blob Storage for remote state with locking.

#Terraform#Azure#Infrastructure as Code#DevOps

Share this article