Terraform Cheat Sheet
The Terraform commands and HCL patterns developers actually use daily — resources, variables, state, and modules — with real examples, common mistakes, and a searchable quick reference.
Core Workflow & CLI
Four commands you'll run constantly, in almost this exact order, every time you touch a Terraform directory.
terraform initInitializes a working directory: downloads providers and modules, sets up the backend. Always the first command in a new or freshly-cloned Terraform directory.
terraform planShows exactly what Terraform would change — create, update, destroy — without actually doing any of it. Always read a plan before applying it.
terraform applyApplies the changes described in a plan, prompting for confirmation first unless -auto-approve is passed.
terraform plan -out=tfplan terraform apply tfplan
terraform destroyDestroys every resource Terraform is currently managing in state.
terraform validateChecks configuration files for syntax errors and internal consistency, without contacting any provider or touching real infrastructure.
terraform fmtRewrites configuration files into Terraform's canonical formatting style — the HCL equivalent of a code formatter.
Providers & Resources
A provider is the plugin that knows how to talk to a specific platform. A resource is the actual thing you want it to create.
provider "aws" { ... }Configures a provider — the plugin Terraform uses to talk to a specific platform (AWS, Google Cloud, Kubernetes, and hundreds more).
provider "aws" { region = "us-east-1" }
resource "aws_instance" "web" { ... }Declares a piece of infrastructure Terraform should create and manage — the type (aws_instance) comes from the provider, the name (web) is your own label.
resource "aws_instance" "web" { ami = "ami-123456" instance_type = "t2.micro" }
aws_instance.webReferences a declared resource elsewhere in your configuration — in an output, another resource's argument, or an expression.
aws_instance.web["primary"]References one specific instance out of a resource created with for_each, by its key.
Variables & Outputs
How configuration gets values in, and how results get values back out.
variable "instance_type" { ... }Declares an input variable, with an optional type constraint and default value.
variable "instance_type" { type = string default = "t2.micro" }
var.instance_typeReferences a declared variable's value anywhere in the configuration.
output "instance_ip" { ... }Exposes a value after apply — printed to the terminal, and available to any module that calls this configuration as a child module.
output "instance_ip" { value = aws_instance.web.public_ip }
terraform.tfvarsA file providing values for declared variables, loaded automatically if it's named exactly terraform.tfvars (or matches *.auto.tfvars).
terraform apply -var="instance_type=t2.large"Overrides a single variable's value from the command line, taking priority over any default or tfvars file.
terraform apply -var-file="prod.tfvars"Loads variable values from a specific file — the usual way to point the same configuration at a different environment's values.
State Management
The file linking your configuration to real infrastructure — and the part teams most often get wrong first.
terraform state listLists every resource currently tracked in state.
terraform state show aws_instance.webShows the full recorded attributes of one specific resource in state.
terraform state mv aws_instance.old aws_instance.newRenames a resource in state without destroying and recreating the real infrastructure — the fix when you rename a resource block in code and don't want Terraform to treat it as brand new.
terraform state rm aws_instance.webRemoves a resource from state without destroying the real infrastructure — Terraform simply stops tracking it.
terraform { backend "s3" { ... } }Configures a remote backend — where state is actually stored, instead of a local file on one person's machine.
terraform { backend "s3" { bucket = "my-terraform-state" key = "prod/terraform.tfstate" } }
Modules
Reusable, self-contained bundles of configuration — call one the same way you'd call a function.
module "vpc" { ... }Calls a reusable module, either from a local path (shown here) or a registry source like terraform-aws-modules/vpc/aws, passing in its input variables.
module "vpc" { source = "./modules/vpc" cidr_block = "10.0.0.0/16" }
module.vpc.vpc_idReferences one of a called module's declared outputs, the same way you'd reference a resource's attribute.
terraform getDownloads or updates modules referenced by the configuration, without doing a full init.
Data Sources & Expressions
Reading information Terraform doesn't manage, and the small expression language that ties everything else together.
data "aws_ami" "latest" { ... }Reads information about an existing resource Terraform isn't managing — the read-only counterpart to a resource block.
data "aws_ami" "latest" { most_recent = true owners = ["amazon"] }
data.aws_ami.latest.idReferences an attribute from a declared data source.
"${var.name}-bucket"Splices a value into the middle of a literal string using interpolation syntax.
[for s in var.subnets : s.id]A for expression — transforms a list or map into another list or map, the closest thing HCL has to a loop.
var.environment == "prod" ? "t3.large" : "t3.micro"A conditional expression — evaluates to the first value if the condition is true, the second if it's false.
Workspaces
A lightweight way to keep multiple states under one configuration — with real limitations worth knowing before you rely on them.
terraform workspace new stagingCreates a new workspace — a distinct state, kept separate from other workspaces, under the same configuration and backend.
terraform workspace select stagingSwitches to a different existing workspace.
terraform workspace listLists every workspace and marks the currently active one.
terraform.workspaceA built-in reference to the current workspace's name, usable inside your configuration — for example, to vary an instance size or a resource's tags per environment.
Provisioners & Lifecycle
Fine-tuning exactly how and when Terraform is allowed to change or replace a resource.
lifecycle { create_before_destroy = true }Creates the replacement resource before destroying the original, instead of the default destroy-then-create order — avoids a window with no resource at all for anything that can't tolerate downtime.
lifecycle { prevent_destroy = true }Makes Terraform refuse to destroy this specific resource, causing plan or apply to error out instead — a guardrail for anything genuinely irreplaceable.
lifecycle { ignore_changes = [tags] }Tells Terraform to stop treating drift on specific arguments as something to fix — useful when another system (like autoscaling) legitimately manages that field after creation.
depends_on = [aws_instance.web]Forces an explicit dependency between resources that Terraform can't infer automatically from a direct reference — used sparingly, when a real ordering requirement isn't otherwise visible in the configuration.
provisioner "local-exec" { ... }Runs an arbitrary script when a resource is created or destroyed — deliberately the last option on this page, not a first choice.
provisioner "local-exec" { command = "echo done" }
Import & Refactoring
Bringing infrastructure that already exists under Terraform's management, and reshaping configuration without losing track of what's real.
terraform import aws_instance.web i-1234567890abcdef0Brings a resource that already exists in the real world — created manually, or by another tool — under Terraform's management, without recreating it.
moved { ... }Declares that a resource was renamed or moved in configuration, so Terraform updates state to match instead of destroying the old address and creating the new one — the modern, version-controlled alternative to running terraform state mv by hand.
moved { from = aws_instance.old_name to = aws_instance.new_name }
Quick Reference
Already comfortable with Terraform — just blanked on a syntax fragment? Search instead of scrolling.
terraform initDownload providers/modules and set up the backend
terraform planShow exactly what would change, without changing anything
terraform applyApply the changes, prompting for confirmation first
terraform apply -auto-approveApply without an interactive confirmation prompt
terraform plan -out=tfplanSave an exact plan to a file for later review and apply
terraform destroyDestroy every resource Terraform is managing
terraform validateCheck configuration syntax without touching real infrastructure
terraform fmtRewrite files into Terraform's canonical formatting
provider "aws" { }Configure a provider — the plugin talking to a specific platform
resource "type" "name" { }Declare a piece of infrastructure to create and manage
aws_instance.webReference a resource elsewhere in the configuration
variable "name" { }Declare an input variable with a type and optional default
var.nameReference a declared variable's value
output "name" { }Expose a value after apply, or to a calling module
terraform.tfvarsFile providing variable values, loaded automatically
-var="key=value"Override a single variable from the command line
-var-file="prod.tfvars"Load variable values from a specific file
terraform state listList every resource currently tracked in state
terraform state showShow one resource's full recorded attributes in state
terraform state mvRename a resource in state without destroying it
terraform state rmStop tracking a resource without destroying it
backend "s3" { }Configure where state is stored remotely
module "name" { }Call a reusable module by local path or registry source
module.name.outputReference an output value from a called module
terraform getDownload or update modules without a full init
data "type" "name" { }Read information about an existing resource, not manage it
data.type.name.attrReference a data source's attribute
"${var.name}-bucket"Splice a value into the middle of a literal string
[for s in var.list : s.id]Transform a list or map into another list or map
cond ? a : bConditional expression — a if cond is true, else b
terraform workspace newCreate a new named workspace
terraform workspace selectSwitch to a different workspace
terraform workspace listList every workspace, marking the active one
terraform.workspaceReference the current workspace's name in configuration
create_before_destroyCreate the replacement before destroying the original
prevent_destroyBlock Terraform from ever destroying this resource
ignore_changesIgnore drift on specific arguments after creation
depends_onForce an explicit dependency Terraform can't infer on its own
provisioner "local-exec"Run a local script after a resource is created — a last resort
terraform importBring existing infrastructure under Terraform's management
moved { }Declare a resource rename so Terraform doesn't recreate it
41 of 41 commands
Common Use Cases
Real situations, not just isolated syntax — the exact sequence that gets you through each one.
You need to rename a resource in code without destroying it
Update state to match, or declare the rename directly in configuration:
- terraform state mv aws_instance.old aws_instance.new
You want to preview a change before touching real infrastructure
Save the exact plan, review it, then apply precisely that:
- terraform plan -out=tfplan
- terraform apply tfplan
You need different instance sizes for dev vs. prod
One configuration, a separate tfvars file per environment:
- terraform apply -var-file="prod.tfvars"
You already created a resource by hand and want Terraform to manage it
Import it, then confirm your config actually matches:
- terraform import aws_instance.web i-abc123
- terraform plan
You need to replace a resource with zero downtime
Create the replacement before tearing down the original:
- lifecycle { create_before_destroy = true }
You want to safely test a destructive-looking change
Read the plan's summary line before ever running apply:
- terraform plan
- // check "X to destroy" before continuing
Debugging & Troubleshooting
The exact error text Terraform actually prints, decoded.
Error: Resource already existsSomething with that identity already exists in the real world but isn't in Terraform's state. Import it if it should be managed going forward, or rename/remove one side if it's genuinely a duplicate.
terraform import aws_instance.web i-abc123Error acquiring the state lockAnother plan or apply is already running against the same state, or a previous run crashed and left a stale lock behind. Confirm nothing is genuinely still running before force-unlocking.
terraform force-unlock LOCK_IDPlan shows a destroy and recreate for a change that looks smallSome resource arguments are ForceNew — the provider's API has no way to update that specific property in place, so destroy-then-recreate is the only option Terraform has. Check that argument's documentation before applying if this surprises you.
Error: Provider configuration not presentUsually a module or resource referencing a provider that was never configured, or a mismatched alias. Check every provider block, and any explicit providers = or provider = argument.
terraform apply keeps prompting for a variable with no defaultThe variable has no default and wasn't supplied via -var, -var-file, or a *.auto.tfvars file. Provide it one of those ways instead of typing it in manually at every apply.
State and real infrastructure have drifted apartSomething changed outside Terraform — manually, or by another tool. terraform plan shows the drift as a diff; terraform apply reconciles it back to what's in your configuration. Review carefully before applying — it might revert an intentional manual fix.
terraform planThings to Remember
If you forget everything else on this page, keep these.
- Always run terraform plan and actually read it before terraform apply — apply does exactly what the plan says, no exceptions.
- State is the single source of truth linking your configuration to real infrastructure — use a remote backend with locking for anything beyond a personal experiment.
- terraform state mv (or a moved block) renames a resource without destroying it; editing state by hand should be rare and deliberate.
- Pin module versions the same way you'd pin a package dependency — an unpinned module can change out from under you.
- Provisioners are a last resort per Terraform's own docs — prefer a resource's native arguments or cloud-init whenever one exists.
- A variable with no default will interactively prompt for a value — always supply one via a default, -var, or a tfvars file in automation.
- Some resource changes force a destroy-and-recreate even when the diff looks small — read what plan actually says, not just what you expect.
- terraform import brings existing infrastructure under management without recreating it — always run plan immediately after to confirm your configuration actually matches.
- fmt and validate cost nothing and catch real mistakes — run them before every commit, not just before apply.
Common Use Cases
About Terraform Cheat Sheet
Terraform's documentation is thorough per-resource and scattered everywhere else, and most cheat sheets either dump the CLI verb list flat or show HCL syntax in complete isolation — without ever explaining the workflow that actually matters day to day: why you read a plan before applying it, what state genuinely is and why losing it is a real problem, or why changing one small argument can make Terraform want to destroy and recreate a resource instead of just updating it.
This one starts with the core init, plan, apply, destroy workflow and CLI basics, into providers and resources — the actual building blocks — variables and outputs, and state management, the part teams most often get wrong first. From there it covers modules, data sources and expressions, workspaces, provisioners and lifecycle rules, and import for bringing existing infrastructure under management.
Every section calls out the mistakes that actually cause outages or wasted afternoons: applying without reading what the plan actually says, treating a local state file as fine once more than one person touches the configuration, an unpinned module version changing out from under you, reaching for a provisioner before checking whether the resource already has a native argument for what you need. There's a searchable quick reference for the moment you already know roughly what you want, and a troubleshooting section built around the exact error text Terraform prints — a state lock, a ForceNew attribute, a missing provider configuration — not a paraphrase of it.
Nothing on this page talks to a real cloud provider, a state backend, or any actual infrastructure — it's a static reference, like every tool on AllCoreKit. The quick-reference search filters entirely in your browser, and nothing you read or search for is ever sent anywhere or logged.
Frequently Asked Questions
Related Tools
View all Cheat SheetsGit Cheat Sheet
The Git commands developers actually use daily, organized by workflow — branching, rebasing, undoing mistakes, and recovery — with real examples and a searchable quick reference.
Regex Cheat Sheet
The regex syntax developers actually reach for — anchors, character classes, groups, and lookaround — with real patterns, common mistakes, and a searchable quick reference.
Prompt Engineering Cheat Sheet
The prompt patterns that actually change LLM output — anatomy, few-shot, chain-of-thought, and structured formatting — with real examples, pitfalls, and a searchable quick reference.