/cheatsheets/terraform/terraform-cheat-sheet
Terraform cheat sheet: init, plan, apply, state and workspaces
verified onenvironmentlocal · windows 10.0.26200 arm64 · GNU bash 5.3.15 (Git Bash) · Terraform v1.16.6updated 2026-10-20
- tool
- Terraform
- versions
- Terraform 1.5+, OpenTofu 1.6+
- os
- any
The Terraform commands and language constructs used most, grouped by task. Every command also works with tofu (OpenTofu) in place of terraform.
Workflow
| Command | Does |
|---|---|
| terraform init | download providers and modules, configure the backend |
| terraform init -upgrade | pick the newest provider versions allowed by the constraints |
| terraform fmt -recursive | format all .tf files |
| terraform validate | check syntax and references (no API calls) |
| terraform plan | show what would change |
| terraform plan -out=tfplan | save the plan for a later apply |
| terraform apply [tfplan] | make the changes |
| terraform destroy | delete everything in the state |
| terraform output [-json] [NAME] | print outputs |
State
| Command | Does |
|---|---|
| terraform state list | resources in the state |
| terraform state show ADDRESS | attributes of one resource |
| terraform state mv OLD NEW | rename an address (prefer a moved block) |
| terraform state rm ADDRESS | forget a resource without deleting it (prefer a removed block) |
| terraform import ADDRESS ID | adopt an existing object (prefer an import block) |
| terraform plan -refresh-only | see drift between state and reality |
| terraform force-unlock LOCK_ID | release a stuck state lock |
Workspaces
terraform workspace list, terraform workspace new staging, terraform workspace select staging; terraform.workspace holds the current name inside the configuration.
Language snippets
variable "names" {
type = list(string)
default = ["web", "api"]
}
locals {
tags = { project = "demo", env = terraform.workspace }
}
resource "terraform_data" "svc" {
for_each = toset(var.names)
input = "${each.key}-${local.tags.env}"
}
output "ids" {
value = { for k, r in terraform_data.svc : k => r.id }
}Try it offline
cat > main.tf <<'EOF'
variable "names" {
type = list(string)
default = ["web", "api"]
}
resource "terraform_data" "svc" {
for_each = toset(var.names)
input = each.key
}
EOF
terraform init -input=false -no-color >/dev/null
terraform fmt -check && terraform validate -no-color
terraform plan -no-color -input=false | grep -E 'will be created|^Plan:'Output
Success! The configuration is valid. # terraform_data.svc["api"] will be created # terraform_data.svc["web"] will be created Plan: 2 to add, 0 to change, 0 to destroy.
terraform_data is built into Terraform, so this needs no provider and no cloud account.
Sources
Related pages
commands · terraformterraform fmt -check and -recursive: format HCL filesterraform fmt rewrites .tf files in canonical style; -check only reports unformatted files with a non-zero exit, -diff shows changes, -recursive adds modules.flags · terraformterraform plan -out: save a plan and apply exactly that planterraform plan -out=tfplan saves the plan to a file; terraform apply tfplan then applies exactly those changes without a prompt. Inspect it with terraform show.glossary · terraformWhat is Terraform state?Terraform state is the JSON record that maps each resource address in your code to the real object it manages and its last known attributes: terraform.tfstate.