An educational deep dive into deploying a scalable, secure cloud application using DevOps best practices.
What’s This About?
In this post, I’ll walk you through how I built VibeRoll. A modern backend service using a fully automated, production-ready infrastructure powered by:
- AWS: ECS Fargate, RDS PostgreSQL, ElastiCache Redis, ALB, Secrets Manager
- Terraform: Modular infrastructure as code
- GitHub Actions: End-to-end CI/CD automation
- Secrets Management: Validated, versioned, and secure
Whether you're a cloud engineer, a DevOps enthusiast, or a backend developer curious about scaling securely, you're in the right place.
Project Overview
VibeRoll is a stateless Node.js API that runs entirely on AWS using container orchestration, persistent storage, and a secrets-driven CI/CD pipeline.
Requirements
- Node.js API deployed via ECS Fargate
- PostgreSQL database on Amazon RDS
- Redis cluster using ElastiCache
- Secrets in AWS Secrets Manager (rotated and validated)
- GitHub Actions for CI/CD
- VPC, Subnets, Security Groups, WAF for network isolation
1. Architecture Overview
Component | AWS Service |
---|---|
Compute | ECS Fargate |
Image Registry | Elastic Container Registry (ECR) |
Database | RDS PostgreSQL |
Caching | ElastiCache (Redis) |
Load Balancer | Application Load Balancer (ALB) |
Secrets | AWS Secrets Manager |
CI/CD | GitHub Actions |
Monitoring | Amazon CloudWatch |
Networking | VPC with Public/Private Subnets and NAT Gateway |
Security | Security Groups + AWS WAF |
Why This Architecture?
- ECS Fargate provides serverless container orchestration, reducing ops overhead.
- ECR is a secure and scalable container image registry tightly integrated with ECS.
- RDS PostgreSQL manages our relational data layer, providing automated backups and failover.
- ElastiCache Redis boosts application performance with low-latency caching.
- ALB ensures traffic is distributed intelligently with built-in health checks.
- Secrets Manager centralizes and encrypts environment secrets for applications.
- GitHub Actions handles continuous integration and deployment from the repo to the cloud.
- CloudWatch offers full-stack observability with logs, metrics, and alarms.
- VPC + NAT GW create a secure and flexible network layout with controlled internet access.
- WAF + Security Groups protect against common web exploits and control traffic at the instance level.
Diagram Summary
- ALB in public subnet → routes traffic to ECS tasks in private subnets
- RDS and Redis stay private and secure
- ECR hosts Docker images for ECS to pull on deployment
- NAT Gateway allows outbound ECS traffic (e.g., pulling images from ECR)
- GitHub Actions automates the deployment of both infrastructure and app
2. VPC + Subnet Layout
Three-tier network setup:
-
public
subnet → ALB -
private
subnet → ECS tasks, RDS, Redis - NAT Gateway allows private ECS tasks to pull images
module "vpc" {
source = "./modules/vpc"
vpc_cidr = var.vpc_cidr
azs = var.azs
}
3. Modular Terraform Setup
Each part of the infrastructure is modularized for reusability and clarity:
celestn@CN001:/viberoll-project/viberoll-infra$ tree -I 'node_modules' -L 2
.
├── README.md
├── backend.tf
├── images
│ └── viberoll_architecture_improved.png
├── main.tf
├── modules
│ ├── alb
│ ├── cloudwatch
│ ├── ecr
│ ├── ecs
│ ├── elasticache
│ ├── rds
│ ├── secrets
│ ├── vpc
│ └── waf
├── outputs.tf
├── terraform.tfvars
└── variables.tf
12 directories, 8 files
celestn@CN001:/viberoll-project/viberoll-infra$
Example – RDS Module
resource "aws_db_instance" "postgres" {
identifier = "${var.project_name}-postgres"
engine = "postgres"
db_name = var.db_name
username = var.db_username
password = var.db_password
}
4. Secrets Management via AWS Secrets Manager
Secrets are securely passed and verified via GitHub Actions:
resource "aws_secretsmanager_secret" "secrets" {
for_each = var.secrets_map
name = "${var.project_name}-${each.key}"
}
resource "aws_secretsmanager_secret_version" "secrets_version" {
for_each = aws_secretsmanager_secret.secrets
secret_id = each.value.id
secret_string = var.secrets_map[each.key]
version_stages = ["AWSCURRENT"]
}
✅ CI pipeline fails early if a secret is missing or empty
✅ Secrets are validated before any terraform apply
5. CI/CD with GitHub Actions
Here’s how the workflow is structured:
- name: Terraform Plan
run: |
terraform plan -input=false -out=tfplan \
-var-file="secrets.auto.tfvars.json" \
-var="project_name=${TF_PROJECT_NAME}" \
-var="db_username=${TF_DB_USERNAME}"
Key Steps:
- ✅ Validate secrets
- ✅ Generate
secrets.auto.tfvars.json
- ✅ Run
terraform init
,plan
,apply
- ✅ Fail early if secrets are misconfigured
6. Testing the Setup
✅ ECS
- Get the ALB DNS output
- Curl or open it in a browser to verify your service is running
✅ RDS
Temporarily allow your IP in the RDS security group and run:
psql -h <endpoint> -U viberoll_service -d viberoll -p 5432
Run basic SQL queries to verify connectivity.
7. Lessons Learned
What Went Wrong
- Secrets missing the
AWSCURRENT
label - Dynamic
for_each
maps failed during plan
Fixes
- Forced secret version to always include
AWSCURRENT
- Added a
null_resource
to validate secrets - Refactored the secrets map to be predictable
8. Final Thoughts
This project showcases how to build secure, scalable, and repeatable infrastructure for real-world backend applications using modern DevOps practices:
- Secure by design (VPC, secrets, IAM)
- Modular infrastructure (Terraform)
- Fully automated CI/CD (GitHub Actions)
- Post-deploy testing included
Amazon Elastic Container Service (ECS) Cluster
Application Load Balancer (ALB)
Integrated Docker Image to Infra Deployment
Resources
- GitHub Repo: viberoll-infra Repo
- Terraform AWS Provider: terraform.io
- AWS Secrets Manager: docs.aws.amazon.com
❤️ Like This Setup?
Fork the repository, tweak the variables, and you're ready to deploy your own cloud-native service quickly, securely, and in production-grade quality.
Got questions or ideas to improve this stack? Drop a comment below!
Top comments (0)
Some comments may only be visible to logged-in visitors. Sign in to view all comments.