Quick Reference
terraform init # Download providers and initialize
terraform fmt # Format code
terraform validate # Check syntax
terraform plan # Preview changes
terraform apply # Apply changes
terraform destroy # Destroy everything
terraform output # Show outputs
terraform state list # List managed resources
terraform import # Import existing resources
terraform console # Interactive expression evaluator
The Core Workflow
Every Terraform project follows the same pattern:
terraform init → terraform plan → terraform apply
terraform init
Initialize the working directory. Downloads providers, sets up backend, installs modules:
terraform init
Common flags:
terraform init -upgrade # Upgrade providers to latest allowed version
terraform init -reconfigure # Reconfigure backend without migration
terraform init -migrate-state # Migrate state to new backend
terraform init -backend=false # Skip backend configuration
Run init when:
- Starting a new project
- Adding a new provider or module
- Changing backend configuration
- Cloning a repo (first time)
terraform plan
Preview what Terraform will do — without changing anything:
terraform plan
# aws_instance.web will be created
+ resource "aws_instance" "web" {
+ ami = "ami-0c55b159cbfafe1f0"
+ instance_type = "t3.micro"
+ id = (known after apply)
}
Plan: 1 to add, 0 to change, 0 to destroy.
Useful flags:
terraform plan -out=plan.tfplan # Save plan to file
terraform plan -target=aws_instance.web # Plan one resource only
terraform plan -var="region=eu-west-1" # Override a variable
terraform plan -destroy # Preview what destroy would do
terraform plan -refresh=false # Skip state refresh (faster)
terraform apply
Apply the changes:
terraform apply # Interactive (asks for confirmation)
terraform apply -auto-approve # Skip confirmation (CI/CD)
terraform apply plan.tfplan # Apply a saved plan
terraform apply -target=aws_instance.web # Apply one resource
terraform apply -replace="aws_instance.web" # Force-recreate a resource
terraform apply -var="env=prod" # Override variable
terraform apply -parallelism=20 # Run 20 operations in parallel (default: 10)
terraform destroy
Destroy all managed resources:
terraform destroy # Interactive
terraform destroy -auto-approve # Skip confirmation
terraform destroy -target=aws_instance.web # Destroy one resource only
Equivalent to: terraform apply -destroy
Formatting and Validation
terraform fmt
Auto-format .tf files to canonical style:
terraform fmt # Format current directory
terraform fmt -check # Check if files are formatted (CI/CD)
terraform fmt -diff # Show what would change
terraform fmt -recursive # Format all subdirectories
Tip: Set up format on save in your editor. The terraform fmt -check flag is perfect for CI pipelines — it exits with code 1 if files aren’t formatted.
terraform validate
Check syntax and internal consistency:
terraform validate
Success! The configuration is valid.
Catches: missing required arguments, invalid references, type mismatches. Does NOT catch: invalid AMI IDs, wrong instance types (use TFLint for that).
State Management
terraform state list
List all resources in state:
$ terraform state list
aws_instance.web
aws_security_group.web
aws_vpc.main
module.database.aws_db_instance.main
terraform state show
Show details of a specific resource:
$ terraform state show aws_instance.web
# aws_instance.web:
resource "aws_instance" "web" {
ami = "ami-0c55b159cbfafe1f0"
instance_type = "t3.micro"
id = "i-0abc123def456"
public_ip = "54.123.45.67"
# ...
}
terraform state mv
Rename a resource in state (without destroying it):
# Rename a resource
terraform state mv aws_instance.web aws_instance.app
# Move into a module
terraform state mv aws_instance.web module.app.aws_instance.web
terraform state rm
Remove a resource from state (Terraform forgets it, but the real resource stays):
terraform state rm aws_instance.web
Use when: you want Terraform to stop managing a resource without destroying it.
terraform state pull / push
terraform state pull > state.json # Download remote state
terraform state push state.json # Upload state (dangerous!)
Import Existing Resources
terraform import
Bring an existing resource under Terraform management:
terraform import aws_instance.web i-0abc123def456
terraform import aws_s3_bucket.data my-bucket-name
terraform import module.vpc.aws_vpc.main vpc-12345678
Workflow:
- Write the resource block in your
.tffile - Run
terraform import - Run
terraform planto verify no changes - Adjust your
.tffile until plan shows no diff
Import Block (Terraform 1.5+)
Declarative import — no CLI needed:
import {
to = aws_instance.web
id = "i-0abc123def456"
}
Then run terraform plan — it generates the configuration for you.
Variables and Outputs
terraform output
Show output values:
terraform output # All outputs
terraform output instance_ip # Specific output
terraform output -json # JSON format
terraform output -raw instance_ip # Raw value (no quotes)
Useful for scripting:
# Use output in a script
IP=$(terraform output -raw instance_ip)
ssh ubuntu@$IP
Passing Variables
terraform apply -var="region=eu-west-1"
terraform apply -var-file="prod.tfvars"
terraform apply -var='tags={"env":"prod"}'
# Environment variables
export TF_VAR_region=eu-west-1
terraform apply
Workspaces
Manage multiple environments with the same configuration:
terraform workspace list # List workspaces
terraform workspace new staging # Create workspace
terraform workspace select prod # Switch workspace
terraform workspace show # Show current workspace
terraform workspace delete staging # Delete workspace
Use in configuration:
resource "aws_instance" "web" {
instance_type = terraform.workspace == "prod" ? "t3.large" : "t3.micro"
tags = {
Environment = terraform.workspace
}
}
Debugging and Inspection
terraform console
Interactive expression evaluator:
$ terraform console
> var.region
"us-east-1"
> length(var.subnets)
3
> cidrsubnet("10.0.0.0/16", 8, 1)
"10.0.1.0/24"
> exit
terraform graph
Generate a dependency graph:
terraform graph | dot -Tpng > graph.png
terraform providers
Show required providers:
$ terraform providers
Providers required by configuration:
.
├── provider[registry.terraform.io/hashicorp/aws] ~> 5.0
└── provider[registry.terraform.io/hashicorp/random] >= 3.0
Debug Logging
export TF_LOG=DEBUG
terraform plan
Log levels: TRACE, DEBUG, INFO, WARN, ERROR.
CI/CD Flags Summary
| Flag | Purpose |
|---|---|
-auto-approve | Skip confirmation prompts |
-input=false | Disable interactive prompts |
-no-color | Disable color output |
-out=plan.tfplan | Save plan for later apply |
-json | Machine-readable JSON output |
-compact-warnings | Reduce warning verbosity |
-parallelism=N | Parallel operations (default 10) |
Typical CI pipeline:
terraform init -input=false
terraform fmt -check
terraform validate
terraform plan -input=false -out=plan.tfplan
terraform apply -input=false plan.tfplan
Hands-On Courses
Learn by doing with interactive courses on CopyPasteLearn:
Conclusion
The core workflow is init → plan → apply. Use fmt and validate in CI. Use state commands to inspect and reorganize managed resources. Use import to bring existing infrastructure under Terraform control. Use console to test expressions. Use -auto-approve and -input=false for automation.




