Part 1: Getting Started with Terraform and AWS

Cover Image for Part 1: Getting Started with Terraform and AWS
DevOps5 min read

Introduction

Terraform is an Infrastructure as Code (IaC) tool that allows you to define and provision cloud infrastructure using declarative configuration files. Instead of clicking through AWS console or running CLI commands manually, you write code that describes your desired infrastructure state, and Terraform makes it happen.

Why Use Terraform?

1. Infrastructure as Code Benefits

  • Version Control: Track changes to your infrastructure over time
  • Reproducibility: Deploy identical environments consistently
  • Automation: Integrate with CI/CD pipelines
  • Documentation: Your infrastructure is self-documenting

2. Terraform Advantages

  • Multi-cloud support: Works with AWS, Azure, GCP, and 100+ providers
  • Declarative syntax: Describe what you want, not how to get there
  • State management: Tracks resource dependencies and current state
  • Plan before apply: Preview changes before executing them

Setting Up Your Development Environment

1. Install Terraform

macOS (using Homebrew):

brew tap hashicorp/tap
brew install hashicorp/tap/terraform

Windows (using Chocolatey):

choco install terraform

Linux (Ubuntu/Debian):

wget -O- https://apt.releases.hashicorp.com/gpg | sudo gpg --dearmor -o /usr/share/keyrings/hashicorp-archive-keyring.gpg
echo "deb [signed-by=/usr/share/keyrings/hashicorp-archive-keyring.gpg] https://apt.releases.hashicorp.com $(lsb_release -cs) main" | sudo tee /etc/apt/sources.list.d/hashicorp.list
sudo apt update && sudo apt install terraform

Verify Installation:

terraform --version

2. Install AWS CLI

All platforms:

# Download from AWS website or use package managers
pip install awscli

Verify Installation:

aws --version

3. Configure AWS Credentials

You have several options for AWS authentication:

Option 1: AWS CLI Configuration

aws configure

Option 2: Environment Variables

export AWS_ACCESS_KEY_ID="your-access-key"
export AWS_SECRET_ACCESS_KEY="your-secret-key"
export AWS_DEFAULT_REGION="us-east-1"

Option 3: IAM Roles (Recommended for production)

  • Use IAM roles when running on EC2 instances
  • Use IAM roles for cross-account access

Your First Terraform Configuration

Let's create a simple S3 bucket to understand the basics.

Step 1: Create Project Directory

mkdir my-first-terraform
cd my-first-terraform

Step 2: Create main.tf

# main.tf
terraform {
  required_version = ">= 1.0"
  
  required_providers {
    aws = {
      source  = "hashicorp/aws"
      version = "~> 5.0"
    }
  }
}

# Configure AWS Provider
provider "aws" {
  region = "us-east-1"
}

# Create an S3 bucket
resource "aws_s3_bucket" "my_first_bucket" {
  bucket = "my-terraform-bucket-${random_string.bucket_suffix.result}"
  
  tags = {
    Name        = "My First Bucket"
    Environment = "Learning"
    ManagedBy   = "Terraform"
  }
}

# Generate random string for unique bucket name
resource "random_string" "bucket_suffix" {
  length  = 8
  special = false
  upper   = false
}

# Configure bucket versioning
resource "aws_s3_bucket_versioning" "my_first_bucket_versioning" {
  bucket = aws_s3_bucket.my_first_bucket.id
  
  versioning_configuration {
    status = "Enabled"
  }
}

# Configure server-side encryption
resource "aws_s3_bucket_server_side_encryption_configuration" "my_first_bucket_encryption" {
  bucket = aws_s3_bucket.my_first_bucket.id

  rule {
    apply_server_side_encryption_by_default {
      sse_algorithm = "AES256"
    }
  }
}

Step 3: Understanding the Configuration

Terraform Block:

  • Specifies minimum Terraform version
  • Declares required providers and their versions

Provider Block:

  • Configures the AWS provider
  • Sets the default region

Resource Blocks:

  • Define infrastructure components
  • Follow the syntax: resource "resource_type" "local_name"

Dependencies:

  • Terraform automatically detects dependencies between resources
  • The aws_s3_bucket_versioning depends on the S3 bucket

Essential Terraform Commands

1. Initialize Terraform

terraform init

This command:

  • Downloads required provider plugins
  • Sets up the backend for state storage
  • Prepares your working directory

2. Validate Configuration

terraform validate

Checks your configuration for:

  • Syntax errors
  • Missing required arguments
  • Invalid resource references

3. Format Configuration

terraform fmt

Automatically formats your Terraform files for consistency.

4. Plan Changes

terraform plan

Creates an execution plan showing:

  • Resources to be created, modified, or destroyed
  • Order of operations
  • No actual changes are made

5. Apply Changes

terraform apply

Executes the planned changes:

  • Shows the plan again
  • Asks for confirmation (type "yes")
  • Creates/modifies/destroys resources as needed

6. Show Current State

terraform show

Displays the current state of your infrastructure.

7. List Resources

terraform state list

Shows all resources in your state file.

8. Destroy Infrastructure

terraform destroy

Removes all resources defined in your configuration:

  • Shows destruction plan
  • Asks for confirmation
  • Deletes resources in correct order

Understanding Terraform State

Terraform stores information about your infrastructure in a state file (terraform.tfstate).

State File Contains:

  • Current resource configurations
  • Resource dependencies
  • Metadata about resources

Important State Concepts:

  • Never edit state files manually
  • Keep state files secure (they may contain sensitive data)
  • Use remote state for team collaboration
  • Lock state to prevent concurrent modifications

Local vs Remote State

Local State (default):

terraform.tfstate (stored locally)

Remote State (recommended):

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

Best Practices for Beginners

1. Start Small

  • Begin with simple resources
  • Add complexity gradually
  • Test each change

2. Use Version Control

git init
git add .
git commit -m "Initial Terraform configuration"

3. Always Plan Before Apply

terraform plan -out=tfplan
terraform apply tfplan

4. Use Meaningful Names

# Good
resource "aws_s3_bucket" "user_data_backup" {
  bucket = "company-user-data-backup"
}

# Less clear
resource "aws_s3_bucket" "bucket1" {
  bucket = "mybucket123"
}

5. Add Comments and Tags

# S3 bucket for storing application logs
resource "aws_s3_bucket" "app_logs" {
  bucket = "myapp-logs-${var.environment}"
  
  tags = {
    Name        = "Application Logs"
    Environment = var.environment
    Owner       = "DevOps Team"
    Purpose     = "Log Storage"
  }
}

Common Beginner Mistakes

1. Hardcoding Values

# Bad
resource "aws_instance" "web" {
  ami           = "ami-0abcdef123456789"  # Region-specific
  instance_type = "t2.micro"
}

# Better
data "aws_ami" "amazon_linux" {
  most_recent = true
  owners      = ["amazon"]
  
  filter {
    name   = "name"
    values = ["amzn2-ami-hvm-*-x86_64-gp2"]
  }
}

resource "aws_instance" "web" {
  ami           = data.aws_ami.amazon_linux.id
  instance_type = var.instance_type
}

2. Not Using Variables

# variables.tf
variable "environment" {
  description = "Environment name"
  type        = string
  default     = "dev"
}

variable "region" {
  description = "AWS region"
  type        = string
  default     = "us-east-1"
}

3. Ignoring State Management

  • Always backup your state file
  • Use remote state for production
  • Never delete state files manually

Next Steps

In Part 1, you've learned:

  • ✅ What Terraform is and why to use it
  • ✅ How to install and configure your environment
  • ✅ Basic Terraform syntax and concepts
  • ✅ Essential commands and workflow
  • ✅ State management fundamentals

Try This Exercise:

  1. Create the S3 bucket configuration from this guide
  2. Run terraform init, terraform plan, and terraform apply
  3. Check the AWS console to verify your bucket was created
  4. Modify the bucket tags and run terraform plan to see the differences
  5. Clean up by running terraform destroy

In Part 2, we'll dive deeper into AWS-specific resources and build a more complex infrastructure including VPC, subnets, and EC2 instances.


Key Takeaways:

  • Terraform uses declarative syntax to define infrastructure
  • Always plan before applying changes
  • State management is crucial for Terraform operations
  • Start simple and build complexity gradually

Next Part 2: Core AWS Resources and Basic Architecture