← All posts

Mar 1, 2025

How to Build a Terraform AWS Infrastructure Blueprint

A step-by-step guide to provisioning a containerized AWS backend service using reusable Terraform modules.

TerraformAWSInfrastructureDevOps

In this guide, we will walk through how to build a production-style Terraform AWS Infrastructure Blueprint. This blueprint provisions all the AWS resources needed to run a containerized backend service, including a VPC, security groups, ECS cluster, ECR repository, Application Load Balancer, IAM roles, and CloudWatch logs.

The Problem: Configuration Drift and Manual Setup

Every time a new environment is needed, creating AWS resources by hand through the console leads to several issues:

  • Steps are easily forgotten.
  • Configurations drift between development, staging, and production environments.
  • There is no version-controlled record of what was built or why.

The solution is Infrastructure as Code (IaC). By defining all infrastructure in Terraform, any environment can be created or destroyed with a single command, keeping configurations consistent and tracked in git.

Architecture & Layout

Here is the directory structure for our Terraform blueprint:

terraform/
├── modules/
│   ├── vpc/          # VPC, subnets, internet gateway, route tables
│   ├── security/     # Security groups for ALB and ECS tasks
│   ├── ecr/          # ECR repository
│   ├── ecs/          # ECS cluster, task definition, service
│   ├── alb/          # Application Load Balancer, target group, listener
│   ├── iam/          # ECS task execution role and policies
│   └── cloudwatch/   # Log group and metric alarms
├── environments/
│   ├── dev/          # dev.tfvars + backend config
│   └── prod/         # prod.tfvars + backend config
├── main.tf
├── variables.tf
└── outputs.tf

Tech Stack Overview

  • IaC: Terraform (HCL)
  • Networking: AWS VPC, public and private subnets, NAT gateway, internet gateway
  • Compute: Amazon ECS (Fargate), task definitions
  • Registry: Amazon ECR
  • Load Balancing: Application Load Balancer, target group, HTTPS listener
  • Security: IAM roles and policies, security groups
  • Observability: CloudWatch log groups, metric alarms
  • State: S3 remote backend with DynamoDB state locking

Step-by-Step Implementation

1. Networking (VPC Module)

We start by building a secure networking foundation. The VPC module sets up:

  • Public subnets for the Application Load Balancer (ALB) to handle incoming public requests.
  • Private subnets for the ECS Fargate tasks to block direct access from the public internet.
  • Internet Gateways and Route Tables to route public traffic.

2. Networking Security (Security Groups)

  • The ALB security group allows inbound 80 and 443 traffic from the internet.
  • The ECS tasks security group strictly allows traffic only from the ALB security group.

3. Container Management (ECR & ECS Modules)

  • We provision an Amazon ECR repository with image scanning on push enabled.
  • We set up an Amazon ECS cluster with Fargate launch type, including a task definition specifying CPU, memory, and container configurations.

4. Load Balancing & Traffic Routing (ALB Module)

  • The Application Load Balancer listens on HTTP/HTTPS and forwards traffic to the ECS target group.
  • Continuous health checks monitor container status, allowing ECS to auto-replace unhealthy instances.

5. Access Management & Logging (IAM & CloudWatch Modules)

  • We configure an ECS task execution role with least-privilege policies to allow pulling ECR images, reading configurations, and writing to CloudWatch.
  • We create a CloudWatch log group with a configurable retention policy to centralize container stdout/stderr.

Deployment Flow

To provision the infrastructure for any environment (e.g., dev):

  1. Configure credentials: Configure AWS credentials locally or in CI via OpenID Connect (OIDC).
  2. Initialize Terraform:
    terraform init -backend-config=environments/dev/backend.hcl
    
  3. Generate a plan: Preview changes to confirm what will be created:
    terraform plan -var-file=environments/dev/dev.tfvars
    
  4. Apply changes: Deploy to AWS:
    terraform apply -var-file=environments/dev/dev.tfvars
    

Security Best Practices

  • Least Privilege: The ECS task execution role only has permissions to access resources it explicitly needs.
  • Vulnerability Scanning: ECR image scanning is active, blocking deployment of images with critical security vulnerabilities.
  • State Protection: Remote state is stored in a private, encrypted S3 bucket with versioning. DynamoDB handles locking to prevent concurrent state changes.
  • No Committed Secrets: Never hardcode secrets or AWS keys in code. Use environment variables and store production secrets in AWS Secrets Manager.

Key Takeaways

  • Environment Isolation: Modular code makes maintaining dev, staging, and production environments from a single repository practical.
  • State Management: Lock files and remote backend configurations are critical when working in teams to avoid overwriting state.
  • IAM Overhead: Scoping IAM permissions correctly is time-consuming but essential for a secure production posture.