Terraform is an open-source Infrastructure as Code (IaC) tool created by HashiCorp. It lets you describe your entire cloud environment, servers, networks, databases, DNS records, load balancers, in plain text configuration files, and then creates, updates, or destroys that infrastructure automatically.
Instead of clicking through the AWS Console to launch an EC2 instance, you write a few lines of configuration like this:
resource "aws_instance" "web" {
ami = "ami-0c55b159cbfafe1f0"
instance_type = "t3.micro"
}Run one command (terraform apply) and the server exists. Run another (terraform destroy) and it is gone. No clicks, no forgotten settings, no "I wonder what I configured last time."
Infrastructure as Code (IaC) means treating your infrastructure the same way developers treat application code: write it in files, store it in Git, review it in pull requests, and deploy it automatically.
Before IaC, teams managed infrastructure manually. A senior engineer would click through the cloud console, configure something, and the knowledge of how it was configured lived only in their head, or a messy wiki page nobody kept up to date.
This caused predictable problems:
| Benefit | What it means in practice |
|---|---|
| Repeatability | Spin up identical dev, staging and prod environments from the same code |
| Version control | Every infrastructure change is a Git commit with an author, timestamp and message |
| Code review | A teammate reviews your terraform plan output before anything changes in production |
| Disaster recovery | If a region goes down, re-create the entire environment in another region with one command |
| Documentation | The configuration files are the documentation, always accurate, never out of date |
| Speed | Build a 20-resource environment in 2 minutes instead of 2 days |
Terraform follows a simple mental model:
.tf files using HCLThe state file is critical. It is what allows Terraform to say "this resource already exists, I just need to update its tags" rather than creating a duplicate.
A provider is a plugin that lets Terraform communicate with a specific platform. When you declare:
provider "aws" {
region = "us-east-1"
}Terraform downloads the AWS provider, which contains code for every AWS resource type (aws_instance, aws_s3_bucket, aws_vpc, etc.).
There are providers for:
This is what makes Terraform genuinely cloud-agnostic, you learn one workflow and apply it to any platform.
A resource is anything Terraform manages, a server, a bucket, a DNS record, a Kubernetes deployment. Every resource block follows the same pattern:
resource "<provider>_<type>" "<local_name>" {
argument = "value"
}For example:
resource "aws_s3_bucket" "my_bucket" {
bucket = "devopslesson-demo-2026"
}
resource "aws_vpc" "main" {
cidr_block = "10.0.0.0/16"
}The local name (my_bucket, main) is only used inside your Terraform code to reference the resource, it is not the name of the resource in AWS.
Sometimes you need to look up existing infrastructure rather than create new things. That is what data sources are for:
data "aws_ami" "ubuntu" {
most_recent = true
owners = ["099720109477"] # Canonical
filter {
name = "name"
values = ["ubuntu/images/hvm-ssd/ubuntu-*-22.04-amd64-server-*"]
}
}This finds the latest Ubuntu 22.04 AMI without hardcoding an AMI ID that will eventually expire.
Variables make your configuration flexible and reusable. Outputs expose values, like an IP address or a database endpoint, after apply:
variable "instance_type" {
description = "EC2 instance type"
default = "t3.micro"
}
output "server_ip" {
value = aws_instance.web.public_ip
}These are covered in full in the Variables and Outputs tutorial.
It is useful to know where Terraform sits relative to the other common tools.
This is the most common comparison. The key difference is what each tool manages:
Many teams use both: Terraform builds the servers, Ansible configures them. They are complementary, not competing.
CloudFormation is Amazon's native IaC tool. The key differences:
| Feature | Terraform | CloudFormation |
|---|---|---|
| Cloud support | Any provider (AWS, Azure, GCP, â¦) | AWS only |
| Language | HCL (readable, concise) | JSON or YAML (verbose) |
| State management | You control the state file | AWS manages state |
| Error messages | Generally clear | Notoriously confusing |
| Ecosystem | Massive (Terraform Registry) | AWS-only modules |
If you only ever use AWS and your team is deeply embedded in the AWS ecosystem, CloudFormation is a reasonable choice. For everything else, Terraform wins on flexibility.
Pulumi is the most modern alternative. It lets you write infrastructure in TypeScript, Python or Go instead of HCL. The tradeoffs:
For most engineers, Terraform is the right starting point. Learn Terraform first; you can always pick up Pulumi later.
You will go deep on each command in the next tutorials, but here is the overview:
# 1. Download providers and initialise the working directory
terraform init
# 2. Preview what will change, no infrastructure is touched
terraform plan
# 3. Create or update infrastructure
terraform apply
# 4. Tear everything down when you're done
terraform destroyThe plan step is Terraform's superpower. You see exactly what will be created, changed or deleted, with counts and attribute diffs, before you commit. This makes infrastructure changes as reviewable as code changes.
This tutorial series teaches Terraform from zero to production-ready, in order:
init, plan, apply, destroy in depthEach tutorial builds on the last. By the end you will have the skills to provision real cloud infrastructure safely and confidently.
<MCQExercise exercise={{ id: 'tf-intro-q1', title: 'Question 1: What is Terraform?', description: 'Which of the following best describes what Terraform does?', options: [ { id: 'a', text: 'A configuration management tool that installs software on existing servers' }, { id: 'b', text: 'An Infrastructure as Code tool that provisions and manages cloud resources through configuration files' }, { id: 'c', text: 'A container orchestration platform for running Docker workloads at scale' }, { id: 'd', text: 'A CI/CD tool that automates application deployments through pipelines' }, ], correctId: 'b', explanation: 'Terraform is an Infrastructure as Code tool. You describe the infrastructure you want in .tf files and Terraform creates or updates it by calling cloud provider APIs. It provisions infrastructure, servers, networks, databases, rather than configuring software on existing machines (that's Ansible) or orchestrating containers (that's Kubernetes).', wrongExplanations: { a: 'That describes Ansible. Ansible is a configuration management tool. Terraform provisions the infrastructure itself.', c: 'That describes Kubernetes. Terraform can manage Kubernetes clusters, but it is not an orchestration platform.', d: 'That describes tools like GitLab CI or GitHub Actions. Terraform is focused on infrastructure, not application deployment pipelines.', }, }} />
<MCQExercise exercise={{ id: 'tf-intro-q2', title: 'Question 2: The State File', description: 'Why does Terraform maintain a state file?', options: [ { id: 'a', text: 'To store your cloud provider credentials securely' }, { id: 'b', text: 'To cache your .tf files so they run faster on the next apply' }, { id: 'c', text: 'To record what infrastructure Terraform has created so it can calculate changes on the next run' }, { id: 'd', text: 'To store the Terraform binary so you do not need to install it again' }, ], correctId: 'c', explanation: 'The state file is Terraform's record of reality. When you run terraform plan, Terraform reads the state to understand what it already manages, queries the actual infrastructure, and compares both against your .tf files. Without state, Terraform would not know whether to create a new resource or update an existing one.', wrongExplanations: { a: 'Credentials are never stored in the state file. They come from environment variables, AWS profiles, or secrets managers.', b: 'Terraform does not cache .tf files. The state file records the current state of provisioned infrastructure.', d: 'The Terraform binary is installed separately. The state file is a JSON document describing your infrastructure.', }, }} />
<MCQExercise exercise={{ id: 'tf-intro-q3', title: 'Question 3: Terraform vs Ansible', description: 'Your team needs to: (1) create an EC2 instance on AWS, and (2) install Nginx on it. Which tool handles each task?', options: [ { id: 'a', text: 'Terraform handles both tasks' }, { id: 'b', text: 'Ansible handles both tasks' }, { id: 'c', text: 'Terraform creates the EC2 instance; Ansible installs Nginx on it' }, { id: 'd', text: 'Ansible creates the EC2 instance; Terraform installs Nginx on it' }, ], correctId: 'c', explanation: 'Terraform provisions infrastructure, creating the EC2 instance by calling the AWS API. Ansible configures what runs on that infrastructure, SSHing into the server and installing Nginx. These tools are complementary and many production teams use both together.', wrongExplanations: { a: 'While Terraform can run provisioners to run scripts, it is not designed for ongoing configuration management. Ansible is better at that.', b: 'Ansible can launch EC2 instances via its AWS modules, but Terraform is the industry standard for infrastructure provisioning.', d: 'This is reversed. Terraform provisions infrastructure; Ansible configures it.', }, }} />
<MCQExercise exercise={{ id: 'tf-intro-q4', title: 'Question 4: Declarative vs Procedural', description: 'Terraform is described as "declarative". What does this mean?', options: [ { id: 'a', text: 'You write step-by-step instructions telling Terraform exactly how to create each resource' }, { id: 'b', text: 'You describe the desired end state and Terraform figures out the steps to reach it' }, { id: 'c', text: 'Terraform declares variables at the top of every file before using them' }, { id: 'd', text: 'You must declare every resource type in a separate configuration file' }, ], correctId: 'b', explanation: 'Declarative means you describe what you want, not how to achieve it. You write "I want an S3 bucket called my-bucket" and Terraform decides whether to create it, skip it (already exists), or update it. You do not write the API calls yourself. This is the opposite of procedural tools like Bash scripts where you write every step.', wrongExplanations: { a: 'That is procedural programming, writing how to do something step by step. Terraform is declarative: you define the desired end state.', c: 'Variable declaration is a feature of Terraform HCL, but it is not what "declarative" means in this context.', d: 'There is no requirement to separate resource types into different files. Declarative refers to the programming paradigm, not file organisation.', }, }} />
Terraform is a provisioning tool: it creates and destroys infrastructure and tracks what exists in state. Ansible is a configuration management tool: it installs packages and configures software on machines that already exist. Terraform is declarative and works out the changes needed to reach your desired state; Ansible is primarily procedural, running tasks in order. They are complementary rather than competing, and a common pattern is Terraform to build the servers and Ansible to configure what runs on them.
Terraform if you use more than one provider or want the skill to transfer between employers. It works across AWS, Azure, GCP, Kubernetes, Datadog, Cloudflare and hundreds of others with one language and one workflow. CloudFormation is AWS-only but needs no state file of your own, since AWS manages it, and StackSets deploy across an entire AWS Organization with no open-source Terraform equivalent. Many AWS teams run both: CloudFormation or CDK for account baselines, Terraform for application infrastructure.
Terraform moved from the Mozilla Public License to the Business Source License in 2023, which restricts using it to build a competing commercial product but leaves normal infrastructure use unaffected. In response the community forked the last MPL version as OpenTofu, now under the Linux Foundation and largely a drop-in replacement. For most teams either works and the configuration language is the same; the choice comes down to licensing preference and which ecosystem your tooling targets.
Yes, at least the basics of one. Terraform is a way to express infrastructure, not a substitute for understanding it. A aws_vpc resource still requires you to know what a VPC, a subnet and a route table are, and error messages come from the provider rather than from Terraform. Learn the fundamentals of one cloud first, then Terraform becomes a much faster way to work with what you already understand.
State. Terraform records what it created in a state file, and almost every confusing situation. A resource it wants to recreate for no obvious reason, a change made in the console that Terraform undoes, two people applying at once and corrupting the file. Traces back to state. Set up a remote backend with locking before working in a team rather than after, and spend time understanding what state is for early; it pays back more than any other Terraform concept.
Install Terraform on macOS, Linux and Windows with the official package managers, verify the version, switch versions with tfenv and run your first project.
Understand the Terraform init, plan, apply and destroy loop: what each command does, how to read a plan and the mistakes that cause outages.
Learn what terraform init does: download providers, configure the backend, write the lock file, use -upgrade and -reconfigure and run it in CI/CD.