Terraform: A Complete Guide

What is Terraform?

Terraform is an open-source tool used to manage and automate infrastructure. It helps developers define and provision cloud and on-premises resources using a simple, human-readable configuration language. Instead of manually creating servers, databases, and networks, Terraform allows you to write code that describes what your infrastructure should look like, and it takes care of creating, updating, and deleting resources accordingly.

For more details, visit the official Terraform documentation.

Why Do We Need Terraform?

  1. Infrastructure as Code (IaC) – Terraform enables managing infrastructure using code, making it repeatable and version-controlled.
  2. Automation – Reduces manual intervention and human errors.
  3. Consistency – Ensures the same configuration is applied everywhere.
  4. Multi-Cloud Support – Works with AWS, Azure, Google Cloud, and many other providers.
  5. Scalability – Easily scale infrastructure up or down as needed.
  6. Dependency Management – Automatically manages dependencies between resources.

What is Provisioning?

Provisioning refers to the process of setting up IT infrastructure, such as servers, databases, and networks, automatically rather than manually. Terraform allows infrastructure provisioning using declarative code, ensuring reproducibility and reducing errors.

Challenges in IT Infrastructure Management

  1. Manual Errors – Managing resources manually can lead to mistakes.
  2. Scaling Issues – Difficult to scale manually.
  3. Inconsistency – Different environments may have different configurations.
  4. Lack of Documentation – Manual setups often lack proper documentation.
  5. Long Deployment Times – Manual provisioning can take a lot of time.

Terraform vs Ansible

FeatureTerraformAnsible
PurposeInfrastructure provisioningConfiguration management
State ManagementMaintains stateNo state management
Declarative/ImperativeDeclarativeImperative and declarative
Best Use CaseCreating cloud resourcesConfiguring and managing software
Multi-cloud SupportYesYes
Agent-basedNoNo

Terraform File Extension

Terraform configuration files use the .tf extension.

Which Language Does Terraform Use?

Terraform uses HCL (HashiCorp Configuration Language), which is a declarative language designed for defining infrastructure in a human-readable format.

What Can We Provision with Terraform? (Examples)

  1. Cloud Resources – AWS EC2, Azure Virtual Machines, Google Compute Engine.
  2. Networking – Load balancers, DNS records, VPCs, subnets.
  3. Databases – PostgreSQL, MySQL, MongoDB.
  4. Storage – S3 buckets, Azure Blob Storage, Google Cloud Storage.
  5. Containers – Kubernetes, Docker, ECS, EKS, AKS.
  6. Monitoring – CloudWatch, Prometheus.

HCL (HashiCorp Configuration Language) – All Details

Syntax Block

HCL uses blocks to define resources, providers, and configurations. Each block consists of:

  • Type (e.g., resource, provider)
  • Label(s) (e.g., name, type identifier)
  • Body (contains attributes and values)

Example:

resource "aws_instance" "web" {
  ami           = "ami-123456"
  instance_type = "t2.micro"
}

Arguments

Arguments are key-value pairs inside blocks. Example:

variable "region" {
  default = "us-east-1"
}

HCL Features Table

FeatureDescriptionExample
ProvidersDefines cloud/platform-specific APIsprovider "aws" { region = "us-east-1" }
ResourcesDefines infrastructure componentsresource "aws_instance" "example" { ami = "ami-123456" instance_type = "t2.micro" }
VariablesStores values to make code reusablevariable "region" { default = "us-east-1" }
OutputsDisplays values after executionoutput "instance_ip" { value = aws_instance.example.public_ip }
ModulesReusable components to structure infrastructuremodule "network" { source = "./modules/network" }
Data SourcesFetches existing cloud resourcesdata "aws_ami" "latest" { most_recent = true owners = ["amazon"] }

Different Structures to Manage a Terraform Repository

  1. Flat Structure – This structure keeps all Terraform files in a single directory without any modularization. It is suitable for small projects but can become difficult to manage as infrastructure grows.

Example:

project/
├── main.tf
├── variables.tf
├── outputs.tf
├── terraform.tfvars

In this approach, all Terraform configurations are in one directory, making it easy to start with but less scalable for large environments.

  1. Modular Structure – This approach organizes Terraform configurations into reusable modules, making it easier to manage and scale infrastructure. Each module contains its own configuration files for specific components, such as networking or compute resources. This structure promotes code reusability and maintainability, particularly for large-scale projects.

Example:

project/
├── modules/
│   ├── network/
│   │   ├── main.tf
│   │   ├── variables.tf
│   │   ├── outputs.tf
│   ├── compute/
│   │   ├── main.tf
│   │   ├── variables.tf
│   │   ├── outputs.tf
├── main.tf

In this approach, infrastructure is broken into smaller, manageable components, improving maintainability and scalability.

  1. Environment-based Structure – This structure separates Terraform configurations into different directories for each environment, such as development (dev), staging (staging), and production (prod). This approach helps isolate infrastructure changes across different environments, reducing the risk of accidental modifications to production.

Each environment has its own Terraform configuration files to manage specific resources and settings. This method is particularly useful for teams handling multiple environments with different configurations.

Example:

environments/
├── dev/
│   ├── main.tf
│   ├── variables.tf
├── staging/
│   ├── main.tf
│   ├── variables.tf
├── prod/
│   ├── main.tf
│   ├── variables.tf

Each directory contains its respective configuration files, ensuring that changes in one environment do not impact others.

  1. Workspace-based Structure – Terraform workspaces allow managing multiple environments within the same configuration. Instead of maintaining separate directories for different environments, workspaces enable switching between different states dynamically. This is useful when handling development, staging, and production setups without duplicating configuration files.

Example:

terraform {
  backend "s3" {
    bucket = "my-terraform-state"
    key    = "workspace/terraform.tfstate"
    region = "us-east-1"
  }
}

To create and switch between workspaces, use the following commands:

terraform workspace new dev
terraform workspace select dev
terraform workspace list

terraform {
backend "s3" {
bucket = "my-terraform-state"
key = "workspace/terraform.tfstate"
region = "us-east-1"
}
}

What is State in Terraform?

Terraform keeps track of managed infrastructure using a state file (terraform.tfstate). It helps Terraform understand what resources exist and what needs updating.

How Different Developers Can Work on One Terraform Repository

  1. Remote State Storage – Use AWS S3, Azure Blob, or Terraform Cloud for shared state.
  2. Locking Mechanism – Use state locking to prevent conflicts.
  3. Branch-based Development – Work on separate branches and merge changes.
  4. Workspaces – Separate infrastructure environments within the same configuration.

How to Handle Sensitive Data in Terraform

  1. Environment Variables
    variable "db_password" {} export TF_VAR_db_password="supersecurepassword"
  2. Terraform Vault Integration
    provider "vault" {}
  3. AWS Secrets Manager
    data "aws_secretsmanager_secret" "example" { name = "my-secret" }

Nginx Docker Container with Terraform

This project demonstrates how to deploy an Nginx container using Terraform step by step.

To begin, create a new directory and navigate into it:

mkdir terraform-nginx && cd terraform-nginx

Create a main.tf file with the following content:

If the Docker provider is not available by default, initialize Terraform to install it:

terraform init

Ensure that Docker is installed on your machine. If not, install it from Docker’s official website.

provider "docker" {}

resource "docker_image" "nginx" {
  name         = "nginx:latest"
  keep_locally = false
}

resource "docker_container" "nginx" {
  image = docker_image.nginx.latest
  name  = "nginx_container"
  ports {
    internal = 80
    external = 8080
  }
}

Initialize Terraform:

terraform init

Preview the planned changes:

terraform plan

Apply the configuration to create the container:

terraform apply -auto-approve

Verify the running container:

docker ps

Expected output:

CONTAINER ID   IMAGE         COMMAND                  PORTS                    NAMES
abc12345       nginx:latest  "nginx -g 'daemon off;"  0.0.0.0:8080->80/tcp     nginx_container

Test the Nginx server by opening a browser and navigating to http://localhost:8080. You should see the default Nginx welcome page.

If you need to remove the resources, destroy the container:

Local File Creation Project

This project demonstrates how to create a local file using Terraform.

Terraform Configuration:

resource "local_file" "example" {
  content  = "Hello, Terraform!"
  filename = "hello.txt"
}

To execute the project, first initialize the directory by running the following command:

terraform init

Next, plan the changes to verify the execution plan:

terraform plan

Apply the configuration to create the file:

terraform apply

Once applied, check if the file hello.txt has been created in your working directory.

If you no longer need the file, clean up by running:

terraform destroy

More Projects Coming Soon!

Scroll to Top