<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Celestine Ntadi</title>
    <description>The latest articles on DEV Community by Celestine Ntadi (@celestn).</description>
    <link>https://dev.to/celestn</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3173215%2F22f179e4-77f7-4885-b6ce-9d2e8d11ec06.jpeg</url>
      <title>DEV Community: Celestine Ntadi</title>
      <link>https://dev.to/celestn</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/celestn"/>
    <language>en</language>
    <item>
      <title>From Zero to VibeRoll: Production-Ready DevOps Stack on AWS with Terraform &amp; GitHub Actions</title>
      <dc:creator>Celestine Ntadi</dc:creator>
      <pubDate>Tue, 03 Jun 2025 17:41:06 +0000</pubDate>
      <link>https://dev.to/celestn/from-zero-to-viberoll-production-ready-devops-stack-on-aws-with-terraform-github-actions-4m39</link>
      <guid>https://dev.to/celestn/from-zero-to-viberoll-production-ready-devops-stack-on-aws-with-terraform-github-actions-4m39</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;An educational deep dive into deploying a scalable, secure cloud application using DevOps best practices.&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  What’s This About?
&lt;/h2&gt;

&lt;p&gt;In this post, I’ll walk you through how I built &lt;strong&gt;VibeRoll&lt;/strong&gt;. A modern backend service using a fully automated, production-ready infrastructure powered by:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;AWS&lt;/strong&gt;: ECS Fargate, RDS PostgreSQL, ElastiCache Redis, ALB, Secrets Manager
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Terraform&lt;/strong&gt;: Modular infrastructure as code
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;GitHub Actions&lt;/strong&gt;: End-to-end CI/CD automation
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Secrets Management&lt;/strong&gt;: Validated, versioned, and secure&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Whether you're a cloud engineer, a DevOps enthusiast, or a backend developer curious about scaling securely, you're in the right place.&lt;/p&gt;




&lt;h2&gt;
  
  
  Project Overview
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;VibeRoll&lt;/strong&gt; is a stateless Node.js API that runs entirely on AWS using container orchestration, persistent storage, and a secrets-driven CI/CD pipeline.&lt;/p&gt;

&lt;h3&gt;
  
  
  Requirements
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Node.js API deployed via &lt;strong&gt;ECS Fargate&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;PostgreSQL&lt;/strong&gt; database on &lt;strong&gt;Amazon RDS&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Redis&lt;/strong&gt; cluster using &lt;strong&gt;ElastiCache&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Secrets&lt;/strong&gt; in AWS Secrets Manager (rotated and validated)&lt;/li&gt;
&lt;li&gt;GitHub Actions for &lt;strong&gt;CI/CD&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;VPC, Subnets, Security Groups, WAF for &lt;strong&gt;network isolation&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  1. Architecture Overview
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;strong&gt;Component&lt;/strong&gt;&lt;/th&gt;
&lt;th&gt;&lt;strong&gt;AWS Service&lt;/strong&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Compute&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;ECS Fargate&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Image Registry&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Elastic Container Registry (ECR)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Database&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;RDS PostgreSQL&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Caching&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;ElastiCache (Redis)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Load Balancer&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Application Load Balancer (ALB)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Secrets&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;AWS Secrets Manager&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;CI/CD&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;GitHub Actions&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Monitoring&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Amazon CloudWatch&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Networking&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;VPC with Public/Private Subnets and NAT Gateway&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Security&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Security Groups + AWS WAF&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;




&lt;h2&gt;
  
  
  Why This Architecture?
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;ECS Fargate&lt;/strong&gt; provides serverless container orchestration, reducing ops overhead.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;ECR&lt;/strong&gt; is a secure and scalable container image registry tightly integrated with ECS.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;RDS PostgreSQL&lt;/strong&gt; manages our relational data layer, providing automated backups and failover.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;ElastiCache Redis&lt;/strong&gt; boosts application performance with low-latency caching.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;ALB&lt;/strong&gt; ensures traffic is distributed intelligently with built-in health checks.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Secrets Manager&lt;/strong&gt; centralizes and encrypts environment secrets for applications.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;GitHub Actions&lt;/strong&gt; handles continuous integration and deployment from the repo to the cloud.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;CloudWatch&lt;/strong&gt; offers full-stack observability with logs, metrics, and alarms.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;VPC + NAT GW&lt;/strong&gt; create a secure and flexible network layout with controlled internet access.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;WAF + Security Groups&lt;/strong&gt; protect against common web exploits and control traffic at the instance level.&lt;/li&gt;
&lt;/ul&gt;




&lt;h3&gt;
  
  
  Diagram Summary
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;ALB in &lt;strong&gt;public subnet&lt;/strong&gt; → routes traffic to ECS tasks in &lt;strong&gt;private subnets&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;RDS and Redis stay private and secure&lt;/li&gt;
&lt;li&gt;ECR hosts Docker images for ECS to pull on deployment&lt;/li&gt;
&lt;li&gt;NAT Gateway allows outbound ECS traffic (e.g., pulling images from ECR)&lt;/li&gt;
&lt;li&gt;GitHub Actions automates the deployment of both infrastructure and app&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fzxna554hiuqoyxtg8d3k.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fzxna554hiuqoyxtg8d3k.png" alt="Architecture Diagram" width="800" height="933"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  2. VPC + Subnet Layout
&lt;/h2&gt;

&lt;p&gt;Three-tier network setup:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;public&lt;/code&gt; subnet → ALB
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;private&lt;/code&gt; subnet → ECS tasks, RDS, Redis
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;NAT Gateway&lt;/strong&gt; allows private ECS tasks to pull images
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight hcl"&gt;&lt;code&gt;&lt;span class="nx"&gt;module&lt;/span&gt; &lt;span class="s2"&gt;"vpc"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;source&lt;/span&gt;   &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"./modules/vpc"&lt;/span&gt;
  &lt;span class="nx"&gt;vpc_cidr&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;var&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;vpc_cidr&lt;/span&gt;
  &lt;span class="nx"&gt;azs&lt;/span&gt;      &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;var&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;azs&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  3. Modular Terraform Setup
&lt;/h2&gt;

&lt;p&gt;Each part of the infrastructure is modularized for reusability and clarity:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;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$
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Example – RDS Module
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight hcl"&gt;&lt;code&gt;&lt;span class="nx"&gt;resource&lt;/span&gt; &lt;span class="s2"&gt;"aws_db_instance"&lt;/span&gt; &lt;span class="s2"&gt;"postgres"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;identifier&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"${var.project_name}-postgres"&lt;/span&gt;
  &lt;span class="nx"&gt;engine&lt;/span&gt;     &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"postgres"&lt;/span&gt;
  &lt;span class="nx"&gt;db_name&lt;/span&gt;    &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;var&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;db_name&lt;/span&gt;
  &lt;span class="nx"&gt;username&lt;/span&gt;   &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;var&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;db_username&lt;/span&gt;
  &lt;span class="nx"&gt;password&lt;/span&gt;   &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;var&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;db_password&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  4. Secrets Management via AWS Secrets Manager
&lt;/h2&gt;

&lt;p&gt;Secrets are securely passed and verified via GitHub Actions:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight hcl"&gt;&lt;code&gt;&lt;span class="nx"&gt;resource&lt;/span&gt; &lt;span class="s2"&gt;"aws_secretsmanager_secret"&lt;/span&gt; &lt;span class="s2"&gt;"secrets"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;for_each&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;var&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;secrets_map&lt;/span&gt;
  &lt;span class="nx"&gt;name&lt;/span&gt;     &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"${var.project_name}-${each.key}"&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight hcl"&gt;&lt;code&gt;&lt;span class="nx"&gt;resource&lt;/span&gt; &lt;span class="s2"&gt;"aws_secretsmanager_secret_version"&lt;/span&gt; &lt;span class="s2"&gt;"secrets_version"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;for_each&lt;/span&gt;        &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;aws_secretsmanager_secret&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;secrets&lt;/span&gt;
  &lt;span class="nx"&gt;secret_id&lt;/span&gt;       &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;each&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;
  &lt;span class="nx"&gt;secret_string&lt;/span&gt;   &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;var&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;secrets_map&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;each&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;key&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
  &lt;span class="nx"&gt;version_stages&lt;/span&gt;  &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"AWSCURRENT"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;✅ CI pipeline &lt;strong&gt;fails early&lt;/strong&gt; if a secret is missing or empty&lt;br&gt;&lt;br&gt;
✅ Secrets are validated before any &lt;code&gt;terraform apply&lt;/code&gt;&lt;/p&gt;


&lt;h2&gt;
  
  
  5. CI/CD with GitHub Actions
&lt;/h2&gt;

&lt;p&gt;Here’s how the workflow is structured:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Terraform Plan&lt;/span&gt;
  &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;|&lt;/span&gt;
    &lt;span class="s"&gt;terraform plan -input=false -out=tfplan \&lt;/span&gt;
      &lt;span class="s"&gt;-var-file="secrets.auto.tfvars.json" \&lt;/span&gt;
      &lt;span class="s"&gt;-var="project_name=${TF_PROJECT_NAME}" \&lt;/span&gt;
      &lt;span class="s"&gt;-var="db_username=${TF_DB_USERNAME}"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Key Steps:
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;✅ Validate secrets
&lt;/li&gt;
&lt;li&gt;✅ Generate &lt;code&gt;secrets.auto.tfvars.json&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;✅ Run &lt;code&gt;terraform init&lt;/code&gt;, &lt;code&gt;plan&lt;/code&gt;, &lt;code&gt;apply&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;✅ Fail early if secrets are misconfigured&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  6. Testing the Setup
&lt;/h2&gt;

&lt;h3&gt;
  
  
  ✅ ECS
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Get the &lt;strong&gt;ALB DNS&lt;/strong&gt; output&lt;/li&gt;
&lt;li&gt;Curl or open it in a browser to verify your service is running&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  ✅ RDS
&lt;/h3&gt;

&lt;p&gt;Temporarily allow your IP in the RDS security group and run:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;psql &lt;span class="nt"&gt;-h&lt;/span&gt; &amp;lt;endpoint&amp;gt; &lt;span class="nt"&gt;-U&lt;/span&gt; viberoll_service &lt;span class="nt"&gt;-d&lt;/span&gt; viberoll &lt;span class="nt"&gt;-p&lt;/span&gt; 5432
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Run basic SQL queries to verify connectivity.&lt;/p&gt;




&lt;h2&gt;
  
  
  7. Lessons Learned
&lt;/h2&gt;

&lt;h3&gt;
  
  
  What Went Wrong
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Secrets missing the &lt;code&gt;AWSCURRENT&lt;/code&gt; label
&lt;/li&gt;
&lt;li&gt;Dynamic &lt;code&gt;for_each&lt;/code&gt; maps failed during plan
&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Fixes
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Forced secret version to always include &lt;code&gt;AWSCURRENT&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Added a &lt;code&gt;null_resource&lt;/code&gt; to validate secrets
&lt;/li&gt;
&lt;li&gt;Refactored the secrets map to be predictable&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  8. Final Thoughts
&lt;/h2&gt;

&lt;p&gt;This project showcases how to build &lt;strong&gt;secure&lt;/strong&gt;, &lt;strong&gt;scalable&lt;/strong&gt;, and &lt;strong&gt;repeatable infrastructure&lt;/strong&gt; for real-world backend applications using modern DevOps practices:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Secure by design (VPC, secrets, IAM)
&lt;/li&gt;
&lt;li&gt;Modular infrastructure (Terraform)
&lt;/li&gt;
&lt;li&gt;Fully automated CI/CD (GitHub Actions)
&lt;/li&gt;
&lt;li&gt;Post-deploy testing included&lt;/li&gt;
&lt;/ul&gt;




&lt;p&gt;&lt;strong&gt;ElasticCache Cluster&lt;/strong&gt;&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ft7v27jcfogkh0usovo8b.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ft7v27jcfogkh0usovo8b.png" alt="ElasticCache Cluster" width="800" height="166"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Amazon Elastic Container Service (ECS) Cluster&lt;/strong&gt;&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F8ytlopfcqhisocbc57uj.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F8ytlopfcqhisocbc57uj.png" alt="Amazon Elastic Container Service (ECS) Cluster" width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Application Load Balancer (ALB)&lt;/strong&gt;&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fl5j0z8ib68x1kopgoqin.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fl5j0z8ib68x1kopgoqin.png" alt="Application Load Balancer (ALB)" width="800" height="449"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Elastic Container Registry&lt;/strong&gt;&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fx1i5503t30wd3lqi68v4.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fx1i5503t30wd3lqi68v4.png" alt="Elastic Container Registry" width="800" height="447"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;SwaggerUI Sample User Created&lt;/strong&gt;&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fa9rp05mik65r5z4lzwgx.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fa9rp05mik65r5z4lzwgx.png" alt="SwaggerUI Sample User Created" width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Integrated Docker Image to Infra Deployment&lt;/strong&gt;&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fcpqmltafbf681jgm6dt4.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fcpqmltafbf681jgm6dt4.png" alt="Integrated Docker Image to Infra Deployment" width="800" height="449"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F41k024b31x0xbcs7eyd2.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F41k024b31x0xbcs7eyd2.png" alt="Integrated Docker Image to Infra Deployment" width="800" height="449"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;WAF &amp;amp; Shield&lt;/strong&gt;&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fuoayuidq5em3t3c1484k.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fuoayuidq5em3t3c1484k.png" alt="WAF &amp;amp; Shield" width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Application ELB&lt;/strong&gt;&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6phj3rgsg6s6aghix0j3.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6phj3rgsg6s6aghix0j3.png" alt="Application ELB" width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  Resources
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;GitHub Repo: &lt;a href="https://github.com/celestn1/viberoll-infra" rel="noopener noreferrer"&gt;viberoll-infra Repo&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Terraform AWS Provider: &lt;a href="https://registry.terraform.io/providers/hashicorp/aws" rel="noopener noreferrer"&gt;terraform.io&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;AWS Secrets Manager: &lt;a href="https://docs.aws.amazon.com/secretsmanager" rel="noopener noreferrer"&gt;docs.aws.amazon.com&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  ❤️ Like This Setup?
&lt;/h2&gt;

&lt;p&gt;Fork the repository, tweak the variables, and you're ready to deploy your own cloud-native service quickly, securely, and in production-grade quality.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Got questions or ideas to improve this stack? Drop a comment below!&lt;/strong&gt;&lt;/p&gt;

</description>
      <category>aws</category>
      <category>devops</category>
      <category>terraform</category>
      <category>ecs</category>
    </item>
    <item>
      <title>Building and Deploying a Scalable Video Platform: DevOps Contributions from the VibeRoll Project</title>
      <dc:creator>Celestine Ntadi</dc:creator>
      <pubDate>Sat, 17 May 2025 10:50:56 +0000</pubDate>
      <link>https://dev.to/celestn/building-and-deploying-a-scalable-video-platform-devops-contributions-from-the-viberoll-project-cg4</link>
      <guid>https://dev.to/celestn/building-and-deploying-a-scalable-video-platform-devops-contributions-from-the-viberoll-project-cg4</guid>
      <description>&lt;p&gt;As part of my work on &lt;strong&gt;VibeRoll&lt;/strong&gt;, a next-generation video-sharing platform with blockchain integrations, I led the full backend architecture and DevOps implementation. This post outlines how I applied advanced DevOps practices, overcame infrastructure challenges, and built a CI/CD pipeline that aligns with industry best practices. The project is fully open-source and available at &lt;a href="https://github.com/celestn1/viberoll-backend" rel="noopener noreferrer"&gt;GitHub Repo&lt;/a&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  Why DevOps Matters for Media-Heavy Applications
&lt;/h2&gt;

&lt;p&gt;VibeRoll aims to blend social video sharing with NFT and AI integrations. The infrastructure requirements included:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;High I/O and network throughput for video uploads&lt;/li&gt;
&lt;li&gt;Real-time data support using Redis&lt;/li&gt;
&lt;li&gt;Token-based authentication and rate limiting&lt;/li&gt;
&lt;li&gt;Frequent iteration and deployments&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;To deliver this reliably, I implemented a DevOps-first approach.&lt;/p&gt;




&lt;h2&gt;
  
  
  Cloud Infrastructure and CI/CD Pipeline
&lt;/h2&gt;

&lt;p&gt;I deployed the application on an &lt;strong&gt;Azure Linux VM&lt;/strong&gt;, using:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Node.js (Express)&lt;/strong&gt; for the backend API&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;PostgreSQL&lt;/strong&gt; and &lt;strong&gt;Redis&lt;/strong&gt; for persistent and cache storage&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;GitHub Actions&lt;/strong&gt; for CI/CD with service containers&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Contributions:
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Created a CI/CD workflow that:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Spins up Postgres and Redis using Docker&lt;/li&gt;
&lt;li&gt;Installs dependencies, runs tests, linting, and audit checks&lt;/li&gt;
&lt;li&gt;Seeds a test database via &lt;code&gt;Prisma&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;&lt;p&gt;Authored the &lt;code&gt;.github/workflows/ci.yml&lt;/code&gt; from scratch and debugged cross-service health checks&lt;/p&gt;&lt;/li&gt;

&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Repo:&lt;/strong&gt; &lt;a href="https://github.com/celestn1/viberoll-backend" rel="noopener noreferrer"&gt;viberoll-backend GitHub&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  Dependency and Security Management
&lt;/h2&gt;

&lt;p&gt;During testing, GitHub Dependabot flagged a high-severity &lt;strong&gt;SSRF vulnerability in axios&lt;/strong&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  My Actions:
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Used &lt;code&gt;npm-check-updates&lt;/code&gt; to upgrade all packages&lt;/li&gt;
&lt;li&gt;Integrated Dependabot into the CI lifecycle&lt;/li&gt;
&lt;li&gt;Configured GitHub Actions to fail builds on &lt;code&gt;npm audit&lt;/code&gt; high-severity issues&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Impact:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Improved application security posture&lt;/li&gt;
&lt;li&gt;Ensured continuous compliance with open-source package hygiene&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Infrastructure as Code and Database Migrations
&lt;/h2&gt;

&lt;p&gt;To support version-controlled schema changes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;I added &lt;strong&gt;Prisma ORM&lt;/strong&gt; with full migration and seed capabilities&lt;/li&gt;
&lt;li&gt;Wrote seed scripts to automate admin account provisioning&lt;/li&gt;
&lt;li&gt;Enabled repeatable test environments in CI/CD
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npx prisma migrate deploy
npx prisma db seed
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This ensured consistency between local, test, and production environments.&lt;/p&gt;




&lt;h2&gt;
  
  
  Swagger UI and Dynamic Cloud URLs
&lt;/h2&gt;

&lt;p&gt;Swagger by default binds to localhost, which fails in cloud deployments. I enhanced it to dynamically detect IPs:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;baseUrl&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;HOST&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;http://localhost:&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;}${&lt;/span&gt;&lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;PORT&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="mi"&gt;4000&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This allowed both local and public Swagger API access, critical for QA and frontend developers.&lt;/p&gt;




&lt;h2&gt;
  
  
  Final DevOps Checklist
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Task&lt;/th&gt;
&lt;th&gt;Description&lt;/th&gt;
&lt;th&gt;Status&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;CI/CD Pipeline&lt;/td&gt;
&lt;td&gt;GitHub Actions with Docker containers&lt;/td&gt;
&lt;td&gt;✅ Done&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Prisma Migrations&lt;/td&gt;
&lt;td&gt;Schema version control&lt;/td&gt;
&lt;td&gt;✅ Done&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Seed Script&lt;/td&gt;
&lt;td&gt;Automated admin and test data&lt;/td&gt;
&lt;td&gt;✅ Done&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;.env.example&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Environment templating and validation&lt;/td&gt;
&lt;td&gt;✅ Done&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Swagger Dynamic Host&lt;/td&gt;
&lt;td&gt;Public documentation support&lt;/td&gt;
&lt;td&gt;✅ Done&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Security Audit Integration&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;npm audit&lt;/code&gt; + Dependabot&lt;/td&gt;
&lt;td&gt;✅ Done&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;




&lt;h2&gt;
  
  
  Outcomes and Lessons Learned
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Reduced onboarding time by automating dev setup and DB creation&lt;/li&gt;
&lt;li&gt;Shortened deploy cycles with CI/CD pipelines&lt;/li&gt;
&lt;li&gt;Prevented production risks by patching vulnerabilities early&lt;/li&gt;
&lt;li&gt;Enabled safe multi-user collaboration via GitHub workflows&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;In this project, I showcased how DevOps practices, from CI/CD automation to security enforcement, can transform a backend service from being local-only to becoming cloud-ready. My contributions included infrastructure planning, toolchain integration, and ensuring deployment resilience.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;This work reflects my ability to build, scale, and secure cloud-native services with DevOps methodologies.&lt;/strong&gt;&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Feel free to explore the open-source repo and CI/CD workflows: &lt;a href="https://github.com/celestn1/viberoll-backend" rel="noopener noreferrer"&gt;Open-source viberoll-backend repo&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

</description>
    </item>
  </channel>
</rss>
