How to Set Up a CI/CD Pipeline on AWS Using GitHub Actions and Terraform
Learn how to automate deployments on AWS with GitHub Actions and Terraform, including repository setup, S3 backend configuration, ECS deployment, and safe rollback strategy.
The challenge: Manual deployments cause errors, inconsistent environments create bugs, and teams waste time on repetitive tasks. Infrastructure as Code (IaC) with CI/CD pipelines solve all three.
Why Automate Deployment?
Deploying manually takes hours and requires someone to remember the steps. One missed step, and your production environment drifts from the expected state. IaC and CI/CD eliminate human error.
"Our team spent entire days deployments. Now it's automatic and takes 5 minutes. We deploy multiple times per day with confidence." — DevOps Lead
Step 1: Repository Setup
Create a clean folder structure in your GitHub repo:
infra/
main.tf
variables.tf
outputs.tf
app/
src/
.github/workflows/
deploy.yml
Store secrets in GitHub Actions secrets, never in version control. Use AWS IAM roles with least privilege—each deployment job only has permissions it needs.
Step 2: GitHub Actions Workflow
Define a workflow that triggers on push to main:
name: CI/CD
on:
push:
branches: [main]
jobs:
plan:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: hashicorp/setup-terraform@v2
- run: terraform init
- run: terraform plan
apply:
needs: plan
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: hashicorp/setup-terraform@v2
- run: terraform apply -auto-approve
Step 3: S3 Backend for State Management
Terraform state must be stored centrally so multiple team members can collaborate safely:
terraform {
backend "s3" {
bucket = "my-terraform-state"
key = "prod/terraform.tfstate"
region = "us-east-1"
dynamodb_table = "terraform-lock"
}
}
DynamoDB locks the state during operations, preventing concurrent modifications that cause corruption.
Step 4: Deploy to ECS or EC2
For ECS: Terraform creates the service and task definition. GitHub Actions builds the Docker image, pushes it to ECR, and GitHub Actions updates the ECS service.
For EC2: Terraform creates instances and security groups. GitHub Actions can then SSH into instances or use CodeDeploy for automatic deployments.
Step 5: Rollback Strategy
Keep the previous task definition revision or AMI available for instant rollback. Use GitHub Actions to revert to the previous state:
# Rollback to previous ECS task definition
aws ecs update-service --cluster my-cluster --service my-service --task-definition my-service:PREVIOUS_REVISION
Technologies Used
GitHub Actions • Terraform • AWS S3 • AWS DynamoDB • AWS ECS • AWS EC2 • Docker • ECR • AWS CodeDeploy
Results & Impact
- Deployment time reduced from 4 hours to 8 minutes
- Rollback time improved to 2 minutes vs. manual recovery of 3+ hours
- Infrastructure state is now version-controlled and auditable
- Eliminates configuration drift between environments
- Teams deploy multiple times daily with confidence
Key Learnings
Use separate AWS accounts for prod: If your prod state file is compromised, a bad actor can destroy your entire infrastructure. Separate accounts with cross-account roles are safer.
State file backups are critical: If the S3 bucket is accidentally deleted, you lose your infrastructure. Enable versioning on the state bucket.
Plan before apply: Always review the terraform plan before applying. Automation should never skip human approval for production changes.
Why This Matters
Infrastructure as Code is no longer optional for modern teams. It enables fast iteration, disaster recovery, and audit trails that business teams depend on for compliance.
Build Your CI/CD Pipeline
Automate your infrastructure