Terraform Cheatsheet

Essential Terraform CLI commands, HCL syntax patterns, state management, modules, functions, and lifecycle rules. Bookmark this page for quick reference during your infrastructure-as-code workflows.

Core Workflow Commands

CommandDescription
terraform initInitialize working directory, download providers and modules
terraform init -upgradeRe-initialize and upgrade all providers to latest allowed versions
terraform init -backend-config=FILEInitialize with external backend configuration file
terraform validateCheck configuration syntax and internal consistency
terraform planPreview changes without applying (dry run)
terraform plan -out=plan.tfplanSave plan to file for exact apply later
terraform plan -target=aws_instance.webPlan changes for a specific resource only
terraform plan -var="region=us-west-2"Pass a variable value on the command line
terraform applyApply changes to reach desired infrastructure state
terraform apply plan.tfplanApply a previously saved plan file (no confirmation prompt)
terraform apply -auto-approveApply without interactive confirmation
terraform destroyDestroy all managed infrastructure resources
terraform destroy -target=aws_instance.webDestroy a specific resource only
terraform fmtFormat configuration files to canonical style
terraform fmt -recursiveFormat all .tf files in subdirectories recursively
terraform showDisplay current state or a saved plan in human-readable form
terraform versionPrint Terraform and provider versions
terraform providersList providers required by the configuration

State Management

CommandDescription
terraform state listList all resources tracked in state
terraform state show aws_instance.webShow attributes of a single resource in state
terraform state mv aws_instance.old aws_instance.newRename or move a resource in state (avoids destroy/recreate)
terraform state rm aws_instance.webRemove a resource from state without destroying it
terraform state pullDownload and print current remote state as JSON
terraform state push local.tfstateUpload a local state file to the remote backend
terraform state replace-provider hashicorp/aws registry.example.com/awsReplace provider in state after registry migration
terraform refreshReconcile state with real infrastructure (read-only update)

Workspace Commands

CommandDescription
terraform workspace listList all workspaces (current marked with *)
terraform workspace new stagingCreate a new workspace named "staging"
terraform workspace select productionSwitch to the "production" workspace
terraform workspace showPrint the name of the current workspace
terraform workspace delete stagingDelete a workspace (must be empty and not current)
terraform.workspaceReference current workspace name in HCL config

Import & Taint

CommandDescription
terraform import aws_instance.web i-0123456789Import existing resource into Terraform state
terraform import module.vpc.aws_vpc.main vpc-abc123Import a resource inside a module
terraform taint aws_instance.webMark resource for forced recreation on next apply
terraform untaint aws_instance.webRemove taint mark, prevent forced recreation
terraform apply -replace=aws_instance.webForce replacement of a resource (preferred over taint)

Output & Console

CommandDescription
terraform outputDisplay all output values from state
terraform output instance_ipDisplay a specific output value
terraform output -jsonDisplay all outputs in JSON format
terraform output -raw instance_ipDisplay output without quotes (useful for scripts)
terraform consoleOpen interactive console to evaluate expressions
terraform graph | dot -Tpng > graph.pngGenerate visual dependency graph (requires Graphviz)

HCL Syntax Quick Reference

PatternDescription
variable "name" { type = string }Declare an input variable with type constraint
variable "name" { default = "value" }Variable with a default value
variable "name" { sensitive = true }Mark variable to hide value from CLI output
var.nameReference a variable value
output "name" { value = aws_instance.web.id }Declare an output value
locals { env = "prod" }Define local values for reuse within a module
local.envReference a local value
data "aws_ami" "latest" { ... }Declare a data source to read external information
data.aws_ami.latest.idReference a data source attribute
terraform { required_version = ">= 1.5" }Constrain the required Terraform version
terraform { required_providers { ... } }Declare required provider versions

Resource Block Structure

PatternDescription
resource "aws_instance" "web" { ... }Declare a resource (type + local name)
aws_instance.web.idReference a resource attribute
aws_instance.web[0].idReference resource created with count by index
aws_instance.web["key"].idReference resource created with for_each by key
depends_on = [aws_vpc.main]Explicit dependency between resources
provisioner "local-exec" { command = "echo done" }Run local command after resource creation
provisioner "remote-exec" { inline = [...] }Run commands on the remote resource via SSH
connection { type = "ssh" ... }Configure SSH connection for remote provisioners

Provider Configuration

PatternDescription
provider "aws" { region = "us-east-1" }Configure the AWS provider with a region
provider "aws" { alias = "west" }Create an aliased provider for multi-region setups
resource "aws_instance" "w" { provider = aws.west }Use a specific provider alias in a resource
provider "google" { project = "my-proj" }Configure the Google Cloud provider
provider "azurerm" { features {} }Configure the Azure provider

Module Usage

PatternDescription
module "vpc" { source = "./modules/vpc" }Use a local module from relative path
module "vpc" { source = "terraform-aws-modules/vpc/aws" }Use a module from the Terraform Registry
module "vpc" { source = "git::https://example.com/vpc.git" }Use a module from a Git repository
module "vpc" { source = "..." version = "~> 3.0" }Pin module version with constraint
module.vpc.vpc_idReference a module output value
terraform getDownload modules referenced in configuration
terraform get -updateUpdate already-downloaded modules

Backend Configuration

PatternDescription
backend "s3" { bucket = "tf-state" key = "prod/terraform.tfstate" region = "us-east-1" }Store state in AWS S3
backend "s3" { ... dynamodb_table = "tf-locks" }Enable state locking with DynamoDB
backend "azurerm" { storage_account_name = "tfstate" container_name = "state" }Store state in Azure Blob Storage
backend "gcs" { bucket = "tf-state" prefix = "prod" }Store state in Google Cloud Storage
backend "local" { path = "terraform.tfstate" }Store state locally (default backend)
terraform { cloud { organization = "my-org" } }Use Terraform Cloud / HCP Terraform as backend
terraform init -migrate-stateMigrate state when changing backend configuration

Terraform Functions

FunctionDescription
lookup(map, key, default)Look up a key in a map with fallback default value
merge(map1, map2)Merge two or more maps together (last wins)
join(", ", list)Join list elements into a single string with separator
split(",", string)Split a string into a list by delimiter
format("Hello, %s!", var.name)Format a string with printf-style verbs
lower(string) / upper(string)Convert string to lowercase or uppercase
replace(string, search, replace)Replace occurrences in a string
length(list_or_map)Return number of elements in a list or map
flatten([list1, [list2]])Flatten nested lists into a single flat list
toset(list)Convert a list to a set (removes duplicates)
try(expression, fallback)Return first expression that does not error
coalesce(val1, val2, ...)Return first non-null, non-empty value
cidrsubnet("10.0.0.0/16", 8, 1)Calculate subnet CIDR within a network prefix
file("path/to/file")Read contents of a file as a string
templatefile("tpl.tftpl", { name = "val" })Render a template file with variables
jsonencode(value) / jsondecode(string)Encode value as JSON / decode JSON string
base64encode(string) / base64decode(string)Base64 encode or decode a string
keys(map) / values(map)Return all keys or values from a map
element(list, index)Return element at index (wraps around)
compact(list)Remove empty strings from a list

Conditional Expressions & Loops

PatternDescription
condition ? true_val : false_valTernary conditional expression
count = var.create ? 1 : 0Conditionally create a resource using count
count = 3Create 3 identical copies of a resource
count.indexCurrent index (0-based) inside a count loop
for_each = toset(["a", "b", "c"])Create one resource per item in a set
for_each = var.instancesCreate one resource per entry in a map
each.key / each.valueReference current key and value in for_each
[for s in var.list : upper(s)]Transform a list with a for expression
{for k, v in var.map : k => upper(v)}Transform a map with a for expression
[for s in var.list : s if s != ""]Filter a list with a for expression
dynamic "ingress" { for_each = var.rules content { ... } }Generate repeated nested blocks dynamically
dynamic "ingress" { ... content { port = ingress.value } }Reference iterator value inside dynamic block

Lifecycle Rules

PatternDescription
lifecycle { prevent_destroy = true }Reject any plan that would destroy this resource
lifecycle { ignore_changes = [tags] }Ignore external changes to specific attributes
lifecycle { ignore_changes = all }Ignore all external attribute changes
lifecycle { create_before_destroy = true }Create replacement before destroying original (zero downtime)
lifecycle { replace_triggered_by = [aws_ami.latest.id] }Force replacement when referenced value changes
lifecycle { precondition { condition = ... error_message = "..." } }Validate assumption before creating resource
lifecycle { postcondition { condition = ... error_message = "..." } }Validate result after creating resource

Frequently Asked Questions

What is the difference between terraform plan and terraform apply?

terraform plan creates an execution plan showing what changes Terraform will make to your infrastructure without actually applying them. It is a safe dry run that lets you review additions, modifications, and deletions before committing. terraform apply executes those changes against your real infrastructure. Best practice is to always run plan first, review the output carefully, and then apply. You can save a plan with -out=plan.tfplan and apply that exact plan to ensure consistency.

How do I import existing infrastructure into Terraform state?

Use terraform import RESOURCE_TYPE.NAME RESOURCE_ID to bring existing infrastructure under Terraform management. First, write a matching resource block in your .tf file, then run the import command with the cloud provider's resource ID. For example: terraform import aws_instance.web i-0123456789abcdef0. After importing, run terraform plan to verify your configuration matches the actual resource and adjust any differences.

What is the purpose of Terraform workspaces?

Terraform workspaces let you manage multiple distinct sets of infrastructure from a single configuration directory. Each workspace maintains its own separate state file. This is commonly used for dev, staging, and production environments. Create a workspace with terraform workspace new staging, switch with terraform workspace select production, and reference the current workspace name in your config using terraform.workspace to vary settings per environment.

When should I use count vs for_each in Terraform?

count creates a given number of identical resources referenced by numeric index. for_each creates one resource per item in a map or set, referenced by key. Prefer for_each in most cases because removing an item from the middle of a list with count causes all subsequent resources to shift indexes and be recreated, while for_each only affects the specific item removed.

How do I prevent Terraform from destroying a critical resource?

Add a lifecycle block with prevent_destroy = true inside the resource definition. This makes Terraform reject any plan that would destroy that resource, including terraform destroy. To eventually remove it, first set prevent_destroy = false and apply, or use terraform state rm to remove the resource from state without destroying the actual infrastructure.

What is a Terraform backend and why should I use a remote one?

A Terraform backend determines where state data is stored and how operations are executed. The default local backend saves state to a file on disk. Remote backends like S3, Azure Blob Storage, or GCS store state centrally, enabling team collaboration, state locking to prevent concurrent modifications, versioning, and encryption at rest. Using a remote backend is essential for any team or production Terraform workflow.