Terraform guide
What Terraform does in production
Teams describe desired infrastructure — VPCs, VMs, databases, DNS, IAM roles,
Kubernetes clusters — in version-controlled
.tf files. Terraform computes a dependency graph, talks to provider
APIs, and creates, updates, or destroys resources to match the config. CI pipelines
(GitHub Actions,
Jenkins) run terraform plan on pull
requests and apply on approved merges.
Core building blocks
- Provider — plugin for a platform (e.g.
hashicorp/aws) - Resource — something Terraform manages (
aws_instance,google_compute_instance) - Data source — read-only lookup of existing infrastructure
- Variable — input parameter (
variable "region" { }) - Output — exported values after apply (IDs, endpoints)
- Module — reusable bundle of resources with inputs/outputs
Minimal configuration
terraform {
required_version = ">= 1.5"
required_providers {
aws = {
source = "hashicorp/aws"
version = "~> 5.0"
}
}
}
provider "aws" {
region = var.region
}
resource "aws_s3_bucket" "logs" {
bucket = var.bucket_name
}
Plan and apply lifecycle
- init — download providers, configure backend
- validate — syntax and internal consistency
- plan — preview create/update/destroy (no changes applied)
- apply — execute the plan; updates state file
- destroy — tear down managed resources (use with care)
Always review plan output in CI and production — unexpected
destroy lines often mean a renamed resource or removed block.
State
Terraform stores a mapping of resource addresses to real-world IDs in
state. Local terraform.tfstate works for solo learning;
teams use remote backends (S3 + DynamoDB lock, GCS, Terraform
Cloud, etc.) so state is shared and locking prevents concurrent applies corrupting
state. Never commit secrets in state — it may contain sensitive attributes.
Workspaces
Workspaces split state for the same code (e.g. dev,
staging, prod). Alternatively use separate directories or
separate backend keys per environment — pick one convention and document it.
Modules and the registry
Publish and consume modules from the Terraform Registry or private registries. Pin module versions. Root modules call child modules; outputs flow up the tree. Similar spirit to Helm charts for Kubernetes — packaged, versioned infrastructure patterns.
Secrets and credentials
Provider credentials come from environment variables, shared credentials files, or
OIDC in CI — not hardcoded in .tf. For application secrets after
infrastructure exists, use Vault or cloud
secret managers rather than storing them in Terraform variables in plain text.
Drift and import
Manual changes in a cloud console cause drift — next plan shows
diffs. terraform import adopts existing resources into state.
terraform refresh (implicit in plan) reconciles state with reality.
Key files in a project
*.tf— configuration*.tfvars— variable values per environment (often gitignored for secrets).terraform.lock.hcl— provider checksum lock (commit this)terraform.tfstate— local state (prefer remote backend in teams)
Learning resources
- Terraform documentation — developer.hashicorp.com/terraform
- Configuration language — HCL syntax
- Best practices — Recommended practices
- Provider registry — registry.terraform.io