All cheatsheets
Terraform · Cheatsheet
Terraform Cheatsheet
Modules, workspaces, state surgery, import, plan/apply tips. Plus the OpenTofu equivalents.
Updated 2026-05-21 9 min
Core workflow
| terraform init | Download providers + modules |
| terraform init -upgrade | Upgrade providers to latest matching version |
| terraform fmt -recursive | Format all .tf files |
| terraform validate | Static syntax + type check |
| terraform plan -out=tfplan | Plan and save to file |
| terraform apply tfplan | Apply the saved plan (predictable) |
| terraform destroy -target=module.x | Destroy just one resource/module |
State surgery
| terraform state list | List everything in state |
| terraform state show aws_instance.web | Show full state of one resource |
| terraform state mv old new | Rename without recreating |
| terraform state rm aws_instance.web | Forget about a resource (does not destroy it) |
| terraform import aws_iam_role.lambda role-name | Bring existing resource into state |
| terraform refresh | Sync state with real-world resources |
| terraform force-unlock <LOCK_ID> | Break a stuck state lock (use sparingly) |
Workspaces
| terraform workspace list | List workspaces |
| terraform workspace new staging | Create + switch to a workspace |
| terraform workspace select prod | Switch to existing workspace |
| ${terraform.workspace} | Reference current workspace in code |
Variables & outputs
| terraform plan -var='region=us-east-1' | Override at CLI |
| terraform plan -var-file=prod.tfvars | Override from a file |
| TF_VAR_region=us-east-1 terraform apply | Via env var |
| terraform output -json | All outputs as JSON (CI-friendly) |
| terraform output vpc_id | Single output value |
Modules
| module "vpc" { source = "./modules/vpc" } | Local module |
| source = "terraform-aws-modules/vpc/aws" version = "~> 5.5" | Registry module, pinned |
| source = "git::https://github.com/x/repo.git//path?ref=v1.2.0" | Git module, tagged |
| terraform get -update | Re-pull module sources |
Common HCL idioms
| for_each = toset(["a","b"]) | Iterate a set |
| count = var.enable ? 1 : 0 | Conditional resource |
| dynamic "ingress" { for_each = var.rules content { ... } } | Dynamic nested blocks |
| depends_on = [aws_iam_role.x] | Force ordering |
| lifecycle { prevent_destroy = true } | Guard production resources |
| lifecycle { ignore_changes = [tags["LastModified"]] } | Ignore drifty attributes |
Backends (remote state)
| backend "s3" { bucket=..., key=..., dynamodb_table=... } | S3 + DynamoDB lock — standard |
| terraform init -reconfigure | After changing backend config |
| terraform init -migrate-state | Move state to a new backend |
Speed + safety tricks
| terraform plan -parallelism=20 | Parallelise refresh |
| terraform apply -refresh=false | Skip refresh (faster on huge states) |
| TF_LOG=DEBUG terraform apply 2> tf.log | Verbose log to file |
| terragrunt run-all plan | Plan multiple stacks (Terragrunt) |
| tflint / tfsec / checkov -d . | Lint + security + policy scan |
OpenTofu compatibility
| tofu init / plan / apply | Drop-in replacement, MPL-2.0 |
| tofu state encryption | Native at-rest state encryption (1.7+) |
| Provider syntax unchanged | Same providers, same registry mirror |
Want the full hands-on training behind this?
Cloudadhar batches walk you through every command in a real production setup — with labs, code reviews, and 1:1 doubt sessions.