<?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: Ngozi</title>
    <description>The latest articles on DEV Community by Ngozi (@ngozi_n).</description>
    <link>https://dev.to/ngozi_n</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%2F3259805%2Fdbfffe3b-37ed-48be-8d15-48b471aa6509.jpg</url>
      <title>DEV Community: Ngozi</title>
      <link>https://dev.to/ngozi_n</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/ngozi_n"/>
    <language>en</language>
    <item>
      <title>Automating S3 Cross-Region Replication (CRR) with Pulumi</title>
      <dc:creator>Ngozi</dc:creator>
      <pubDate>Mon, 21 Jul 2025 11:15:43 +0000</pubDate>
      <link>https://dev.to/ngozi_n/automating-s3-cross-region-replication-crr-with-pulumi-d8j</link>
      <guid>https://dev.to/ngozi_n/automating-s3-cross-region-replication-crr-with-pulumi-d8j</guid>
      <description>&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%2Fir0sgmehn2hvyqsxkza5.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%2Fir0sgmehn2hvyqsxkza5.png" alt="Architectural Diagram" width="778" height="274"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Managing data redundancy and disaster recovery is critical in cloud environments. I will show you how to set up S3 Cross-Region Replication (CRR) using Pulumi — a modern Infrastructure as Code tool that lets you use familiar programming languages like Python to provision cloud resources.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What is S3 Cross-Region Replication (CRR)?&lt;/strong&gt;&lt;br&gt;
S3 CRR automatically replicates objects from one S3 bucket in a specific AWS region to another bucket in a different region. This ensures:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;High availability&lt;/li&gt;
&lt;li&gt;Improved disaster recovery&lt;/li&gt;
&lt;li&gt;Regional compliance requirements&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Steps to Deploy S3 CRR with Pulumi&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;em&gt;Setup Pulumi and AWS CLI&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Ensure AWS CLI is configured with appropriate IAM permissions.&lt;/li&gt;
&lt;li&gt;Install Pulumi:&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;code&gt;curl -fsSL https://get.pulumi.com | sh&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;&lt;strong&gt;Define Infrastructure with Pulumi (Python)&lt;/strong&gt;&lt;/em&gt;&lt;br&gt;
The core of the project includes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Source S3 Bucket (e.g., us-east-1)&lt;/li&gt;
&lt;li&gt;Destination S3 Bucket (e.g., us-west-2)&lt;/li&gt;
&lt;li&gt;Replication Role &amp;amp; Policy&lt;/li&gt;
&lt;li&gt;Replication Configuration
Pulumi uses aws.s3.Bucket and related resources to build this.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;em&gt;&lt;strong&gt;Deploy Infrastructure&lt;/strong&gt;&lt;/em&gt;&lt;br&gt;
In your terminal, navigate to your project directory and run:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;pulumi up&lt;/code&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%2Flhd9g8mmwxqzb6eexmmr.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%2Flhd9g8mmwxqzb6eexmmr.PNG" alt="pulumi up" width="800" height="394"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This command:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Creates both S3 buckets&lt;/li&gt;
&lt;li&gt;Sets up replication configuration&lt;/li&gt;
&lt;li&gt;Deploys necessary IAM roles&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%2Faorquxiv56lf9grqtmat.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%2Faorquxiv56lf9grqtmat.PNG" alt="S3Buckets created in both specified regions in AWS" width="800" height="252"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;&lt;strong&gt;Test the Replication&lt;/strong&gt;&lt;/em&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Upload objects to your source bucket via AWS Console or CLI.&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%2Fjg1mf8ouz02si58vriu2.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%2Fjg1mf8ouz02si58vriu2.PNG" alt="Uploaded objects to source bucket" width="800" height="190"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Pulumi-enabled CRR will automatically replicate the objects to your destination bucket.&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%2Fsedtbx7l2vmkbangh82d.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%2Fsedtbx7l2vmkbangh82d.PNG" alt="Objects replicated in destination bucket at the same time" width="800" height="194"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;em&gt;Destroy Infrastructure&lt;/em&gt;&lt;/strong&gt;&lt;br&gt;
To remove all deployed resources:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;pulumi destroy&lt;/code&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%2Fbnwn5rpv3n78gmg5bup8.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%2Fbnwn5rpv3n78gmg5bup8.PNG" alt="pulumi destroy" width="800" height="458"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Final Thoughts&lt;/strong&gt;&lt;br&gt;
By using Pulumi to automate S3 CRR:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;You simplify repetitive infrastructure tasks.&lt;/li&gt;
&lt;li&gt;Manage multi-region replication efficiently.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Pulumi’s ability to manage AWS resources through familiar programming makes it a powerful tool for DevOps Engineers seeking flexibility.&lt;/p&gt;

&lt;p&gt;All project files are available here: &lt;a href="https://github.com/Ngozi-N/s3-crr-with-pulumi.git" rel="noopener noreferrer"&gt;GitHub Repository&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Let’s connect on &lt;a href="http://www.linkedin.com/in/ngozinwadialo" rel="noopener noreferrer"&gt;LinkedIn&lt;/a&gt;!&lt;/p&gt;

</description>
      <category>pulumi</category>
      <category>python</category>
      <category>s3</category>
      <category>crr</category>
    </item>
    <item>
      <title>Automating IAM Cleanup: How I Built an Inactive Users Detection System on AWS Using Lambda, Terraform &amp; SNS</title>
      <dc:creator>Ngozi</dc:creator>
      <pubDate>Mon, 23 Jun 2025 16:04:14 +0000</pubDate>
      <link>https://dev.to/ngozi_n/automating-iam-cleanup-how-i-built-an-inactive-users-detection-system-on-aws-using-lambda-3l5a</link>
      <guid>https://dev.to/ngozi_n/automating-iam-cleanup-how-i-built-an-inactive-users-detection-system-on-aws-using-lambda-3l5a</guid>
      <description>&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%2Fw41qtyg4juu6q4ifdsmo.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%2Fw41qtyg4juu6q4ifdsmo.png" alt="Architectural Diagram" width="734" height="469"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;p&gt;IAM users often get created and forgotten. And forgotten IAM users are a security risk.&lt;br&gt;
In this project, I automated the detection of inactive IAM users and sent alerts using AWS Lambda, EventBridge, SNS, and S3 — all provisioned with Terraform. Here’s how I did it.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Tools Used:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Terraform: Infrastructure provisioning&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Lambda (Python): Logic for identifying inactive users&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;IAM: User credentials check&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;S3: Archival of inactive user reports&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;SNS: Notification delivery&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;EventBridge: Scheduled execution (CRON: every Monday at 12pm)&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;




&lt;p&gt;&lt;strong&gt;Step 1 — Terraform Setup&lt;/strong&gt;&lt;br&gt;
I started by writing Terraform files to create all required AWS resources: an S3 bucket, an SNS topic, a Lambda function, and an EventBridge rule to trigger the function on a schedule.&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%2F8axgppebl1cd6e2pglxa.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%2F8axgppebl1cd6e2pglxa.PNG" alt="terraform apply" width="800" height="158"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;Step 2 — Writing the Lambda Function (Python)&lt;/strong&gt;&lt;br&gt;
The core logic was written in Python using boto3. It:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Lists all IAM users&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Checks PasswordLastUsed&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Flags users inactive for over 90 days&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Saves the list in S3&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Sends it as an email notification via SNS&lt;/p&gt;&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%2Fn7q3rm04mzw6dpcp09gy.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%2Fn7q3rm04mzw6dpcp09gy.PNG" alt="current IAM users" width="800" height="306"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;Step 3 — Scheduling with EventBridge&lt;/strong&gt;&lt;br&gt;
I used a CRON expression to schedule the function to run weekly on Mondays at 12pm.&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%2F71pk0cadzjlc4u3yh3b6.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%2F71pk0cadzjlc4u3yh3b6.PNG" alt="Event rule showing cron schedule" width="800" height="118"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;Step 4 — Notifications and Output&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;A file containing the list of inactive users is automatically uploaded to S3&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;An email alert is sent with the same content via SNS&lt;/p&gt;&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%2Fij7wk8kv27t4jrb12w1n.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%2Fij7wk8kv27t4jrb12w1n.PNG" alt="Subscription confirmation request Email" width="800" height="237"&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%2Fceeq59k4aj6s5087z2yy.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%2Fceeq59k4aj6s5087z2yy.PNG" alt="Email showing a list of inactive IAM users" width="800" height="205"&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%2Fswqnf1con0622vrgy4uw.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%2Fswqnf1con0622vrgy4uw.PNG" alt="S3 bucket showing the file" width="800" height="159"&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%2Fu64z6mu63kkp2oim2jut.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%2Fu64z6mu63kkp2oim2jut.PNG" alt="Downloaded file showing inactive users" width="800" height="299"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;p&gt;Here’s the &lt;a href="https://github.com/Ngozi-N/iam-inactive-users-cleanup.git" rel="noopener noreferrer"&gt;Repo on GitHub&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Let’s connect on &lt;a href="http://www.linkedin.com/in/ngozinwadialo" rel="noopener noreferrer"&gt;LinkedIn&lt;/a&gt;!&lt;/p&gt;

</description>
      <category>iam</category>
      <category>terraform</category>
      <category>lambda</category>
      <category>sns</category>
    </item>
    <item>
      <title>Deploying a Dockerized Browser Game with Elastic Beanstalk</title>
      <dc:creator>Ngozi</dc:creator>
      <pubDate>Sun, 15 Jun 2025 18:04:08 +0000</pubDate>
      <link>https://dev.to/ngozi_n/deploying-a-dockerized-browser-game-with-elastic-beanstalk-1aen</link>
      <guid>https://dev.to/ngozi_n/deploying-a-dockerized-browser-game-with-elastic-beanstalk-1aen</guid>
      <description>&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%2Fxye762oo6n44hv2oqe0x.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%2Fxye762oo6n44hv2oqe0x.png" alt="Architectural Diagram" width="601" height="441"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;Introduction&lt;/strong&gt;&lt;br&gt;
I built a simple, colorful browser game using HTML/CSS/JavaScript, containerized it with Docker, and deployed it using AWS Elastic Beanstalk — a service that simplifies deployment for containerized applications.&lt;/p&gt;

&lt;p&gt;This post covers the full process — from writing the game to seeing it live on a public URL.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 1: Building the Game&lt;/strong&gt;&lt;br&gt;
I created a browser game called Color Click. The goal is simple: click as many randomly appearing colorful dots as you can. It’s fast, fun, and great for beginners in frontend or game logic.&lt;/p&gt;

&lt;p&gt;Technologies used:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;HTML, CSS, JavaScript (Frontend)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Nginx (as the static file server)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Docker (to containerize the app)&lt;/p&gt;&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%2Fjokfu5xo5j38ezev210d.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%2Fjokfu5xo5j38ezev210d.PNG" alt="Image Build Complete" width="800" height="242"&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%2Fsdxdie5l5xfvo1oz5m2e.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%2Fsdxdie5l5xfvo1oz5m2e.PNG" alt="Container Running on Port 80" width="800" height="74"&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%2F6j6dzur738erlxdoyg8l.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%2F6j6dzur738erlxdoyg8l.PNG" alt="Game Accessed in Browser via localhost" width="800" height="391"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;Step 2: Version Control with GitHub&lt;/strong&gt;&lt;br&gt;
I initialized a Git repo, committed all files (Dockerfile, HTML, CSS, JS), and pushed the code to GitHub.&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%2Fikrwk7xt864al0d2c8ll.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%2Fikrwk7xt864al0d2c8ll.PNG" alt="Files pushed to GitHub" width="800" height="161"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;Step 3: Deploy to AWS Elastic Beanstalk&lt;/strong&gt;&lt;br&gt;
Elastic Beanstalk allows you to run Docker containers easily without managing infrastructure manually. Here’s what I did:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Zipped the project files (including Dockerfile)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Created a new Elastic Beanstalk app via the AWS Console&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Chose the Docker platform&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Set up:&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Service role&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;EC2 instance profile&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Key pair (for SSH)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Public IP assignment&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Default VPC with public subnet&lt;/p&gt;&lt;/li&gt;
&lt;/ol&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%2F1ht7fh3onk88385wdzrc.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%2F1ht7fh3onk88385wdzrc.PNG" alt="Elastic Beanstalk Environment Successfully Created" width="800" height="314"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;Step 4: Access the Game via the Web&lt;/strong&gt;&lt;br&gt;
After deployment, Elastic Beanstalk assigned a public domain. I simply opened the URL and saw the game running — served via Nginx inside my Docker container on an EC2 instance.&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%2F1ckgxhr7gr0tg90d993q.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%2F1ckgxhr7gr0tg90d993q.PNG" alt="Game Accessed via Elastic Beanstalk Assigned Public Domain URL" width="800" height="407"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;p&gt;Here’s my &lt;a href="https://github.com/Ngozi-N/Color-Click-Game.git" rel="noopener noreferrer"&gt;GitHub Repo&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Let’s Connect on &lt;a href="http://www.linkedin.com/in/ngozinwadialo" rel="noopener noreferrer"&gt;LinkedIn&lt;/a&gt;!&lt;/p&gt;

</description>
      <category>elasticbeanstalk</category>
      <category>docker</category>
      <category>nginx</category>
      <category>gamedev</category>
    </item>
    <item>
      <title>Deploying a Python Microservices App on AWS with EKS, Docker, Helm, and RabbitMQ</title>
      <dc:creator>Ngozi</dc:creator>
      <pubDate>Fri, 13 Jun 2025 14:09:57 +0000</pubDate>
      <link>https://dev.to/ngozi_n/deploying-a-python-microservices-app-on-aws-with-eks-docker-helm-and-rabbitmq-2n3n</link>
      <guid>https://dev.to/ngozi_n/deploying-a-python-microservices-app-on-aws-with-eks-docker-helm-and-rabbitmq-2n3n</guid>
      <description>&lt;p&gt;In this project, I deployed a Python-based microservices application on AWS using a Kubernetes cluster (EKS), Docker for containerization, and Helm for resource management. The end goal of the application is to &lt;strong&gt;convert uploaded video files into MP3 audio format&lt;/strong&gt;, delivering the output back to the user via a notification system.&lt;/p&gt;

&lt;p&gt;The app consists of multiple services such as authentication, file conversion, gateway, and notification — each built and deployed as independent microservices. The project also incorporates MongoDB, PostgreSQL, and RabbitMQ to support key application features like data storage, queue processing, and service communication.&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;1. Setting up the Prerequisites&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Before getting started, I ensured that the following were installed and configured on my local environment:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;AWS CLI &amp;amp; IAM credentials&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;kubectl&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Python&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Docker&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Helm&lt;/p&gt;&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%2Fw7vloanu1wuxy2czikcp.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%2Fw7vloanu1wuxy2czikcp.PNG" alt="Confirm that all needed are installed" width="800" height="266"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;2. Creating the Kubernetes Cluster (EKS)&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;I created an EKS cluster and node group. Once active, I confirmed the nodes (EC2 instances) were up and running.&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%2Fygzimwgxfixfc1dk8z0h.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%2Fygzimwgxfixfc1dk8z0h.PNG" alt="Cluster created and active" width="800" height="341"&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%2Fel9ugjzh6bmm6k8kp3db.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%2Fel9ugjzh6bmm6k8kp3db.PNG" alt="Node group created/Instances running" width="800" height="122"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;3. Connecting EKS Cluster to CLI&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The cluster was then connected to the CLI using aws eks update-kubeconfig, allowing further operations using kubectl.&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;4. Deploying Databases and Message Queue&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The project uses the following backend services:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;MongoDB for the auth service&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;PostgreSQL for token storage&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;RabbitMQ for messaging between services&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;All were deployed using Helm charts.&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%2Fyqgcmv42lxdx2pdy2nby.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%2Fyqgcmv42lxdx2pdy2nby.PNG" alt="MongoDB, PostgreSQL, and RabbitMQ deployed" width="800" height="619"&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%2F60tz67jxztcdxifbcjks.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%2F60tz67jxztcdxifbcjks.PNG" alt="Queues created in RabbitMQ after accessing RabbitMQ via port 30004" width="800" height="282"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;5. Building and Pushing Microservice Images&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Each service — auth, converter, gateway, and notification—was containerized using Docker. Images were pushed to Docker Hub.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;docker build -t your-image-name .&lt;br&gt;
docker push your-image-name&lt;/code&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%2F24ikay5x1pjzwrudzlep.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%2F24ikay5x1pjzwrudzlep.PNG" alt="All 4 images built and pushed to DockerHub" width="800" height="256"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;6. Deploying Microservices with Helm&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;After building the images, I created Helm charts for each microservice and deployed them to the EKS cluster.&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%2Fru0baljdfndfm1hbin2v.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%2Fru0baljdfndfm1hbin2v.PNG" alt="Confirmation of all services running" width="800" height="619"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;7. Verifying Functionality&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Received a token from PostgreSQL&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%2F7l2bcem0zn2sn40rfddn.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%2F7l2bcem0zn2sn40rfddn.PNG" alt="Token from PostgreSQL" width="800" height="84"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Accessed the email notification&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%2Fyz95jb8287e9pdnnjyil.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%2Fyz95jb8287e9pdnnjyil.PNG" alt="Email notification gotten with mp3 file id" width="800" height="180"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Successfully downloaded and played the converted MP3 file&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%2Fpd7gtb30xs809yauldpf.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%2Fpd7gtb30xs809yauldpf.PNG" alt="Converted mp3 downloaded" width="800" height="113"&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%2Fijme023wdyns4h8pz1k0.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%2Fijme023wdyns4h8pz1k0.PNG" alt="Downloaded mp3 playing same sound as in video" width="800" height="414"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;p&gt;This project demonstrates how to deploy a full-fledged Python microservices app with scalable architecture using AWS EKS, Docker, and Helm. It covers essential DevOps workflows and can be a great template for production-grade deployments.&lt;/p&gt;

&lt;p&gt;Here’s the &lt;a href="https://github.com/Ngozi-N/Python-based-Video-Converter-Microservice-Application.git" rel="noopener noreferrer"&gt;Repo on GitHub&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Let’s connect on &lt;a href="http://www.linkedin.com/in/ngozinwadialo" rel="noopener noreferrer"&gt;LinkedIn&lt;/a&gt;!&lt;/p&gt;

</description>
      <category>microservices</category>
      <category>kubernetes</category>
      <category>python</category>
      <category>helm</category>
    </item>
  </channel>
</rss>
