Last updated: April 13, 2025
Table of Contents
1. Introduction: What is Terraform?
Terraform, developed by HashiCorp, is a leading open-source Infrastructure as Code (IaC) tool. It allows you to define, provision, and manage infrastructure resources (like virtual machines, networks, databases, DNS entries) across various cloud providers (AWS, Azure, GCP) and other services using a declarative configuration language.
Instead of manually clicking through web consoles or writing complex scripts, you describe your desired infrastructure in configuration files. Terraform then figures out how to create, update, or delete resources to match your definition, making infrastructure management more predictable, repeatable, and versionable.
This guide provides a hands-on introduction to get you started with Terraform basics.
2. Installation
Terraform is distributed as a single binary. Download the appropriate package for your operating system from the official Terraform downloads page.
- Download the ZIP archive.
- Unzip the package. You'll find a single binary file named
terraform
(orterraform.exe
on Windows). - Move the binary to a directory included in your system's PATH environment variable (e.g.,
/usr/local/bin
on Linux/macOS, or a dedicated folder added to PATH on Windows).
Verify the installation by opening a new terminal session and running:
terraform --version
Alternatively, use package managers like Homebrew (macOS) or Chocolatey (Windows):
# macOS (Homebrew)
brew tap hashicorp/tap
brew install hashicorp/tap/terraform
# Windows (Chocolatey)
choco install terraform
3. Core Terraform Concepts
3.1 HCL (HashiCorp Configuration Language)
Terraform configurations are written in HCL, a declarative language designed to be human-readable and machine-friendly. Files typically have a .tf
extension.
3.2 Providers
Providers are plugins that allow Terraform to interact with specific APIs (e.g., AWS, Azure, GCP, Docker, GitHub). You declare which providers your configuration needs, and Terraform downloads them automatically during initialization.
3.3 Resources
Resources are the fundamental building blocks of your infrastructure (e.g., an AWS EC2 instance, a GCP VPC network, an Azure storage account). You define resources in your configuration files, specifying their type and desired attributes.
3.4 State
Terraform maintains a state file (usually terraform.tfstate
) to keep track of the real-world resources it manages, their configuration, and their dependencies. This state file is crucial for Terraform to understand what infrastructure currently exists and how to plan updates.
Important: For team collaboration, the state file should be stored remotely and securely (e.g., in an AWS S3 bucket, Azure Blob Storage, or Terraform Cloud/Enterprise) with locking enabled to prevent conflicts.
3.5 Core Workflow (init, plan, apply)
The basic Terraform workflow involves three main commands:
terraform init
: Initializes the working directory, downloads provider plugins, and sets up the backend for state storage. Run this once per project initially and whenever providers change.terraform plan
: Creates an execution plan. Terraform compares your configuration files with the current state file and the actual infrastructure to determine what changes (create, update, delete) are needed. It shows you this plan for review before making any changes.terraform apply
: Executes the actions proposed in the plan to reach the desired state described in your configuration.
4. Your First Terraform Project (AWS Example)
Let's create a simple AWS EC2 instance.
Prerequisites:
- Terraform installed.
- An AWS account.
- AWS credentials configured for Terraform to use (e.g., via environment variables
AWS_ACCESS_KEY_ID
andAWS_SECRET_ACCESS_KEY
, or an IAM role if running on EC2). See AWS Provider Authentication for details.
4.1 Project Setup
Create a new directory for your project:
mkdir terraform-learn
cd terraform-learn
4.2 Configure the Provider
Create a file named main.tf
(or any name ending in .tf
) and configure the AWS provider:
# main.tf
terraform {
required_providers {
aws = {
source = "hashicorp/aws"
version = "~> 5.0" # Specify desired provider version
}
}
}
# Configure the AWS Provider
provider "aws" {
region = "us-west-2" # Choose your desired AWS region
}
4.3 Define a Resource
In the same main.tf
file, define an AWS EC2 instance resource:
# Define an AWS EC2 instance resource
resource "aws_instance" "example_server" {
# ami = "ami-08d70e59c07c61a3a" # Example: Ubuntu 22.04 LTS for us-west-2 (Find current AMI for your region)
ami = data.aws_ami.ubuntu.id # Use data source below for dynamic AMI lookup
instance_type = "t2.micro" # Instance size
tags = {
Name = "HelloWorldServer"
}
}
# Data source to find the latest Ubuntu 22.04 AMI in the selected region
data "aws_ami" "ubuntu" {
most_recent = true
filter {
name = "name"
values = ["ubuntu/images/hvm-ssd/ubuntu-jammy-22.04-amd64-server-*"]
}
filter {
name = "virtualization-type"
values = ["hvm"]
}
owners = ["099720109477"] # Canonical's AWS account ID for Ubuntu images
}
resource "aws_instance" "example_server"
: Declares a resource of typeaws_instance
with the local nameexample_server
.ami
: Specifies the Amazon Machine Image ID (operating system). Using a data source likedata.aws_ami.ubuntu.id
is recommended to find the latest AMI dynamically.instance_type
: Specifies the size of the EC2 instance.tags
: Assigns metadata tags to the resource.data "aws_ami" "ubuntu" { ... }
: A data source block that looks up information (in this case, an AMI ID) from AWS without creating a resource.
Note: Always check the AWS documentation or console for the latest appropriate AMI ID for your desired OS and region, or use a data source as shown.
4.4 Initialize the Project (terraform init
)
Run this command in your project directory:
terraform init
Terraform downloads the AWS provider plugin specified in your configuration.
4.5 Plan the Changes (terraform plan
)
See what Terraform intends to do:
terraform plan
Terraform will analyze your configuration and show output indicating it plans to create one resource (the aws_instance
). Review the plan carefully.
4.6 Apply the Changes (terraform apply
)
Execute the plan to create the EC2 instance:
terraform apply
Terraform will show the plan again and ask for confirmation. Type yes
and press Enter.
Terraform will now interact with the AWS API to create the instance. This might take a minute or two.
4.7 Inspect State (terraform show
)
After applying, you can see the resources Terraform is managing:
terraform show
This displays information about the created instance from the state file.
4.8 Destroy Resources (terraform destroy
)
When you're finished with the resources, you can destroy them:
terraform destroy
Terraform will show a plan of resources to be destroyed and ask for confirmation. Type yes
to proceed.
5. Using Variables and Outputs
5.1 Input Variables
Avoid hardcoding values like regions or instance types. Use input variables.
Create a file variables.tf
:
# variables.tf
variable "aws_region" {
description = "The AWS region to deploy resources in."
type = string
default = "us-west-2"
}
variable "instance_type" {
description = "EC2 instance type."
type = string
default = "t2.micro"
}
Modify main.tf
to use these variables:
# main.tf (modified)
provider "aws" {
region = var.aws_region # Use variable
}
resource "aws_instance" "example_server" {
ami = data.aws_ami.ubuntu.id
instance_type = var.instance_type # Use variable
tags = {
Name = "HelloWorldServer"
}
}
# ... (data source remains the same) ...
You can override default variable values using a terraform.tfvars
file or via the command line (-var="aws_region=eu-central-1"
).
5.2 Output Values
Define output values to display useful information after applying changes, like an instance's IP address.
Create a file outputs.tf
:
# outputs.tf
output "instance_public_ip" {
description = "Public IP address of the EC2 instance."
value = aws_instance.example_server.public_ip
}
output "instance_id" {
description = "ID of the EC2 instance."
value = aws_instance.example_server.id
}
After running terraform apply
, these values will be displayed.
6. Next Steps
This guide covers the absolute basics. Explore further:
- More Resource Types: Define networks (VPC), security groups, databases (RDS), load balancers, etc.
- Modules: Organize and reuse Terraform code.
- Remote State: Store state files securely for team collaboration.
- Provisioners: Execute scripts on resources after creation (use sparingly; prefer configuration management tools or immutable images).
- Data Sources: Query existing infrastructure or external data.
- Functions and Expressions: Use built-in functions for dynamic configurations.
7. Conclusion
Terraform provides a powerful, declarative way to manage infrastructure as code. By defining resources in HCL, using providers to interact with APIs, and following the init
, plan
, apply
workflow, you can automate infrastructure provisioning, improve consistency, and enable version control for your infrastructure. This basic introduction should give you the foundation to start exploring Terraform for managing your own cloud resources.
8. Related Articles
- Infrastructure as Code (IaC) Explained
- Docker Commands Guide
- Choosing a Cloud Provider (AWS vs GCP vs Azure)
- Getting Started with Kubernetes