Skip to main content

Lesson: Provisioning with Terraform

What you'll learn

  • What Terraform is for: provisioning infrastructure (creating VMs, networks, DNS, etc.).
  • The core building blocks: providers, resources, and HCL syntax.
  • What the state file is and why it's central to how Terraform works.
  • The everyday workflow: init, plan, apply, destroy.
  • Where Terraform shines and where it doesn't.

Skill gained: you can read a basic Terraform file, explain what it would create, and describe the plan/apply loop — enough to follow real Terraform code and start small experiments.

The lesson

Note: Terraform is not deployed in the lab yet. This lesson teaches it conceptually with small standalone examples you can read and try on your own machine.

1. What Terraform does

Terraform, by HashiCorp, is the most popular provisioning tool. Provisioning means creating the raw infrastructure: a virtual machine, a network, a firewall rule, a DNS record, a cloud storage bucket. You declare what should exist, and Terraform creates, changes, or deletes real resources to match.

It is declarative (you describe the end state) and tracks state (it remembers what it built). Those two facts explain almost everything about how it behaves.

2. Providers: Terraform's plugins

Terraform itself knows nothing about any specific platform. It learns through providers — plugins that translate your declarations into API calls. There's a provider for AWS, one for Azure, one for Google Cloud, one for Proxmox, one for DNS, and hundreds more.

terraform {
  required_providers {
    aws = {
      source  = "hashicorp/aws"
      version = "~> 5.0"
    }
  }
}

provider "aws" {
  region = "eu-central-1"
}

You declare which providers you need; terraform init downloads them. The ~> 5.0 is a version constraint meaning "5.x, but not 6.0" — pinning versions keeps runs reproducible.

3. Resources: the things you create

A resource is one piece of infrastructure. You write a resource block with a type, a name, and arguments:

resource "aws_instance" "web" {
  ami           = "ami-0abcd1234"   # which OS image
  instance_type = "t3.micro"        # size of the VM

  tags = {
    Name = "web-server"
    Env  = "lab"
  }
}
  • aws_instance is the type (defined by the AWS provider).
  • web is your name for it (used to reference it elsewhere).
  • The block body declares the desired settings.

Resources can reference each other. Below, a firewall-rule resource points at the instance's ID — Terraform reads this and figures out it must create the instance first:

resource "aws_eip" "web_ip" {
  instance = aws_instance.web.id
}

That aws_instance.web.id reference builds a dependency graph so Terraform creates things in the right order automatically.

4. HCL: the language

Terraform files use HCL (HashiCorp Configuration Language), saved as .tf files. It's designed to be human-readable: blocks, key = value pairs, and a few helpers like variables and outputs.

variable "instance_size" {
  type    = string
  default = "t3.micro"
}

resource "aws_instance" "web" {
  ami           = "ami-0abcd1234"
  instance_type = var.instance_size
}

output "public_ip" {
  value = aws_instance.web.public_ip
}
  • variables let you parameterize (no hard-coded values everywhere).
  • outputs surface useful values after a run (e.g. the new server's IP — here it would print something like 203.0.113.10).

5. State: Terraform's memory

After creating resources, Terraform records them in a state file (terraform.tfstate). State maps your code (aws_instance.web) to the real resource ID in the cloud. On the next run, Terraform:

   YOUR CODE  ───┐
                 ├──>  Terraform compares  ──> PLAN (the diff)
   STATE FILE ───┤
                 │
   REAL WORLD ───┘
  1. Reads your .tf files (desired state).
  2. Reads the state file (what it built last time).
  3. Checks the real world (what's actually there).
  4. Computes the difference and proposes changes.

This is why state matters: lose or corrupt it and Terraform forgets what it owns. In teams, state lives in shared remote backends (e.g. an S3 bucket or Terraform Cloud) with locking, so two people don't run at once. Never commit a state file to Git — it can contain secrets.

6. The core workflow

Four commands cover daily use:

terraform init     # download providers, set up the working dir (run once / when providers change)
terraform plan     # preview: show exactly what will be created/changed/destroyed
terraform apply    # do it (after showing the plan and asking yes)
terraform destroy  # tear it all down

A typical plan output reads like a diff:

  + create        (a new resource)
  ~ update         (change in place)
  - destroy        (remove)

Plan: 1 to add, 0 to change, 0 to destroy.

Always read the plan before you apply. The plan is your safety net — it tells you precisely what's about to change before anything real happens. If a plan says "destroy" something you care about, stop.

7. What Terraform is good at (and not)

Great at:

  • Creating and managing the lifecycle of infrastructure across clouds.
  • Multi-resource setups with dependencies (network + VMs + DNS together).
  • Keeping a clear, reviewable record of what infrastructure exists.
  • Tearing environments up and down repeatably (great for short-lived test envs).

Not its job:

  • Installing and configuring software inside a machine over time — that's configuration management (Ansible, Chapter 3). Terraform can kick off a first-boot script, but it isn't designed to manage a server's ongoing internal state.
  • One-off imperative tasks. Terraform wants to own the lifecycle of what it manages.

A common pattern: Terraform builds the VM, passes it a cloud-init snippet for first boot, and Ansible configures the software. Each tool does the job it's best at. Chapter 5 ties this together.

Dig deeper

Search terms

  • terraform getting started tutorial
  • terraform plan apply destroy explained
  • what is terraform state file
  • terraform providers and resources HCL
  • terraform remote backend why

Check yourself

  1. What job does Terraform do, and what does "provisioning" mean?
  2. What is a provider, and why does Terraform need one?
  3. Explain what the state file is and one reason losing it is bad.
  4. What does terraform plan show, and why should you read it before apply?
  5. Name one task Terraform is not the right tool for, and say which tool fits instead.