Loading source
Pulling the file list, source metadata, and syntax-aware rendering for this listing.
Source from repo
Prepare Azure environments for new workloads—subscriptions, networking, identity, and landing zones
Files
Skill
Size
Entrypoint
Format
Open file
Syntax-highlighted preview of this file as included in the skill package.
references/recipes/terraform/patterns.md
1# Terraform Patterns23Common patterns for Terraform Azure deployments.45## File Structure67```8infra/9├── main.tf # Main resources10├── variables.tf # Variable definitions11├── outputs.tf # Output values12├── terraform.tfvars # Variable values13├── backend.tf # State backend14└── modules/15└── ...16```1718## Provider Configuration1920```hcl21# backend.tf22terraform {23required_version = ">= 1.5.0"2425required_providers {26azurerm = {27source = "hashicorp/azurerm"28version = "~> 3.0"29}30azurecaf = {31source = "aztfmod/azurecaf"32version = "~> 1.2"33}34}3536backend "azurerm" {37resource_group_name = "rg-terraform-state"38storage_account_name = "tfstate<unique>"39container_name = "tfstate"40key = "app.terraform.tfstate"41}42}4344provider "azurerm" {45features {}46}47```4849## Variables5051```hcl52# variables.tf53variable "environment" {54type = string55description = "Environment name"56}5758variable "location" {59type = string60description = "Azure region"61default = "eastus2"62}63```6465## Main Configuration6667```hcl68# main.tf69resource "azurerm_resource_group" "main" {70name = "rg-${var.environment}"71location = var.location72tags = { environment = var.environment }73}7475module "app" {76source = "./modules/app"77resource_group_name = azurerm_resource_group.main.name78location = azurerm_resource_group.main.location79environment = var.environment80}81```8283## Outputs8485```hcl86# outputs.tf87output "resource_group_name" {88value = azurerm_resource_group.main.name89}9091output "app_url" {92value = module.app.url93}94```9596## Naming with Azure CAF9798```hcl99resource "azurecaf_name" "storage" {100name = var.environment101resource_type = "azurerm_storage_account"102random_length = 5103}104105resource "azurerm_storage_account" "main" {106name = azurecaf_name.storage.result107# ...108}109```110111## State Backend Setup112113```bash114# Create state storage115az group create --name rg-terraform-state --location eastus2116117az storage account create \118--name tfstate<unique> \119--resource-group rg-terraform-state \120--sku Standard_LRS121122az storage container create \123--name tfstate \124--account-name tfstate<unique>125```126127## Security Requirements128129| Requirement | Pattern |130|-------------|---------|131| No hardcoded secrets | Use Key Vault data sources |132| Managed Identity | `identity { type = "UserAssigned" }` |133| State encryption | Azure Storage encryption |134| State locking | Azure Blob lease |135136## Container Apps with ACR137138> **⚠️ Two-Phase Deployment Required.** See [Container Apps Terraform Patterns](../../services/container-apps/terraform.md) for full details.139140Use a **public placeholder image** during initial provisioning. Never reference an ACR image that hasn't been built yet. Do **not** use `admin_enabled` on the ACR or add a `registry` block with `username`/`password_secret_name` — use managed identity instead.141142```hcl143resource "azurerm_container_app" "api" {144# ...145template {146container {147name = "api"148image = "mcr.microsoft.com/azuredocs/containerapps-helloworld:latest"149# ...150}151}152153# Prevent Terraform from reverting post-apply image and registry updates154lifecycle {155ignore_changes = [156template[0].container[0].image,157registry,158]159}160}161```162163After `terraform apply`, build the real image and update the Container App via CLI — see the **azure-deploy** skill's `references/recipes/terraform/README.md` (Container Apps Two-Phase Deployment section).164