Cloud  /  Terraform

IaC Terraform 50 guides · updated 2026

Infrastructure as code done right — providers, state, reusable modules, and the workflow patterns that keep multi-cloud deployments sane in 2026.

Terraform Input Variables

Input variables make Terraform configurations flexible and reusable. Instead of hardcoding values, you declare variables for anything that changes between environments, deployments, or users — then supply the actual values separately.


Declaring Input Variables

variables.tf
variable "environment" {
description = "Target deployment environment"
type = string
default = "dev"
}
variable "instance_count" {
description = "Number of application server instances"
type = number
default = 2
}
variable "enable_deletion_protection" {
description = "Prevent accidental database deletion"
type = bool
default = true
}
variable "allowed_cidr_blocks" {
description = "CIDR blocks allowed to reach the application load balancer"
type = list(string)
default = ["0.0.0.0/0"]
}
variable "database_config" {
description = "RDS database configuration"
type = object({
engine = string
engine_version = string
instance_class = string
allocated_storage = number
})
default = {
engine = "postgres"
engine_version = "16.3"
instance_class = "db.t3.micro"
allocated_storage = 20
}
}

Using Variables in Configuration

Reference variables with var.<variable_name>:

main.tf
resource "aws_instance" "app" {
count = var.instance_count
instance_type = var.environment == "production" ? "t3.large" : "t3.micro"
tags = {
Environment = var.environment
Name = "app-${var.environment}-${count.index + 1}"
}
}
resource "aws_db_instance" "main" {
engine = var.database_config.engine
engine_version = var.database_config.engine_version
instance_class = var.database_config.instance_class
allocated_storage = var.database_config.allocated_storage
deletion_protection = var.enable_deletion_protection
}

Supplying Variable Values

1. terraform.tfvars (Auto-Loaded)

terraform.tfvars
environment = "staging"
instance_count = 3
allowed_cidr_blocks = [
"10.0.0.0/8",
"172.16.0.0/12"
]
database_config = {
engine = "postgres"
engine_version = "16.3"
instance_class = "db.t3.small"
allocated_storage = 50
}

2. Named .tfvars Files

Terminal window
terraform apply -var-file="environments/production.tfvars"
terraform apply -var-file="environments/staging.tfvars"

3. Environment Variables

Terraform reads environment variables prefixed with TF_VAR_:

Terminal window
export TF_VAR_environment="production"
export TF_VAR_instance_count="5"
terraform apply

4. Command-Line -var Flag

Terminal window
terraform apply -var="environment=production" -var="instance_count=5"

Variable Precedence (Highest to Lowest)

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

Variables with Validation

variable "environment" {
type = string
default = "dev"
validation {
condition = contains(["dev", "staging", "production"], var.environment)
error_message = "environment must be 'dev', 'staging', or 'production'."
}
}
variable "instance_type" {
type = string
validation {
condition = can(regex("^(t3|t3a|m6i|m6a|c6i)\\.(micro|small|medium|large|xlarge|2xlarge)$", var.instance_type))
error_message = "Must be a valid EC2 instance type in the approved family."
}
}
variable "port" {
type = number
default = 8080
validation {
condition = var.port >= 1024 && var.port <= 65535
error_message = "Port must be between 1024 and 65535."
}
}
variable "tags" {
type = map(string)
validation {
condition = contains(keys(var.tags), "Team") && contains(keys(var.tags), "CostCenter")
error_message = "Tags map must include 'Team' and 'CostCenter' keys."
}
}

Sensitive Variables

variable "database_password" {
description = "RDS master password"
type = string
sensitive = true # Value hidden in plan/apply output and state
}
variable "api_key" {
type = string
sensitive = true
}

When sensitive = true:

Terminal window
# Pass sensitive values via environment variables — never in terraform.tfvars
export TF_VAR_database_password="$(aws secretsmanager get-secret-value \
--secret-id prod/rds/password --query SecretString --output text)"

Complex Variable Types

# List of objects
variable "users" {
type = list(object({
name = string
email = string
role = string
}))
default = [
{ name = "Alice", email = "alice@example.com", role = "admin" },
{ name = "Bob", email = "bob@example.com", role = "reader" }
]
}
resource "aws_iam_user" "team" {
for_each = { for u in var.users : u.name => u }
name = each.value.name
tags = {
Email = each.value.email
Role = each.value.role
}
}
# Map of objects
variable "environments" {
type = map(object({
instance_type = string
instance_count = number
enable_ha = bool
}))
default = {
dev = {
instance_type = "t3.micro"
instance_count = 1
enable_ha = false
}
production = {
instance_type = "t3.large"
instance_count = 3
enable_ha = true
}
}
}