📋 Cheat Sheets

Terraform Cheat Sheet — Commands, Syntax, and Common Patterns


Click any item to expand the explanation and examples.

🚀 Core Commands

terraform init / plan / apply / destroy cli
# Initialize (download providers, set up backend)
terraform init

Preview changes

terraform plan

Apply changes

terraform apply terraform apply -auto-approve # Skip confirmation

Destroy everything

terraform destroy

Format code

terraform fmt terraform fmt -recursive

Validate syntax

terraform validate

Show current state

terraform show

List resources in state

terraform state list

The workflow: initplanapply. Always plan before apply.

terraform state — manage state cli
# List all resources
terraform state list

Show details of a resource

terraform state show aws_instance.web

Remove resource from state (without destroying it)

terraform state rm aws_instance.web

Move/rename resource in state

terraform state mv aws_instance.web aws_instance.app

Import existing resource into state

terraform import aws_instance.web i-1234567890abcdef0

Pull remote state to local file

terraform state pull > state.json

📐 HCL Syntax

Providers and resources syntax
# Provider
terraform {
  required_providers {
    aws = {
      source  = "hashicorp/aws"
      version = "~> 5.0"
    }
  }
}

provider “aws” { region = “eu-west-1” }

Resource

resource “aws_instance” “web” { ami = “ami-0c55b159cbfafe1f0” instance_type = “t3.micro”

tags = { Name = “web-server” Env = “production” } }

Variables and outputs syntax
# variables.tf
variable "region" {
  type        = string
  default     = "eu-west-1"
  description = "AWS region"
}

variable “instance_type” { type = string default = “t3.micro” }

variable “allowed_cidrs” { type = list(string) default = [“0.0.0.0/0”] }

variable “tags” { type = map(string) default = { Env = “dev” } }

Use variables

resource “aws_instance” “web” { instance_type = var.instance_type tags = var.tags }

outputs.tf

output “instance_ip” { value = aws_instance.web.public_ip description = “Public IP of the web server” }

Set variables

terraform apply -var=“region=us-east-1”

terraform apply -var-file=“prod.tfvars”

export TF_VAR_region=us-east-1

Data sources and locals syntax
# Data source — read existing resources
data "aws_ami" "ubuntu" {
  most_recent = true
  owners      = ["099720109477"]  # Canonical

filter { name = “name” values = [“ubuntu/images/hvm-ssd/ubuntu--amd64-server-”] } }

resource “aws_instance” “web” { ami = data.aws_ami.ubuntu.id }

Locals — computed values

locals { name_prefix = ”${var.project}-${var.environment}” common_tags = { Project = var.project Environment = var.environment ManagedBy = “terraform” } }

resource “aws_instance” “web” { tags = merge(local.common_tags, { Name = ”${local.name_prefix}-web” }) }

🔁 Loops & Conditionals

count, for_each, for loops
# count — create N copies
resource "aws_instance" "web" {
  count         = 3
  ami           = "ami-123"
  instance_type = "t3.micro"
  tags = { Name = "web-${count.index}" }
}

for_each — create from map/set

resource “aws_iam_user” “users” { for_each = toset([“alice”, “bob”, “carol”]) name = each.value }

for_each with map

variable “buckets” { default = { assets = { acl = “private” } logs = { acl = “private” } public = { acl = “public-read” } } }

resource “aws_s3_bucket” “this” { for_each = var.buckets bucket = ”${var.project}-${each.key}” }

for expression

output “instance_ips” { value = [for i in aws_instance.web : i.public_ip] }

Conditional

resource “aws_instance” “bastion” { count = var.create_bastion ? 1 : 0 ami = “ami-123” instance_type = “t3.micro” }

Prefer for_each over count — it’s safer when removing items from the middle of a list.

📦 Modules

Using and creating modules modules
# Use a public module
module "vpc" {
  source  = "terraform-aws-modules/vpc/aws"
  version = "5.0.0"

name = “my-vpc” cidr = “10.0.0.0/16” azs = [“eu-west-1a”, “eu-west-1b”] }

Use a local module

module “web” { source = ”./modules/web-server”

instance_type = “t3.small” subnet_id = module.vpc.public_subnets[0] }

Module structure

modules/web-server/

main.tf

variables.tf

outputs.tf

🗄️ Backend (Remote State)

S3 backend backend
terraform {
  backend "s3" {
    bucket         = "my-terraform-state"
    key            = "prod/terraform.tfstate"
    region         = "eu-west-1"
    dynamodb_table = "terraform-locks"
    encrypt        = true
  }
}
Always use remote state in teams. The DynamoDB table prevents concurrent modifications.

⚡ Tips

Common patterns tips
# Target specific resource
terraform plan -target=aws_instance.web
terraform apply -target=aws_instance.web

Refresh state (detect drift)

terraform refresh

Generate dependency graph

terraform graph | dot -Tpng > graph.png

Workspace (multiple environments)

terraform workspace new staging terraform workspace select production terraform workspace list

Lock version

terraform { required_version = ”>= 1.5.0” }

.gitignore for Terraform

.terraform/

*.tfstate

*.tfstate.backup

*.tfvars (if contains secrets)