📋 Cheat Sheets
· 4 min read

Terraform Cheat Sheet — Commands, Syntax, and Common Patterns


Some links in this article are affiliate links. We earn a commission at no extra cost to you when you purchase through them. Full disclosure.

Click any item to expand the explanation and examples. New to Terraform? Start with what is Terraform or compare it with alternatives in Terraform vs Pulumi.

🚀 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)

Quick access: Raycast lets you search commands, snippets, and cheat sheets instantly from your keyboard. Free for Mac.

Related:* What is Terraform? A Simple Explanation for Developers