Quick Answer
Input variables parameterize your config. Output values expose results. Local values compute intermediate values. Define variables in variables.tf, set them in terraform.tfvars, and expose results in outputs.tf.
Input Variables
Basic Variable Types
# String
variable "environment" {
type = string
description = "Deployment environment"
default = "dev"
}
# Number
variable "instance_count" {
type = number
default = 2
}
# Boolean
variable "enable_monitoring" {
type = bool
default = true
}
# List
variable "availability_zones" {
type = list(string)
default = ["us-east-1a", "us-east-1b", "us-east-1c"]
}
# Map
variable "instance_types" {
type = map(string)
default = {
dev = "t3.micro"
staging = "t3.small"
prod = "t3.medium"
}
}
# Object
variable "database" {
type = object({
engine = string
instance_class = string
allocated_storage = number
})
default = {
engine = "postgres"
instance_class = "db.t3.micro"
allocated_storage = 20
}
}
Using Variables
resource "aws_instance" "web" {
count = var.instance_count
ami = data.aws_ami.ubuntu.id
instance_type = var.instance_types[var.environment]
tags = {
Name = "web-${var.environment}-${count.index}"
Environment = var.environment
}
}
Variable Validation
variable "environment" {
type = string
validation {
condition = contains(["dev", "staging", "prod"], var.environment)
error_message = "Environment must be dev, staging, or prod."
}
}
variable "instance_type" {
type = string
validation {
condition = can(regex("^t3\\.", var.instance_type))
error_message = "Only t3.* instance types are allowed."
}
}
Sensitive Variables
variable "db_password" {
type = string
sensitive = true # Won't show in plan output
}
Setting Variable Values
terraform.tfvars (Auto-loaded)
# terraform.tfvars
environment = "prod"
instance_count = 3
enable_monitoring = true
Environment-Specific Files
# Apply with a specific var file
terraform apply -var-file="prod.tfvars"
Command Line
terraform apply -var="environment=prod" -var="instance_count=3"
Environment Variables
export TF_VAR_environment="prod"
export TF_VAR_db_password="secret123"
terraform apply
Precedence (Highest to Lowest)
-varflag on command line*.auto.tfvarsfiles (alphabetical order)terraform.tfvars- Environment variables (
TF_VAR_*) - Variable defaults
Output Values
# outputs.tf
output "instance_ids" {
description = "IDs of the web instances"
value = aws_instance.web[*].id
}
output "load_balancer_dns" {
description = "DNS name of the load balancer"
value = aws_lb.main.dns_name
}
output "db_endpoint" {
description = "Database connection endpoint"
value = aws_db_instance.main.endpoint
sensitive = true # Hidden from console output
}
# View outputs after apply
terraform output
terraform output load_balancer_dns
terraform output -json # Machine-readable
Local Values
locals {
name_prefix = "${var.project}-${var.environment}"
common_tags = {
Project = var.project
Environment = var.environment
ManagedBy = "terraform"
}
}
resource "aws_instance" "web" {
ami = data.aws_ami.ubuntu.id
instance_type = var.instance_types[var.environment]
tags = merge(local.common_tags, { Name = "${local.name_prefix}-web" })
}
File Organization
project/
├── main.tf # Resources
├── variables.tf # Variable declarations
├── outputs.tf # Output declarations
├── locals.tf # Local values
├── terraform.tfvars # Default values
├── dev.tfvars # Dev overrides
├── staging.tfvars # Staging overrides
└── prod.tfvars # Production overrides
Related Articles
- Terraform Data Sources Guide
- How to Structure a Terraform Project
- Terraform for_each vs count
- Terraform Glossary
Conclusion
Use input variables for parameterization, outputs to expose values to other configs, and locals for computed intermediate values. Always add type, description, and validation to variables. Use .tfvars files per environment and never hardcode secrets — use sensitive = true and environment variables.




