Hardcoding values like instance types, region names, and resource counts in your Terraform configuration makes it brittle and hard to reuse. Variables and outputs make configurations flexible and composable.
Input Variables
Input variables are parameters for your Terraform module or root configuration:
variable "environment" {
description = "Deployment environment (dev, staging, production)"
type = string
default = "dev"
validation {
condition = contains(["dev", "staging", "production"], var.environment)
error_message = "Must be dev, staging, or production."
}
}
variable "instance_type" {
description = "EC2 instance type"
type = string
default = "t3.micro"
}
variable "instance_count" {
description = "Number of instances"
type = number
default = 1
}
variable "allowed_cidrs" {
description = "List of CIDRs allowed to access the app"
type = list(string)
default = ["0.0.0.0/0"]
}
variable "tags" {
description = "Tags to apply to all resources"
type = map(string)
default = {}
}
# Sensitive variables — values are hidden in plan/apply output
variable "db_password" {
description = "Database master password"
type = string
sensitive = true
}
Variable Types
| Type | Example |
|---|---|
| string | "us-east-1" |
| number | 3 |
| bool | true |
| list(string) | ["a", "b", "c"] |
| set(string) | Like list but unique, unordered |
| map(string) | { key = "value" } |
| object({...}) | Structured type with named attrs |
| tuple([...]) | Fixed-length list with mixed types |
| any | No type constraint |
Assigning Variable Values
# Command line flag
terraform apply -var="environment=production" -var="instance_count=3"
# Variable definition file (.tfvars)
terraform apply -var-file="production.tfvars"
# Automatically loaded files (no -var-file needed)
# terraform.tfvars or *.auto.tfvars
# Environment variables
export TF_VAR_environment=production
export TF_VAR_db_password=mysecret
terraform apply
# production.tfvars
environment = "production"
instance_type = "t3.large"
instance_count = 3
tags = {
Team = "platform"
CostCenter = "eng-infra"
}
Local Values
Locals compute values used in multiple places — DRY principle applied to Terraform:
locals {
name_prefix = "${var.project}-${var.environment}"
common_tags = merge(var.tags, {
Project = var.project
Environment = var.environment
ManagedBy = "terraform"
})
is_production = var.environment == "production"
}
resource "aws_instance" "app" {
tags = merge(local.common_tags, {
Name = "${local.name_prefix}-app"
})
}
resource "aws_db_instance" "db" {
multi_az = local.is_production # enable Multi-AZ only in prod
}
Output Values
Outputs expose values after terraform apply. They appear in the terminal output, and are accessible to parent modules:
output "vpc_id" {
description = "The ID of the VPC"
value = aws_vpc.main.id
}
output "load_balancer_dns" {
description = "DNS name of the load balancer"
value = aws_lb.main.dns_name
}
output "db_endpoint" {
description = "RDS endpoint"
value = aws_db_instance.main.endpoint
sensitive = true # hide in logs and plan output
}
terraform output # show all outputs
terraform output vpc_id # show specific output
terraform output -json # JSON format for scripting
Next: Terraform State — the mechanism that tracks your infrastructure and enables Terraform to determine what needs to change.