Skip to content

10.7 Terraform Variables

Overview

This section provides a comprehensive reference for all variables used in the infrastructure configuration. Variables allow customization without modifying the main Terraform code.

Variable Definition File

All variables are defined in variables.tf:

# Location and Resource Group
variable "resource_group_location" { ... }
variable "resource_group_name_prefix" { ... }

# Authentication
variable "username" { ... }
variable "password" { ... }

# Networking
variable "virtual_network_name" { ... }
variable "subnet_name" { ... }
variable "public_ip_name" { ... }
variable "network_security_group_name" { ... }
variable "network_interface_name" { ... }

# Compute
variable "virtual_machine_name" { ... }
variable "virtual_machine_size" { ... }
variable "disk_name" { ... }
variable "redundancy_type" { ... }

# Load Balancer
variable "load_balancer_name" { ... }

Location and Resource Group Variables

resource_group_location

variable "resource_group_location" {
  type        = string
  default     = "eastus"
  description = "Location of the resource group."
}

Purpose: Specifies the Azure region for all resources

Default: "eastus"

Common Values: - "eastus" - East US - "eastus2" - East US 2 - "westus2" - West US 2 - "centralus" - Central US - "westeurope" - West Europe - "northeurope" - North Europe - "southeastasia" - Southeast Asia

How to Choose: - Proximity to users (lower latency) - Compliance requirements - Service availability - Cost (varies by region)

List Available Regions:

az account list-locations --output table

resource_group_name_prefix

variable "resource_group_name_prefix" {
  type        = string
  default     = "rg"
  description = "Prefix of the resource group name that's combined with a random ID so name is unique in your Azure subscription."
}

Purpose: Prefix for randomly generated resource group name

Default: "rg"

Examples: - "rg" → rg-happy-dolphin - "prod-rg" → prod-rg-brave-tiger - "dev-lb" → dev-lb-golden-panther

Authentication Variables

username

variable "username" {
  type        = string
  default     = "azureadmin"
  description = "The username for the local account that will be created on the new VM."
}

Purpose: Admin username for VM login

Default: "azureadmin"

Restrictions: - Cannot be "admin", "administrator", "root", "guest" - 1-64 characters - Cannot start with a number

Best Practice: Use a non-obvious username for security

password

variable "password" {
  type        = string
  default     = ""
  description = "The password for the local account that will be created on the new VM."
}

Purpose: Admin password for VM login

Default: "" (empty, triggers random password generation)

Requirements: - 12-72 characters - Must have 3 of: lowercase, uppercase, number, special character - Cannot contain username

Security Note: If left empty, a random 16-character password is generated

Networking Variables

virtual_network_name

variable "virtual_network_name" {
  type        = string
  default     = "test-vnet"
  description = "Name of the Virtual Network."
}

Purpose: Name for the Virtual Network

Default: "test-vnet"

Naming Convention: <environment>-<purpose>-vnet - "prod-web-vnet" - "dev-app-vnet" - "staging-lb-vnet"

subnet_name

variable "subnet_name" {
  type        = string
  default     = "test-subnet"
  description = "Name of the subnet."
}

Purpose: Name for the subnet

Default: "test-subnet"

Naming Convention: <tier>-subnet - "frontend-subnet" - "backend-subnet" - "web-subnet"

public_ip_name

variable "public_ip_name" {
  type        = string
  default     = "test-public-ip"
  description = "Name of the Public IP."
}

Purpose: Name for the public IP address

Default: "test-public-ip"

Naming Convention: <resource>-<purpose>-pip - "lb-frontend-pip" - "web-public-ip"

network_security_group_name

variable "network_security_group_name" {
  type        = string
  default     = "test-nsg"
  description = "Name of the Network Security Group."
}

Purpose: Name for the Network Security Group

Default: "test-nsg"

Naming Convention: <subnet>-nsg - "web-subnet-nsg" - "frontend-nsg"

network_interface_name

variable "network_interface_name" {
  type        = string
  default     = "test-nic"
  description = "Name of the Network Interface."
}

Purpose: Base name for network interfaces (indexed 0, 1)

Default: "test-nic"

Result: Creates test-nic0 and test-nic1

Naming Convention: <vm-name>-nic - "web-vm-nic" → web-vm-nic0, web-vm-nic1

Compute Variables

virtual_machine_name

variable "virtual_machine_name" {
  type        = string
  default     = "test-vm"
  description = "Name of the Virtual Machine."
}

Purpose: Base name for virtual machines (indexed 0, 1)

Default: "test-vm"

Result: Creates test-vm0 and test-vm1

Restrictions: - 1-64 characters - Alphanumeric and hyphens - Cannot start or end with hyphen

Naming Convention: <environment>-<purpose>-vm - "prod-web-vm" → prod-web-vm0, prod-web-vm1

virtual_machine_size

variable "virtual_machine_size" {
  type        = string
  default     = "Standard_B2s"
  description = "Size or SKU of the Virtual Machine."
}

Purpose: Specifies VM size/SKU

Default: "Standard_B2s" (2 vCPU, 4 GB RAM)

Common Sizes:

Size vCPU RAM Use Case Monthly Cost*
Standard_B1s 1 1 GB Minimal workloads ~$8
Standard_B2s 2 4 GB Dev/Test ~$30
Standard_B2ms 2 8 GB Small production ~$60
Standard_D2s_v3 2 8 GB Production ~$70
Standard_D4s_v3 4 16 GB High performance ~$140

*Approximate costs for East US region

List Available Sizes:

az vm list-sizes --location eastus --output table

disk_name

variable "disk_name" {
  type        = string
  default     = "test-disk"
  description = "Name of the OS disk of the Virtual Machine."
}

Purpose: Base name for OS disks (indexed 0, 1)

Default: "test-disk"

Result: Creates test-disk0 and test-disk1

redundancy_type

variable "redundancy_type" {
  type        = string
  default     = "Standard_LRS"
  description = "Storage redundancy type of the OS disk."
}

Purpose: Specifies storage redundancy level

Default: "Standard_LRS"

Options:

Type Description Copies Use Case Cost
Standard_LRS Locally redundant HDD 3 (same datacenter) Dev/Test $
StandardSSD_LRS Locally redundant SSD 3 (same datacenter) General purpose $$
Premium_LRS Premium SSD 3 (same datacenter) Production $$$
Premium_ZRS Zone-redundant Premium 3 (across zones) High availability $$$$

Load Balancer Variables

load_balancer_name

variable "load_balancer_name" {
  type        = string
  default     = "test-lb"
  description = "Name of the Load Balancer."
}

Purpose: Name for the load balancer

Default: "test-lb"

Naming Convention: <purpose>-lb - "web-lb" - "frontend-lb" - "public-lb"

Using Variables

Method 1: terraform.tfvars File

Create or edit terraform.tfvars:

# Location
resource_group_location = "westus2"

# Naming
resource_group_name_prefix = "prod-web"
virtual_machine_name       = "web-vm"
load_balancer_name         = "web-lb"

# VM Configuration
virtual_machine_size = "Standard_B2ms"
redundancy_type      = "StandardSSD_LRS"

# Authentication
username = "webadmin"
password = "MySecureP@ssw0rd123!"

Method 2: Command Line

terraform apply \
  -var="resource_group_location=westus2" \
  -var="virtual_machine_size=Standard_B2ms" \
  -var="username=webadmin"

Method 3: Environment Variables

export TF_VAR_resource_group_location="westus2"
export TF_VAR_virtual_machine_size="Standard_B2ms"
export TF_VAR_username="webadmin"

terraform apply

Method 4: Variable Files

# Create production.tfvars
terraform apply -var-file="production.tfvars"

# Create development.tfvars
terraform apply -var-file="development.tfvars"

Example Configurations

Development Environment

# dev.tfvars
resource_group_location    = "eastus"
resource_group_name_prefix = "dev"
virtual_machine_name       = "dev-vm"
virtual_machine_size       = "Standard_B1s"
redundancy_type            = "Standard_LRS"
load_balancer_name         = "dev-lb"
username                   = "devadmin"

Usage:

terraform apply -var-file="dev.tfvars"

Production Environment

# prod.tfvars
resource_group_location    = "eastus2"
resource_group_name_prefix = "prod"
virtual_machine_name       = "prod-web-vm"
virtual_machine_size       = "Standard_D2s_v3"
redundancy_type            = "Premium_LRS"
load_balancer_name         = "prod-web-lb"
username                   = "prodadmin"
password                   = ""  # Use random generation

Usage:

terraform apply -var-file="prod.tfvars"

Multi-Region Deployment

# us-east.tfvars
resource_group_location    = "eastus"
resource_group_name_prefix = "useast"
virtual_network_name       = "useast-vnet"

# us-west.tfvars
resource_group_location    = "westus2"
resource_group_name_prefix = "uswest"
virtual_network_name       = "uswest-vnet"

Variable Validation

Add validation rules to variables:

variable "resource_group_location" {
  type        = string
  default     = "eastus"
  description = "Location of the resource group."

  validation {
    condition     = contains(["eastus", "eastus2", "westus2", "centralus"], var.resource_group_location)
    error_message = "Location must be one of: eastus, eastus2, westus2, centralus."
  }
}

variable "virtual_machine_size" {
  type        = string
  default     = "Standard_B2s"
  description = "Size or SKU of the Virtual Machine."

  validation {
    condition     = can(regex("^Standard_", var.virtual_machine_size))
    error_message = "VM size must start with 'Standard_'."
  }
}

Sensitive Variables

Mark sensitive variables:

variable "password" {
  type        = string
  default     = ""
  description = "The password for the local account that will be created on the new VM."
  sensitive   = true
}

Effect: Value won't be displayed in Terraform output

Variable Precedence

Terraform loads variables in this order (later overrides earlier):

  1. Environment variables (TF_VAR_*)
  2. terraform.tfvars file
  3. terraform.tfvars.json file
  4. *.auto.tfvars files (alphabetical order)
  5. -var and -var-file command line flags

Best Practices

  1. Use terraform.tfvars: For environment-specific values
  2. Don't Commit Secrets: Add *.tfvars to .gitignore (except examples)
  3. Document Variables: Provide clear descriptions
  4. Set Sensible Defaults: For development/testing
  5. Validate Input: Use validation blocks
  6. Use Naming Conventions: Consistent, descriptive names
  7. Separate Environments: Use different .tfvars files
  8. Mark Sensitive Data: Use sensitive = true

Common Patterns

Conditional Resources

variable "enable_monitoring" {
  type    = bool
  default = false
}

resource "azurerm_monitor_diagnostic_setting" "example" {
  count = var.enable_monitoring ? 1 : 0
  # ... configuration ...
}

Dynamic Counts

variable "vm_count" {
  type    = number
  default = 2
}

resource "azurerm_linux_virtual_machine" "example" {
  count = var.vm_count
  # ... configuration ...
}

Complex Objects

variable "vm_config" {
  type = object({
    size  = string
    count = number
    disk_size = number
  })
  default = {
    size      = "Standard_B2s"
    count     = 2
    disk_size = 30
  }
}

Next Steps

Proceed to 10.8-Outputs.md to learn about the output values provided by this infrastructure.