Step-by-Step Guide: Configuring Terraform for AWS

Step-by-Step Guide: Configuring Terraform for AWS

Terraform has become the go-to tool for infrastructure as code, allowing teams to define, provision, and manage cloud resources efficiently. In this tutorial, we’ll walk through configuring Terraform for AWS, covering workspaces, remote backends, modules, variables with validations, and .tfvars management.


Prerequisites

Before starting, ensure you have:

  • Terraform installed
  • An AWS account with IAM credentials configured
  • AWS CLI installed and configured

1. Setting Up Terraform Workspaces

Terraform workspaces allow you to manage multiple environments (e.g., dev, staging, prod) from the same configuration.

# Initialize Terraform
terraform init

# Create a new workspace for dev
terraform workspace new dev

# Switch between workspaces
terraform workspace select dev

# List all workspaces
terraform workspace list

Each workspace maintains its own state file, enabling isolated environments.


2. Configuring a Remote Backend with S3

Storing Terraform state in an S3 bucket with optional DynamoDB for state locking is recommended for team collaboration.

Example backend.tf:

terraform {
  backend "s3" {
    bucket         = "my-terraform-states"
    key            = "project/terraform.tfstate"
    region         = "us-east-1"
    dynamodb_table = "terraform-lock"
    encrypt        = true
  }
}
  • bucket: The S3 bucket to store state files
  • key: The path within the bucket
  • dynamodb_table: Optional, for state locking to prevent conflicts
  • encrypt: Ensure state files are encrypted

After defining the backend:

terraform init

Terraform will automatically migrate your local state to the remote backend.


3. Using Terraform Modules

Modules allow you to encapsulate and reuse configurations.

Example: Creating an S3 Module

modules/s3/main.tf:

resource "aws_s3_bucket" "this" {
  bucket = var.bucket_name
  acl    = var.acl
}

output "bucket_id" {
  value = aws_s3_bucket.this.id
}

modules/s3/variables.tf:

variable "bucket_name" {
  type        = string
  description = "Name of the S3 bucket"
}

variable "acl" {
  type        = string
  description = "Access control list"
  default     = "private"
}

Use the module in your main configuration:

module "my_s3_bucket" {
  source      = "./modules/s3"
  bucket_name = "my-app-bucket"
}

4. Defining Variables and Validations

Terraform variables improve configuration flexibility and safety.

Example variables.tf:

variable "environment" {
  type        = string
  description = "Deployment environment"
  validation {
    condition     = contains(["dev", "staging", "prod"], var.environment)
    error_message = "Environment must be one of dev, staging, or prod"
  }
}

variable "instance_count" {
  type        = number
  description = "Number of EC2 instances"
  default     = 1
  validation {
    condition     = var.instance_count > 0
    error_message = "Instance count must be greater than 0"
  }
}

This ensures that incorrect values are caught early.


5. Managing .tfvars Files

Terraform variables can be injected via .tfvars files or environment variables.

Example dev.auto.tfvars:

environment    = "dev"
instance_count = 2
  • .auto.tfvars files are automatically loaded by Terraform.
  • Other .tfvars files can be passed explicitly:
terraform plan -var-file="staging.tfvars"

You can also inject variables via environment variables:

export TF_VAR_environment=prod
export TF_VAR_instance_count=3
terraform apply

This flexibility allows secure and environment-specific configuration without changing the main Terraform code.


Conclusion

By combining workspaces, remote S3 backends, reusable modules, variables with validations, and flexible .tfvars injection, you can build a robust and maintainable Terraform setup for AWS. These practices ensure:

  • Environment isolation
  • Team collaboration with state locking
  • Reusable infrastructure components
  • Safe and predictable deployments

Terraform becomes a powerful tool when these patterns are implemented correctly.

Read more