Skip to content

/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

CommandDoes
terraform initdownload providers and modules, configure the backend
terraform init -upgradepick the newest provider versions allowed by the constraints
terraform fmt -recursiveformat all .tf files
terraform validatecheck syntax and references (no API calls)
terraform planshow what would change
terraform plan -out=tfplansave the plan for a later apply
terraform apply [tfplan]make the changes
terraform destroydelete everything in the state
terraform output [-json] [NAME]print outputs

State

CommandDoes
terraform state listresources in the state
terraform state show ADDRESSattributes of one resource
terraform state mv OLD NEWrename an address (prefer a moved block)
terraform state rm ADDRESSforget a resource without deleting it (prefer a removed block)
terraform import ADDRESS IDadopt an existing object (prefer an import block)
terraform plan -refresh-onlysee drift between state and reality
terraform force-unlock LOCK_IDrelease 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

hcl
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

bash
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