Intermediate
Quick reference for Terraform — CLI workflow, HCL blocks, providers, variables and outputs, state and backends, modules, data sources, count/for_each, and lifecycle meta-arguments.
IaCHCLStateModules
CLI Workflow
Core Commands
terraform init # install providers, set up backend
terraform fmt -recursive # canonical formatting
terraform validate # syntax + config check
terraform plan -out=tfp # preview changes
terraform apply tfp # apply saved plan
terraform destroy # tear down everything
terraform apply -target=aws_instance.web # target one resource
State Commands
terraform state list
terraform state show aws_instance.web
terraform state mv <src> <dst>
terraform state rm aws_instance.web
terraform import aws_instance.web i-0abc123
terraform output # show output values
HCL Blocks
terraform {
required_version = ">= 1.9"
required_providers {
aws = { source = "hashicorp/aws", version = "~> 5.60" }
}
}
provider "aws" { region = var.region }
resource "aws_instance" "web" {
ami = data.aws_ami.ubuntu.id
instance_type = "t3.micro"
}
| Block | Purpose |
| provider | Platform API plugin |
| resource | Managed object |
| data | Read-only lookup |
| variable / output | Inputs / exports |
| module | Reusable bundle |
Variables & Outputs
variable "env" {
type = string
default = "dev"
validation {
condition = contains(["dev","staging","prod"], var.env)
error_message = "invalid env"
}
}
output "ip" { value = aws_instance.web.public_ip }
Set Values
terraform apply -var="env=prod"
terraform apply -var-file=prod.tfvars
export TF_VAR_env=prod
Remote Backend
terraform {
backend "s3" {
bucket = "acme-tf-state"
key = "prod/terraform.tfstate"
region = "us-east-1"
encrypt = true
use_lockfile = true # native locking (1.10+)
}
}
count vs for_each
# count — numeric index
resource "aws_instance" "w" {
count = 3
tags = { Name = "w-${count.index}" }
}
# for_each — keyed, stable
resource "aws_s3_bucket" "b" {
for_each = toset(["logs","assets"])
bucket = "acme-${each.key}"
}
| Use | When |
| count | Identical copies by number |
| for_each | Keyed set/map; avoids re-indexing |
Modules & Data
module "vpc" {
source = "terraform-aws-modules/vpc/aws"
version = "~> 5.0"
name = "prod-vpc"
cidr = "10.0.0.0/16"
}
# use output: module.vpc.private_subnets[0]
data "aws_ami" "ubuntu" {
most_recent = true
owners = ["099720109477"]
filter { name = "name", values = ["ubuntu-*-24.04-*"] }
}
Workspaces & Lifecycle
terraform workspace new staging
terraform workspace select staging
terraform workspace list
lifecycle {
create_before_destroy = true
prevent_destroy = true
ignore_changes = [tags]
}