Core Commands — From Blueprint to Building
The builder has written a blueprint (an .tf file in HCL). Now the contractor needs to build from it. Terraform's core commands are the steps that turn notation into real infrastructure — and, crucially, they let you preview everything before anything changes.
Providers — Hiring the Contractors
Terraform itself doesn't build anything. Providers are the plugins that talk to a real cloud — each one is a specialized contractor company (AWS, Azure, GCP, GitHub, and thousands more).
terraform {
required_providers {
aws = {
source = "hashicorp/aws"
version = "~> 5.0"
}
}
}
provider "aws" {
region = "eu-west-1"
}
The required_providers block pins which company and version to use. The provider "aws" block sets its settings, like the region where the colony will be built.
Resources and Data Sources
Resources — things Terraform creates and manages
resource "aws_s3_bucket" "archive" {
bucket = "campus-library-archive"
}
Terraform will create this bucket, remember it, and track every future change to it.
Data sources — things that already exist, that you want to read
data "aws_ami" "ubuntu" {
most_recent = true
owners = ["099720109477"]
filter {
name = "name"
values = ["ubuntu/images/hvm-ssd/ubuntu-*-amd64-server-*"]
}
}
A data source reads information about existing infrastructure (like "what's the latest Ubuntu AMI?") without managing it. Reference it as data.aws_ami.ubuntu.id.
Resource = "build and manage this." Data source = "just tell me about that." If Terraform created it, it's a resource; if it merely reads it, it's a data source.
The Lifecycle — Commands in Order
terraform init
terraform fmt
terraform validate
terraform plan
terraform apply
1 · terraform init — the first contractor meeting
Downloads the provider plugins and sets up the working directory. Run it once when you start, and again when you change providers.
terraform init
Initializing the backend...
Initializing provider plugins...
- Finding hashicorp/aws versions matching "~> 5.0"...
- Installing hashicorp/aws v5.x.x...
Terraform has been successfully initialized!
It also creates terraform.lock.hcl — the dependency lock file that pins exact provider versions so the whole team uses identical contractors.
2 · terraform fmt — tidy the blueprint
Reformats your .tf files to the standard style (indentation, spacing). No logic changes — just neatness.
terraform fmt
3 · terraform validate — check the blueprint for errors
Checks syntax and internal consistency without touching any cloud. The builder's proofread.
terraform validate
Success! The configuration is valid.
4 · terraform plan — show what will happen
The magic step. Terraform compares the blueprint against reality (via state) and prints exactly what it would create, change, or delete. It changes nothing.
terraform plan
Plan: 1 to add, 0 to change, 0 to destroy.
You can save a plan to a file and apply exactly that plan later:
terraform plan -out plan.tfplan
A plan that says "0 to destroy" is what you expect for new infrastructure. If a plan unexpectedly lists things to destroy, read it carefully before applying — see the Troubleshooting desk.
5 · terraform apply — build it
Executes the plan and creates, updates, or deletes resources. By default it re-plans and asks for confirmation.
terraform apply
Do you want to perform these actions?
Terraform will perform the actions described above.
Only 'yes' will be accepted to approve.
Enter a value: yes
aws_s3_bucket.archive: Creating...
aws_s3_bucket.archive: Creation complete after 2s
Apply complete! Resources: 1 added, 0 changed, 0 destroyed.
To skip the prompt (used in scripts and CI):
terraform apply -auto-approve
Inspecting What You Built
terraform show # full view of state + outputs
terraform output # just the declared outputs
terraform output archive_arn # one specific output
terraform console # interactive shell for expressions
terraform graph # dependency graph as DOT (visualizable)
terraform output
archive_arn = "arn:aws:s3:::campus-library-archive"
Refreshing — Checking Reality
If someone changed infrastructure outside Terraform (drift), update state to match reality without changing anything:
terraform apply -refresh-only
Destroy — Demolition Day
Tears down everything the configuration created — the reverse of apply.
terraform destroy
Destroy complete! Resources: 1 destroyed.
destroy removes real infrastructure and costs. In practice, team destroys run only in temporary environments — the permanent colony usually lives forever.
Command Cheat Sheet
| Command | What it does | When to use |
|---|---|---|
terraform init | Downloads providers, sets up backend | First time, or when providers change |
terraform fmt | Reformats files to standard style | Before validate, on every save |
terraform validate | Checks config for errors (no cloud access) | Before plan, in CI |
terraform plan | Shows what would change; changes nothing | Always before apply |
terraform apply | Creates/updates/deletes resources | After reviewing a plan |
terraform apply -auto-approve | Applies without the prompt | Scripts and CI |
terraform apply -refresh-only | Updates state to match reality | After external changes |
terraform destroy | Deletes everything in the config | Cleaning up |
terraform show | Displays state and outputs | Inspecting |
terraform output | Prints declared outputs | Reading results |
terraform console | Interactive expression playground | Experimenting |
terraform graph | Exports the dependency graph | Visualizing |
Next, understand the quiet hero behind all of this: the site register — Terraform state.