Terraform provisions and manages infrastructure declaratively from HCL configuration. This page covers the CLI workflow you'll use daily — init, plan, apply, and the state operations that keep a team's infrastructure in sync.
Installation
terraform versionPrints the installed Terraform version and any configured provider versions.
terraform -helpLists all subcommands. Run `terraform <subcommand> -help` for flags on any of them.
Initialization
terraform initDownloads providers and modules, and configures the backend. Always the first command run in a new or cloned working directory.
terraform init -upgradeInstalls the latest acceptable provider and module versions, ignoring what's currently cached.
terraform init -reconfigureReconfigures the backend from scratch, ignoring any existing saved configuration. Use when backend settings changed.
terraform init -migrate-stateReconfigures the backend and attempts to migrate the existing state to the new backend automatically.
Reconfigure vs. migrate-state
Use -reconfigure when you're pointing at a fresh backend and don't need the old state carried over. Use
-migrate-state when you're moving existing state to a new backend and want Terraform to copy it for you.
Formatting and Validation
terraform fmtRewrites .tf files to the canonical style. Add -recursive to format subdirectories too.
terraform validateChecks configuration syntax and internal consistency without touching any real infrastructure or state.
Planning
terraform planShows what Terraform would change to match configuration, without applying it.
terraform plan -out=tfplanSaves the plan to a file so the exact reviewed plan can be applied later, guaranteeing apply matches what was reviewed.
terraform show tfplanRenders a saved plan file back into human-readable output.
Apply
terraform applyShows a plan and prompts for approval before applying it.
terraform apply tfplanApplies a previously saved plan file exactly as reviewed, with no new plan or prompt.
terraform apply -auto-approveApplies without an interactive approval prompt. Safe in CI with a reviewed plan artifact; risky when run against a fresh plan on a shared environment.
Prefer terraform apply tfplan in pipelines — it applies exactly what was reviewed, rather than re-planning and auto-approving whatever comes out.
Destroy
terraform destroyDestroys every resource Terraform manages in the current workspace. Irreversible for anything without external backups or snapshots.
terraform destroy -target=aws_instance.exampleDestroys only the targeted resource. A scoping escape hatch, not a routine workflow — targeted operations can drift state from configuration.
State
terraform state listLists every resource address currently tracked in state.
terraform state show aws_instance.examplePrints the full recorded attributes of a single resource in state.
terraform state mv aws_instance.old aws_instance.newRenames or moves a resource within state without destroying and recreating the underlying infrastructure.
terraform state rm aws_instance.exampleRemoves a resource from state without destroying it in the real world. The resource keeps running but Terraform forgets about it — a common step before re-importing under a different address.
terraform state pullDownloads and prints the current remote state as raw JSON.
terraform state push terraform.tfstateOverwrites remote state with a local file. Only for recovery — a bad push can corrupt team state for everyone.
Import
terraform import aws_instance.example i-0123456789abcdef0Brings a resource that already exists in the real world under Terraform management, associating it with a resource address in config.
Write the config first
terraform import only populates state — it does not generate the matching .tf configuration. Write (or generate) the resource block first, then import, then run terraform plan to confirm no diff.
Refresh
terraform apply -refresh-only
Updates state to match real infrastructure and shows you the diff first, requiring approval before writing it. The safe way to reconcile drift.
terraform plan -refresh-only
Shows what a refresh would change in state, without writing anything. Use this to detect drift without side effects.
terraform refreshLegacy command that updates state to match real infrastructure immediately, with no plan shown and no approval step. Superseded by terraform apply -refresh-only, which is safer.
Workspaces
terraform workspace listLists all workspaces in the current backend; the active one is marked with an asterisk.
terraform workspace new devCreates a new workspace with its own isolated state file, and switches to it.
terraform workspace select prodSwitches the active workspace without creating one.
Workspaces aren't environments
Terraform workspaces share the same configuration and only isolate state. Most teams use separate root modules or a wrapper like Terragrunt for genuinely distinct environments (different variables, providers, or approval flows) — reserve workspaces for lightweight variations of the same config, like short-lived feature branches.
Troubleshooting
Common failure modes — state locks, drift, provider mismatches — have their own dedicated walkthroughs.
terraform force-unlock LOCK_IDManually releases a stuck state lock. Only run this after confirming no other terraform process is actually running against this state.
See the Terraform Troubleshooting tab for the full diagnostic sequence for state locks, corrupted state, drift, and failed applies.