Terraform Introduction
The problem Infrastructure as Code solves, installing Terraform, and terraform init.
The problem: infrastructure by clicking doesn't scale
Provisioning cloud infrastructure by clicking through a web console works fine for a single server on a personal project. It breaks down fast once real requirements show up:
- It doesn't scale to more than a few resources. Manually recreating a VPC, subnets, security groups, an EC2 instance, and a database by clicking through a console — correctly, in the right order, with the right settings — for a second environment (staging, a second region, a disaster-recovery copy) is slow and error-prone.
- It isn't reviewable. A pull request can be read, commented on, and approved before it's merged. A sequence of console clicks leaves no diff anyone can review before it takes effect.
- It isn't reproducible. Six months later, nobody can say with confidence exactly what settings were chosen when a resource was created, because the only record was a person's memory of clicking through a UI.
- It drifts. Someone fixes an urgent problem by tweaking a setting directly in the console; that change is now invisible to everyone else and to any documentation that assumed the original configuration still holds.
Infrastructure as Code (IaC)
Infrastructure as Code means describing your infrastructure — servers, networks, databases, permissions — as text files, and using a tool to make the real infrastructure match that description. This gets you everything manual console work lacks:
- Version control — infrastructure changes go through the same
git diff, pull request, and code review workflow as application code. - Repeatability — spinning up an identical staging environment, or rebuilding production after a disaster, is running the same code again, not remembering a sequence of manual steps.
- A single source of truth — the
.tffiles describe what infrastructure is supposed to exist; if reality has drifted from that (someone made a manual change), the tool can detect and report the difference.
What Terraform is
Terraform (by HashiCorp) is the most widely used IaC tool. You write declarative configuration — you describe the desired end state ("a t3.micro EC2 instance running Ubuntu, in this subnet, with this security group"), not the imperative steps to get there. Terraform figures out what API calls are needed to make reality match your description, whether that means creating something new, changing an existing resource, or destroying one no longer in your config.
Terraform works with essentially every major cloud provider (AWS, Azure, GCP) and hundreds of other systems (Kubernetes, Datadog, GitHub itself) through providers — plugins that translate Terraform's generic resource model into calls against a specific system's API. This is covered in depth on the next page.
Installing Terraform
On macOS (Homebrew):
brew tap hashicorp/tap
brew install hashicorp/tap/terraform
On Debian/Ubuntu:
wget -O- https://apt.releases.hashicorp.com/gpg | sudo gpg --dearmor -o /usr/share/keyrings/hashicorp-archive-keyring.gpg
echo "deb [signed-by=/usr/share/keyrings/hashicorp-archive-keyring.gpg] https://apt.releases.hashicorp.com $(lsb_release -cs) main" | sudo tee /etc/apt/sources.list.d/hashicorp.list
sudo apt update && sudo apt install terraform
Verify it installed correctly:
terraform version
terraform init
Every Terraform project (a directory of .tf files) starts with terraform init, run once before any other command:
terraform init
This does three things:
- Downloads and installs the providers referenced in your configuration (e.g. the AWS provider plugin).
- Sets up the backend — where Terraform's state file will be stored (locally by default; a remote backend is covered on the next page).
- Downloads any modules your configuration references.
You re-run init any time you add a new provider or module, or change the backend configuration. It's safe to run repeatedly — it won't touch your actual infrastructure.
Common mistakes
- Treating Terraform config as a one-time setup script rather than the living, ongoing source of truth for infrastructure — config that isn't kept in sync with reality defeats the entire point.
- Making a manual change in the cloud console "just this once" — the next
terraform planwill either try to revert it or report unexpected drift. - Skipping
terraform initafter pulling changes that add a new provider or module, then being confused by an error that a provider "isn't installed." - Committing the provider's downloaded plugin binaries (the
.terraform/directory) to version control — it's regenerated byinitand should be gitignored.