Day 27 – Production Style AWS Infrastructure with Terraform and GitHub Actions CI/CD
Introduction
For Day 27 of my AWS and Terraform learning journey, I wanted to move beyond basic Terraform deployments and simulate a more production style Infrastructure as Code workflow.
The goal of this project was not just to deploy AWS resources manually from a laptop, but to build a deployment pipeline where infrastructure changes are reviewed, approved, and automatically applied through GitHub Actions.
This project included:
- Terraform based AWS infrastructure deployment
- GitHub Actions CI/CD workflow
- AWS OIDC authentication instead of static access keys
- Protected production approval workflow
- Auto Scaling Group infrastructure updates through Git commits
- Multi AZ production style network architecture
Architecture Overview
This architecture includes:
- VPC with public and private subnets
- Internet Gateway
- NAT Gateway
- Application Load Balancer
- Auto Scaling Group
- EC2 instances running Nginx
- S3 backend for Terraform remote state
- GitHub Actions CI/CD pipeline
- GitHub OIDC authentication with AWS IAM Role
Project Structure
The repository was structured to separate infrastructure deployment logic, bootstrap configuration, CI/CD workflows, and helper scripts.
My repository structure included:
.github/workflows
bootstrap-oidc
scripts
main.tf
variables.tf
outputs.tf
providers.tf
locals.tf
versions.tf
user_data.sh
terraform.auto.tfvars
Why I Used GitHub Actions
In real production environments, infrastructure changes are usually not applied manually from a local machine.
Instead, the workflow typically looks like this:
Developer Push
→ Pull Request
→ Terraform Plan
→ Approval
→ Terraform Apply
→ Infrastructure Update
GitHub Actions allowed me to automate this process and simulate a controlled production deployment pipeline.
Terraform Remote Backend
I configured Terraform remote state using Amazon S3.
This allows Terraform state to remain centralized instead of storing it only on a local laptop.
Backend bucket configuration:
bucket = "jay-terraformstate-bucket"
region = "us-east-1"
encrypt = true
use_lockfile = true
Benefits:
- Centralized Terraform state
- State locking support
- Team collaboration readiness
- Better operational consistency
AWS Infrastructure Components
The infrastructure deployed through Terraform included:
Networking
- Custom VPC
- Public subnets
- Private subnets
- Internet Gateway
- NAT Gateway
- Route tables
Compute Layer
- Launch Template
- Auto Scaling Group
- EC2 instances
- User data bootstrap script
Load Balancing
- Application Load Balancer
- Target Group
- Health checks
- HTTP Listener
Storage
- S3 bucket for assets and logs
GitHub Actions CI/CD Workflow
The GitHub Actions workflow was responsible for:
- Terraform formatting validation
- Terraform initialization
- Terraform validation
- Terraform planning
- Terraform apply
- Manual production approval
Workflow file location:
.github/workflows/terraform.yml
The workflow used:
environment: Prod
This enabled protected production deployments with approval gates.
AWS OIDC Authentication
One of the most important parts of this project was implementing AWS OIDC authentication for GitHub Actions.
Instead of storing long lived AWS access keys inside GitHub secrets, GitHub Actions authenticated to AWS using temporary credentials.
The workflow assumed an AWS IAM Role using:
aws-actions/configure-aws-credentials@v4
This is a much better security practice compared to storing static access keys in CI/CD systems.
Benefits:
- No hardcoded AWS credentials
- Temporary short lived authentication
- Reduced credential exposure risk
- Production style security model
Protected Production Approval Workflow
I also implemented a production deployment approval process.
Before Terraform apply executes, GitHub Actions pauses and waits for manual approval.
This simulates a real production deployment gate where infrastructure changes require review before execution.
GitHub Environment:
Prod
Protection Rule:
- Required reviewer enabled
This was one of the most useful learning experiences because it demonstrated how infrastructure deployments are controlled in enterprise environments.
Testing Infrastructure Changes Through CI/CD
To test the full Infrastructure as Code lifecycle, I updated the Auto Scaling Group desired capacity.
Original value:
desired_capacity = 2
Updated value:
desired_capacity = 3
After committing and pushing the change, GitHub Actions automatically triggered the Terraform workflow.
Terraform detected infrastructure drift and generated the following plan:
desired_capacity = 2 -> 3
This was an important learning moment because it clearly demonstrated how Terraform compares:
- Desired infrastructure state
- Terraform state file
- Actual AWS infrastructure
Terraform then safely modified the Auto Scaling Group in place.
Terraform Apply Through GitHub Actions
After approving the deployment, GitHub Actions automatically executed Terraform apply.
Terraform updated the Auto Scaling Group successfully without recreating the infrastructure.
Terraform output:
Plan: 0 to add, 1 to change, 0 to destroy
This demonstrated safe infrastructure reconciliation through CI/CD.
Auto Scaling Group Validation
After deployment, I verified the infrastructure directly from AWS.
Checks performed:
- EC2 instances launched successfully
- Target group health checks passed
- ALB traffic routing worked correctly
- Auto Scaling Group updated desired capacity
Application Validation
I validated the deployed application using the ALB DNS endpoint.
Example:
http://day27-prod-infra-prod-alb-xxxxxxxx.us-east-1.elb.amazonaws.com
The application was successfully accessible through the Application Load Balancer.
Key Learnings
This project helped me understand that Infrastructure as Code is not just about writing Terraform scripts.
The bigger learning was understanding how infrastructure changes move through a controlled deployment lifecycle.
Some of the biggest takeaways from this project were:
- GitHub Actions can fully automate Terraform deployments
- AWS OIDC is much more secure than static AWS access keys
- Protected production approvals are critical for infrastructure safety
- Terraform continuously reconciles desired state against real infrastructure
- Infrastructure changes can be version controlled just like application code
- Production style infrastructure workflows require validation, approvals, and controlled deployment processes
Challenges Faced
Availability Zone Compatibility Issue
Initially, Terraform selected an unsupported Availability Zone combination for NAT Gateway and ALB resources.
I fixed this by filtering the Terraform Availability Zone data source to use only standard Availability Zones.
GitHub Actions Workflow Location
At first, GitHub Actions did not detect my workflow because the .github/workflows folder was inside the project folder instead of the repository root.
Moving the workflow folder to the repository root resolved the issue.
OIDC Permission Error
After enabling GitHub Environment protection, AWS OIDC authentication initially failed.
I updated the IAM trust policy to allow:
repo:<org>/<repo>:environment:Prod
which resolved the authorization issue.
Final Thoughts
This was one of the most practical Terraform projects I have worked on so far because it combined:
- AWS infrastructure
- Terraform
- CI/CD automation
- GitHub Actions
- IAM security
- Approval workflows
- Infrastructure reconciliation
The project helped me better understand how production infrastructure deployments are automated and controlled in real environments.
Cleanup
To destroy the infrastructure:
terraform destroy
To destroy bootstrap OIDC resources:
cd bootstrap-oidc
terraform destroyVideo Reference
Comments
Post a Comment