<?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: B.G.Skillz 🧑‍💻</title>
    <description>The latest articles on DEV Community by B.G.Skillz 🧑‍💻 (@hormogbolahan20).</description>
    <link>https://dev.to/hormogbolahan20</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%2F1138052%2Fa18ae0b9-3ef7-444f-9420-115cc67a0c9c.jpg</url>
      <title>DEV Community: B.G.Skillz 🧑‍💻</title>
      <link>https://dev.to/hormogbolahan20</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/hormogbolahan20"/>
    <language>en</language>
    <item>
      <title>[Boost]</title>
      <dc:creator>B.G.Skillz 🧑‍💻</dc:creator>
      <pubDate>Sun, 21 Dec 2025 15:18:47 +0000</pubDate>
      <link>https://dev.to/hormogbolahan20/-39b6</link>
      <guid>https://dev.to/hormogbolahan20/-39b6</guid>
      <description>&lt;div class="ltag__link"&gt;
  &lt;a href="/hormogbolahan20" class="ltag__link__link"&gt;
    &lt;div class="ltag__link__pic"&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%2Fuser%2Fprofile_image%2F1138052%2Fa18ae0b9-3ef7-444f-9420-115cc67a0c9c.jpg" alt="hormogbolahan20"&gt;
    &lt;/div&gt;
  &lt;/a&gt;
  &lt;a href="https://dev.to/hormogbolahan20/dockerizing-a-react-task-a-hands-on-devops-implementation-3kp7" class="ltag__link__link"&gt;
    &lt;div class="ltag__link__content"&gt;
      &lt;h2&gt;Dockerizing a React Task: A Hands-On DevOps Implementation&lt;/h2&gt;
      &lt;h3&gt;B.G.Skillz 🧑‍💻 ・ Dec 20&lt;/h3&gt;
      &lt;div class="ltag__link__taglist"&gt;
        &lt;span class="ltag__link__tag"&gt;#devops&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#react&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#docker&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#containers&lt;/span&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/a&gt;
&lt;/div&gt;


</description>
      <category>devops</category>
      <category>react</category>
      <category>docker</category>
      <category>containers</category>
    </item>
    <item>
      <title>Dockerizing a React Task: A Hands-On DevOps Implementation</title>
      <dc:creator>B.G.Skillz 🧑‍💻</dc:creator>
      <pubDate>Sat, 20 Dec 2025 04:16:30 +0000</pubDate>
      <link>https://dev.to/hormogbolahan20/dockerizing-a-react-task-a-hands-on-devops-implementation-3kp7</link>
      <guid>https://dev.to/hormogbolahan20/dockerizing-a-react-task-a-hands-on-devops-implementation-3kp7</guid>
      <description>&lt;p&gt;In this article, I’ll walk through how I built a Dockerized React Task Manager from scratch, emphasizing real-world DevOps practices like containerization, multi-stage builds, and production-ready deployment.&lt;/p&gt;

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

&lt;p&gt;Build a React-based Task Manager to track tasks in real time.&lt;/p&gt;

&lt;p&gt;Containerize the frontend using Docker and serve it with Nginx.&lt;/p&gt;

&lt;p&gt;Set up a backend API placeholder for future integration.&lt;/p&gt;

&lt;p&gt;Implement multi-container orchestration using Docker Compose.&lt;/p&gt;

&lt;p&gt;This project serves as both a DevOps practice exercise and a production-ready application template.&lt;/p&gt;

&lt;h2&gt;
  
  
  2. File Structure
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;devops-react-task-manager/&lt;br&gt;
├── frontend/&lt;br&gt;
│   ├── Dockerfile&lt;br&gt;
│   ├── nginx.conf&lt;br&gt;
│   ├── package.json&lt;br&gt;
│   └── src/&lt;br&gt;
├── backend/&lt;br&gt;
│   ├── Dockerfile&lt;br&gt;
├── package.json&lt;br&gt;
│   └── app.js&lt;br&gt;
├── docker-compose.yml&lt;br&gt;
├── .env&lt;br&gt;
└── README.md&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%2Fmzt3xkjwfwv9op9hxr3w.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%2Fmzt3xkjwfwv9op9hxr3w.png" alt=" " width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  3. Setting Up the React Environment
&lt;/h2&gt;

&lt;p&gt;I use vite for React&lt;br&gt;
&lt;code&gt;cd frontend&lt;br&gt;
npm create vite@latest . -- --template react&lt;br&gt;
npm install&lt;br&gt;
npm run dev&lt;/code&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%2Ffl8jea3oz140i67yjdq1.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%2Ffl8jea3oz140i67yjdq1.png" alt=" " width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Verified the React app works locally.&lt;/li&gt;
&lt;li&gt;Initially displayed default Vite UI with counter and logos&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  4. Containarized the frontend
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# Build stage
FROM node:20-alpine AS build
WORKDIR /app
COPY package*.json ./
RUN npm install
COPY . .
RUN npm run build

# Production stage
FROM nginx:alpine
COPY nginx.conf /etc/nginx/conf.d/default.conf
COPY --from=build /app/dist /usr/share/nginx/html
EXPOSE 80
CMD ["nginx", "-g", "daemon off;"]

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In the first &lt;code&gt;Dockerfile&lt;/code&gt; I wrote I use &lt;code&gt;node:18&lt;/code&gt; which It doesnt work with &lt;code&gt;vite&lt;/code&gt; during the testing I met with errors before realizing vite doesnt work with version 18 but version 20.&lt;/p&gt;

&lt;h2&gt;
  
  
  5. Docker Compose Setup
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;version: "3.9"

service:
  frontend:
   build: ./frontend
   ports:
   - "3000:80"
   depend_on:
   - backend

  backend:
  build: ./backend
  ports:
  -"5000:5000
  env_file:
  - .env
  network:
  - devops-net

network:
 devops-net:
  driver: bridge
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;frontend:&lt;/code&gt; React app served via Nginx on port 3000.&lt;br&gt;
&lt;code&gt;backend:&lt;/code&gt; Placeholder API for future development.&lt;/p&gt;

&lt;h2&gt;
  
  
  Building Containers
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;docker compose up --build&lt;/code&gt;&lt;br&gt;
TO run in background&lt;br&gt;
&lt;code&gt;docker compose up -d --build&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%2Fuzmndxqd39t4b96z1745.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%2Fuzmndxqd39t4b96z1745.png" alt=" " width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Frontend available at &lt;code&gt;http://localhost:3000&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%2Ft216adtuxn48de6j6czy.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%2Ft216adtuxn48de6j6czy.png" alt=" " width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Backend available at &lt;code&gt;http://localhost:5000&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%2Ffvqdbdfqm7j6bvrof0u5.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%2Ffvqdbdfqm7j6bvrof0u5.png" alt=" " width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  What I understand after the implementation
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Multi-stage Docker builds for optimized production images.&lt;/li&gt;
&lt;li&gt;Node version management: Vite requires Node 20+.&lt;/li&gt;
&lt;li&gt;Frontend-backend orchestration with Docker Compose.&lt;/li&gt;
&lt;li&gt;Nginx for static hosting of React production builds.&lt;/li&gt;
&lt;li&gt;Container networking: frontend calls backend using service names.&lt;/li&gt;
&lt;li&gt;Troubleshooting: identifying build errors and version mismatches.&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>devops</category>
      <category>react</category>
      <category>docker</category>
      <category>containers</category>
    </item>
    <item>
      <title>Docker for Beginners: How I Containerized an Existing Project Node-by-Node</title>
      <dc:creator>B.G.Skillz 🧑‍💻</dc:creator>
      <pubDate>Wed, 10 Dec 2025 23:05:12 +0000</pubDate>
      <link>https://dev.to/hormogbolahan20/docker-for-beginners-how-i-containerized-an-existing-project-node-by-node-f97</link>
      <guid>https://dev.to/hormogbolahan20/docker-for-beginners-how-i-containerized-an-existing-project-node-by-node-f97</guid>
      <description>&lt;h2&gt;
  
  
  INTRODUCTION
&lt;/h2&gt;

&lt;p&gt;The Local Government Report System is a system develop for people in a Local Government to report any activity going in their area in order for the local government representative. &lt;br&gt;
I dockerized this project in order to make because dockerization is important for project to provides conistent and reliale way to deploy applications across different environments.&lt;/p&gt;

&lt;h2&gt;
  
  
  PROJECT OVERVIEW
&lt;/h2&gt;

&lt;p&gt;The Project was cloned from GitHub and the READ.ME was read in order to understand what the projects entails which I learnt that it run in a Virtual environment &lt;code&gt;venv&lt;/code&gt;. And with docker we dont need to set up virtual environment.&lt;/p&gt;

&lt;h2&gt;
  
  
  WORKFLOW OF THE EXISTING PROJECT
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;venv&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;SQLAchemy&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Template/Admin_dashoard.html, base.html, index.html, login.html, manage_user.html, new_complaint.html e.t.c&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  CLONING OF THE GITHUB REPO
&lt;/h2&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%2Fjqon2bepg154sxsm78ys.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%2Fjqon2bepg154sxsm78ys.png" alt=" " width="614" height="163"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This is the image representation of the clone project&lt;/p&gt;

&lt;h2&gt;
  
  
  CREATING A DOCKERFILE FOR THE APPLICATION
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;FROM python:3.11-slim

WORKDIR /app

COPY requirements.txt .

RUN pip install --no-cache-dir -r requirements.txt

COPY . .

EXPOSE 500

CMD ["python", "app.py"]

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  BUILDING DOCKER IMAGE
&lt;/h2&gt;

&lt;p&gt;After the Dockerfile is store with the clone system file that I proceed to create the Image using &lt;code&gt;sudo docker build -t citizen-report&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%2F0em8xdco1l0eimgu4flh.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%2F0em8xdco1l0eimgu4flh.png" alt=" " width="800" height="256"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  RUNNING THE DOCKER CONTAINER
&lt;/h2&gt;

&lt;p&gt;During the running I perform port mapping 8080 with 5000 &lt;code&gt;8080:5000&lt;/code&gt; this allow the application to run in &lt;code&gt;localhost:8080&lt;/code&gt;.&lt;br&gt;
The command used for this is &lt;code&gt;sudo docker run -d -p 8080:5000 --name local-report-container citizen-report&lt;/code&gt;&lt;br&gt;
The command means that I have an image named &lt;code&gt;citizen-report&lt;/code&gt; and run it a container named &lt;code&gt;local-report-container&lt;/code&gt;, making the listen port 8080 and the application is available at 5000.&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%2Fkfvbsruw1o2tymyliddl.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%2Fkfvbsruw1o2tymyliddl.png" alt=" " width="800" height="113"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  OUTPUT OF THE WORK
&lt;/h2&gt;

&lt;p&gt;The application is running in &lt;code&gt;http//localhost:8080&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%2Fsz4r048sph874ccb8u96.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%2Fsz4r048sph874ccb8u96.png" alt=" " width="800" height="354"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Common Error Fixed in the project
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Syntax error in the &lt;code&gt;Dockerfile&lt;/code&gt; some --, " and others&lt;/li&gt;
&lt;li&gt;Wrong Port, Missing requirement.txt et.c&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;TO Detect were the error are comming from run &lt;code&gt;sudo docker log &amp;lt;image-name&amp;gt;&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;THANKS FOR YOUR TIME&lt;/p&gt;

&lt;p&gt;STAY TUNED FOR MORE ARTICLE ON DOCKER UP NEXT &lt;code&gt;Docker Compose, CI/CD&lt;/code&gt;&lt;/p&gt;

</description>
      <category>devops</category>
      <category>docker</category>
      <category>containers</category>
    </item>
    <item>
      <title>Design and Deploy a Static Website with AWS S3 and CloudFront</title>
      <dc:creator>B.G.Skillz 🧑‍💻</dc:creator>
      <pubDate>Sat, 08 Mar 2025 13:29:26 +0000</pubDate>
      <link>https://dev.to/hormogbolahan20/design-and-deploy-a-static-website-with-aws-s3-and-cloudfront-10l4</link>
      <guid>https://dev.to/hormogbolahan20/design-and-deploy-a-static-website-with-aws-s3-and-cloudfront-10l4</guid>
      <description>&lt;p&gt;&lt;strong&gt;INTRODUCTION&lt;/strong&gt;&lt;br&gt;
In today's fast-paced digital landscape, businesses require websites that are fast, scalable, and globally accessible. AWS (Amazon Web Services) provides an excellent solution using Amazon S3 (Simple Storage Service) for static content hosting and Amazon CloudFront (Content Delivery Network) for optimized global delivery. This blog explores how to design and deploy a static website using AWS S3 and CloudFront. AWS S3 and CloudFront.&lt;/p&gt;

&lt;p&gt;Let begin with little explain on Amazon S3 and Amazon CloudFront&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What is AWS S3&lt;/strong&gt;&lt;br&gt;
Amazon S3 is an object storage service that offers industry-leading scalability, data availability, security, and performance. You can use Amazon S3 to store and retrieve any amount of data at any time, from anywhere.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What is AWS CloudFront&lt;/strong&gt;&lt;br&gt;
Amazon CloudFront is a content delivery network (CDN) service that helps you distribute your static and dynamic content quickly and reliably with high speed.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;SCENARIO for the Task&lt;/strong&gt;&lt;br&gt;
A local business needed a cost-effective, highly available, and globally accessible website to showcase its services. Instead of using traditional web hosting, AWS S3 and CloudFront provided an efficient and scalable solution. This setup ensures:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Low latency due to caching at CloudFront edge locations.&lt;/li&gt;
&lt;li&gt;High availability with S3 storage redundancy.&lt;/li&gt;
&lt;li&gt;Cost efficiency by paying only for what is used.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Architecture Overview&lt;/strong&gt;&lt;br&gt;
The Architecture shows how the Static Website is design and deploy for users in order to access it. During the deployment of the static website the CloudFront was unable to access due to internal issue on Amazon Web Service.&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%2Ftgbmrq8avflau9zs14yg.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%2Ftgbmrq8avflau9zs14yg.png" alt="Image description" width="800" height="293"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Steps to Deploy a Static Website on AWS S3 &amp;amp; CloudFront&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1. Create an S3 Bucket&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Log in to AWS Console and navigate to S3.&lt;/li&gt;
&lt;li&gt;Create a new bucket and name it (e.g., s3-cloudfront-static-site).&lt;/li&gt;
&lt;li&gt;Disable Block Public Access (if not using CloudFront OAC).&lt;/li&gt;
&lt;li&gt;Enable Static Website Hosting and specify index.html as the default document.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;2. Upload Website Files&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Upload index.html, style.css, script.js, and other necessary files.&lt;/li&gt;
&lt;li&gt;Ensure the files are in the root directory (not inside a subfolder).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;3. Configure Bucket Policy for CloudFront&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;To ensure secure access via CloudFront, update the bucket policy:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Principal": "*",
            "Action": "s3:GetObject",
            "Resource": "arn:aws:s3:::s3-cloudfront-static-site/*"
        }
    ]
}

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;** 4. Create a CloudFront Distribution **&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Navigate to CloudFront in AWS.&lt;/li&gt;
&lt;li&gt;Click Create Distribution and set S3 bucket as the origin.&lt;/li&gt;
&lt;li&gt;Enable Origin Access Control (OAC) for security.&lt;/li&gt;
&lt;li&gt;Configure caching settings and save the distribution.&lt;/li&gt;
&lt;li&gt;Copy the CloudFront Domain Name (e.g., &lt;a href="https://d123abc.cloudfront.net" rel="noopener noreferrer"&gt;https://d123abc.cloudfront.net&lt;/a&gt;).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Testing the Deployment&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;To test the deployment:&lt;/li&gt;
&lt;li&gt;Open the CloudFront URL in your browser.&lt;/li&gt;
&lt;li&gt;Check if the index.html page loads correctly.&lt;/li&gt;
&lt;li&gt;Ensure CloudFront caching is working by monitoring load speeds.&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%2Fuaajrjby48kdy301ooi6.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%2Fuaajrjby48kdy301ooi6.png" alt="Image description" width="800" height="398"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The Deployed site is working perfectly &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Benefits of Using AWS S3 &amp;amp; CloudFront&lt;/strong&gt;&lt;br&gt;
✅ Fast global delivery using CloudFront edge locations.&lt;br&gt;
✅ Highly scalable with automatic redundancy.&lt;br&gt;
✅ Secure access using OAC and S3 policies.&lt;br&gt;
✅ Cost-effective with pay-as-you-go pricing.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Conclusion&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Deploying a static website with AWS S3 and CloudFront is an efficient and scalable way to host websites. It ensures fast content delivery, security, and high availability. By following this approach, businesses can provide an optimal user experience with minimal operational costs.&lt;/p&gt;

&lt;p&gt;🚀 Next Steps: Try deploying your own static website using AWS and optimize it further with Route 53 for custom domains!&lt;/p&gt;

</description>
      <category>devops</category>
      <category>cloudcomputing</category>
      <category>cloud</category>
      <category>webdev</category>
    </item>
    <item>
      <title>AUTOMATING USER CREATION AND MANAGEMENT WITH BASH USING REPLIT</title>
      <dc:creator>B.G.Skillz 🧑‍💻</dc:creator>
      <pubDate>Mon, 24 Feb 2025 16:52:06 +0000</pubDate>
      <link>https://dev.to/hormogbolahan20/automating-user-creation-and-management-with-bash-using-replit-271</link>
      <guid>https://dev.to/hormogbolahan20/automating-user-creation-and-management-with-bash-using-replit-271</guid>
      <description>&lt;p&gt;&lt;strong&gt;What is the Purposes of this Task&lt;/strong&gt;&lt;br&gt;
Creating of User and adding them to group manually and setting the permission one by one, will take a lot time. Bash Script can do the task automatically. This is useful in companies.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Scenario for the Task&lt;/strong&gt;&lt;br&gt;
Assuming I am working with TechNova Corp, and the company recruit a new set of employees. The IT department is resposible for creating the Linux Accounts and setting up Access permissions. Instead of Typing commands for each user.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;How the Script will work&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Creating Random Username: The script will help to create Username name randomly after the First_Name and the Last_Name has been declared and initialized with values
&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;#!/bin/bash
# Define First and Last Names
First_Names=("Bolarinwa" "Ayinla" "Ayoade" "Ajibade" "Lawal" "Oseni" "Adeyemi" "Adeyinka" "Adeyinka")
Last_Names=("Gbolahan" "Moses" "Ayobami" "Mayowa" "Ademola" "Sodiq" "Opeyemi" "Adebayo" "Tunde")
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;The base directory was also set &lt;code&gt;BASE_DIR="/home/dept"&lt;br&gt;
sudo mkdir -p "$BASE_DIR"&lt;/code&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Define User Groups: There are 6 department which include &lt;code&gt;Departments=("Sales" "Marketing" "Finance" "HR" "IT" "Legal")&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Create Users and Assign Them to Groups&lt;/strong&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;ul&gt;
&lt;li&gt;The &lt;code&gt;useradd&lt;/code&gt; command was used to create new Linux Users from the name initialized above and also assign them to their department group&lt;/li&gt;
&lt;/ul&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Setting permission for Department Folders&lt;/strong&gt;
Each department have different folders &lt;/li&gt;
&lt;/ol&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;/dept/Sales&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;/dept/Marketing&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;/dept/Finance&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;/dept/HR&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;/dept/IT&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;/dept/Legal&lt;br&gt;
Users are only allow to access their department folder they cant access another Department folder&lt;br&gt;
&lt;code&gt;chown&lt;/code&gt; and &lt;code&gt;chmod&lt;/code&gt; was used  for the access control&lt;br&gt;
&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# Create department directories with appropriate permissions
for dept in "${Departments[@]}"; do
    sudo mkdir -p "$BASE_DIR/$dept"
    sudo chmod 770 "$BASE_DIR/$dept"  # 770 allows only the owner and group to access
    sudo chown root:root "$BASE_DIR/$dept"
done
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;ol&gt;
&lt;li&gt;Generating a Summary Report of all created users, their groups and access permissions&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%2Fyiduf4bwdrubu60cppjn.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%2Fyiduf4bwdrubu60cppjn.png" alt="Image description" width="694" height="507"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Below is the full script&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;#!/bin/bash

# Define First and Last Names
First_Names=("Bolarinwa" "Ayinla" "Ayoade" "Ajibade" "Lawal" "Oseni" "Adeyemi" "Adeyinka" "Adeyinka")
Last_Names=("Gbolahan" "Moses" "Ayobami" "Mayowa" "Ademola" "Sodiq" "Opeyemi" "Adebayo" "Tunde")

# Define Departments
Departments=("Sales" "Marketing" "Finance" "HR" "IT" "Legal")

# Set base directory (changed from /dept to /home/dept)
BASE_DIR="/home/dept"
sudo mkdir -p "$BASE_DIR"

# Create department directories with appropriate permissions
for dept in "${Departments[@]}"; do
    sudo mkdir -p "$BASE_DIR/$dept"
    sudo chmod 770 "$BASE_DIR/$dept"  # 770 allows only the owner and group to access
    sudo chown root:root "$BASE_DIR/$dept"
done

# Number of users to create
NUM_USERS=9

# Create a report file
REPORT_FILE="user_report.txt"
echo "Username | Group | Password" &amp;gt; "$REPORT_FILE"
echo "--------------------------" &amp;gt;&amp;gt; "$REPORT_FILE"

# Create users and assign to departments
for ((i=0; i&amp;lt;$NUM_USERS; i++)); do
    FIRST="${First_Names[$RANDOM % ${#First_Names[@]}]}"
    LAST="${Last_Names[$RANDOM % ${#Last_Names[@]}]}"
    USERNAME="$(echo "$FIRST.$LAST" | tr '[:upper:]' '[:lower:]')"

    PASSWORD=$(openssl rand -base64 8)
    DEPT="${Departments[$RANDOM % ${#Departments[@]}]}"

    # Ensure the department group exists
    sudo groupadd -f "$DEPT"

    # Create user with home directory
    sudo useradd -m -s /bin/bash "$USERNAME"

    # Set user password
    echo "$USERNAME:$PASSWORD" | sudo chpasswd

    # Assign user to department group
    sudo usermod -aG "$DEPT" "$USERNAME"

    # Set correct ownership and permissions for department folder
    sudo chown root:"$DEPT" "$BASE_DIR/$DEPT"
    sudo chmod 770 "$BASE_DIR/$DEPT"

    echo "$USERNAME | $DEPT | $PASSWORD" &amp;gt;&amp;gt; "$REPORT_FILE"
    echo "User $USERNAME created and assigned to $DEPT department"
done

echo "User creation complete. Check $REPORT_FILE for details."

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



</description>
      <category>devops</category>
      <category>programming</category>
    </item>
    <item>
      <title>Deploying a FastAPI Application with CI/CD Pipeline: HNG Task 2</title>
      <dc:creator>B.G.Skillz 🧑‍💻</dc:creator>
      <pubDate>Sat, 15 Feb 2025 11:00:58 +0000</pubDate>
      <link>https://dev.to/hormogbolahan20/deploying-a-fastapi-application-with-cicd-pipeline-hng-task-2-2igi</link>
      <guid>https://dev.to/hormogbolahan20/deploying-a-fastapi-application-with-cicd-pipeline-hng-task-2-2igi</guid>
      <description>&lt;p&gt;&lt;strong&gt;Introduction&lt;/strong&gt;&lt;br&gt;
In this article, I will explain how I deployed a FASTAPI application with continuous Integration (CI) and Continuous deployment (CD).&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Tools Requirements&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Python&lt;/li&gt;
&lt;li&gt;Docker&lt;/li&gt;
&lt;li&gt;GitHub Actions Secrets e.g SSH_HOST, SSH_PRIVATE_KEY&lt;/li&gt;
&lt;li&gt;AWS Linux Server&lt;/li&gt;
&lt;li&gt;Nginx&lt;/li&gt;
&lt;li&gt;FastAPI Application&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;First Step: Fork and Clone the Repository&lt;/strong&gt;&lt;br&gt;
The first step is to fock the repo and clone the repository to your local device&lt;br&gt;
&lt;code&gt;git clone https:/github.com/hng12-devbotops/fastapi-book-project.git&lt;/code&gt;&lt;br&gt;
Then you navigate to your repo after clone it&lt;br&gt;
&lt;code&gt;cd fastapi-book-project/&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Second Step: Setting Up a Virtual Environment&lt;/strong&gt;&lt;br&gt;
Testing the application locally before deploying, using a virtual environment is good for Python dependencies. And to achieve this you need to create and and activate a virtual environment.&lt;br&gt;
&lt;code&gt;python3 -m venv hng&lt;/code&gt;&lt;br&gt;
&lt;code&gt;source hng/bin/activate&lt;/code&gt;&lt;br&gt;
And connecting to virtual environment I then install the required dependency using the following command.&lt;br&gt;
&lt;code&gt;pip install -r requirements.txt&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Third Step: Implementing the Missing Endpoing in book.py&lt;/strong&gt;&lt;br&gt;
The API is currently unable to fetch book using its ID. In this step, I added a new endpoing to the FASTAPI router that handles a GET request to retrieve a book based on provided ID.&lt;br&gt;
So I updated the missing endpoint by add this code to book.py file&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;@router.get("/{book_id}", response_model=Book, status_code=status.HTTP_200_OK)  # New endpoint
async def get_book(book_id: int):
    book = db.books.get(book_id)
    if not book:
        raise HTTPException(
            status_code=status.HTTP_404_NOT_FOUND, 
            detail="Book not found"
        )
    return book
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And also the HTTPException was imported from fastapi&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Forth Step: Testing the Endpoint to check if it working perfectly&lt;/strong&gt;&lt;br&gt;
Once I finish implementing the endpoint, it's important to test it to ensure it working perfectly as expected, So I confirm using &lt;code&gt;pytest&lt;/code&gt; commmand&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%2Fla9uezisqix1w25hyla8.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%2Fla9uezisqix1w25hyla8.png" alt="Image description" width="800" height="83"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;After this I start the FASTAPI application using Uvicorn &lt;code&gt;uvicorn main:app --reload&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
  "1": {
    "id": 1,
    "title": "The Hobbit",
    "author": "J.R.R. Tolkien",
    "publication_year": 1937,
    "genre": "Science Fiction"
  },
  "2": {
    "id": 2,
    "title": "The Lord of the Rings",
    "author": "J.R.R. Tolkien",
    "publication_year": 1954,
    "genre": "Fantasy"
  },
  "3": {
    "id": 3,
    "title": "The Return of the King",
    "author": "J.R.R. Tolkien",
    "publication_year": 1955,
    "genre": "Fantasy"
  }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The application seem to be running fine on the localhost&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Fifth Test: Dockerizing the APP&lt;/strong&gt;&lt;br&gt;
create a Dockerfile in the project directory&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# Use an official lightweight Python image
FROM python:3.9-slim

# Set work directory
WORKDIR /app

# Install dependencies
COPY requirements.txt .
RUN pip install --upgrade pip
RUN pip install -r requirements.txt

# Copy project files
COPY . .

# Expose the port FastAPI runs on
EXPOSE 8000

# Run the FastAPI application using Uvicorn
CMD ["uvicorn", "main:app", "--host", "0.0.0.0", "--port", "8000"]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Sixth Step: Nginx Integrating&lt;/strong&gt;&lt;br&gt;
To make things easier for me, I used a &lt;code&gt;docker-compose.ym&lt;/code&gt;l file to configure Nginx as a reverse proxy. To do this I created an &lt;code&gt;nginx.conf&lt;/code&gt; file with the configurations for my application. The purpose of this configuration is to have Nginx listen on port 80 and forward incoming HTTP requests to the FastAPI application running on port 8000 inside its container.&lt;br&gt;
nginx.conf&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;server {
    listen 80;
    server_name your_domain_or_IP;
    location / {
        proxy_pass http://app:8000;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For 
        $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then processed to the &lt;code&gt;docker-compose.yml&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;version: '3.8'
services:
  app:
    build: .
    container_name: fastapi-app
    ports:
      - "8000:8000"

  nginx:
    image: nginx:latest
    container_name: fastapi-nginx
    volumes:
      - ./nginx.conf:/etc/nginx/conf.d/default.conf
    ports:
      - "80:80"
    depends_on:
      - app
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;The app service builds and runs our FastAPI application.&lt;/li&gt;
&lt;li&gt;The Nginx service uses an Nginx image, mounts the custom configuration file, and maps port 80 of the container to port 80 on the host.&lt;/li&gt;
&lt;li&gt;The depends_on command ensures that the FastAPI container starts before Nginx.&lt;/li&gt;
&lt;li&gt;Then I used this command to build the containers
&lt;code&gt;docker-compose up --build&lt;/code&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%2Fuon3cnr1bw2myf6hbmjj.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%2Fuon3cnr1bw2myf6hbmjj.png" alt="Image description" width="800" height="276"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Seventh Step: Creating a Linux Server&lt;/strong&gt;&lt;br&gt;
For hosting and deploying our FastAPI application, I set up a Linux server on AWS. This server serves as the backbone of our deployment environment, where our Dockerized application will run and be accessible to users.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Eighth Step: Set Up the CI/CD Pipeline&lt;/strong&gt;&lt;br&gt;
I created a GitHub Actions Workflow File for this step to automatically run tests on every pull request targeting the main branch. This ensures that any new changes are validated before they can be merged.&lt;br&gt;
&lt;code&gt;mkdir -p .github/workflows/&lt;/code&gt;&lt;br&gt;
&lt;code&gt;cd .github/workflows/&lt;/code&gt;&lt;br&gt;
&lt;code&gt;nano test.yml&lt;/code&gt;&lt;br&gt;
After the necessary details needed has been input and I close using &lt;code&gt;Ctrl X then press Y and Enter&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;name: ci pipeline

on:
  pull_request:
    branches: [ main ]

jobs:
  test:
    runs-on: ubuntu-latest
    steps:
    - uses: actions/checkout@v2
    - name: Set up Python
      uses: actions/setup-python@v2
      with:
        python-version: '3.9'
    - name: Install dependencies
      run: |
        python -m pip install --upgrade pip
        pip install -r requirements.txt
    - name: Run tests
      run: pytest
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Then follow by the CD Pipeline/Deployment Pipeline&lt;/strong&gt;&lt;br&gt;
For continuous deployment, I created another GitHub Actions Workflow File named &lt;code&gt;deploy.yml&lt;/code&gt;. This deployment pipeline is triggered whenever changes are pushed to the main branch, automating the process of updating the live application.&lt;br&gt;
&lt;code&gt;nano deploy.yml&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;name: CD Pipeline
on:
  push:
    branches: [main]
jobs:
  deploy:
    runs-on: ubuntu-latest
    steps:
      - name: Checkout repository
        uses: actions/checkout@v3

      - name: Deploy via SSH
        uses: appleboy/ssh-action@master
        with:
          host: ${{ secrets.SSH_HOST }}
          username: ${{ secrets.SSH_USERNAME }}
          key: ${{ secrets.SSH_PRIVATE_KEY }}
          script: |
            # Update package index and install dependencies
            sudo apt-get update -y
            sudo apt-get install -y apt-transport-https ca-certificates curl software-properties-common

            # Add Docker's official GPG key
            curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add -
            sudo add-apt-repository "deb [arch=amd64] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable"

            # Install Docker
            sudo apt-get update -y
            sudo apt-get install -y docker-ce docker-ce-cli containerd.io

            # Add the SSH user to the Docker group
            sudo usermod -aG docker ${{ secrets.SSH_USERNAME }}

            # Install Docker Compose
            sudo curl -L "https://github.com/docker/compose/releases/download/v2.20.2/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose
            sudo chmod +x /usr/local/bin/docker-compose

            # Verify installations
            docker --version
            docker-compose --version

            # Navigate to the project directory and deploy
            cd /home/ubuntu/
            git clone &amp;lt;your-github-repo&amp;gt;
            cd fastapi-book-project/
            git pull
            docker-compose up -d --build
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;After pushing the file &lt;code&gt;git add. deploy.yml test.yml&lt;/code&gt; and Check the status of the Pipeline they are working perfectly&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%2F4c2pjby5ghshe54bb055.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%2F4c2pjby5ghshe54bb055.png" alt="Image description" width="800" height="186"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;After that  the Post-Deployment Verification the pipeline are working perfectly&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%2Fl2fu5vib2zlrpphdqwbf.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%2Fl2fu5vib2zlrpphdqwbf.png" alt="Image description" width="800" height="371"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Thanks for reading, don't forget to drop a like and comment&lt;/p&gt;

&lt;p&gt;LOVE YOU&lt;/p&gt;

</description>
      <category>devops</category>
      <category>cicd</category>
      <category>docker</category>
    </item>
    <item>
      <title>Building a Number Classification API with AWS Lambda &amp; API Gateway</title>
      <dc:creator>B.G.Skillz 🧑‍💻</dc:creator>
      <pubDate>Sat, 08 Feb 2025 19:42:46 +0000</pubDate>
      <link>https://dev.to/hormogbolahan20/building-a-number-classification-api-with-aws-lambda-api-gateway-459n</link>
      <guid>https://dev.to/hormogbolahan20/building-a-number-classification-api-with-aws-lambda-api-gateway-459n</guid>
      <description>&lt;p&gt;&lt;strong&gt;Introduction&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;In the world of DevOps, deploying a scalable and serverless API is a valuable skill. This blog post walks you through building a Number Classification API using AWS Lambda, API Gateway, and Python. The API takes a number as input and returns its mathematical properties along with a fun fact.&lt;/p&gt;

&lt;p&gt;I have used Local Machine to perform the task but I am having issue with the Deployment. After making many attempt to use the local machine it doesnt work out. I decided to use AWS Lamba and import my code to the code editor&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;CREATING OF THE FUNCTION&lt;/strong&gt;&lt;br&gt;
I navigate to my Console home and search for Lambda then select and create a function &lt;em&gt;number-classifcation-api&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;WHY I CHOOSE LAMBA&lt;/strong&gt;&lt;br&gt;
I chose AWS Lambda because it is serverless—meaning I don't need to manage servers. AWS automatically provisions the infrastructure, executes the code, and shuts down after execution, making it highly cost-effective since I'm only billed when the function runs.&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%2Fwvlw9mjqsaxxg6y8grvs.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%2Fwvlw9mjqsaxxg6y8grvs.png" alt="Image description" width="800" height="370"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;After create the function I import my code&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import json
import math
import urllib.request
def is_prime(n):
    if n &amp;lt; 2:
        return False
    if n in (2, 3):
        return True
    if n % 2 == 0 or n % 3 == 0:
        return False
    for i in range(5, int(math.sqrt(n)) + 1, 2):
        if n % i == 0:
            return False
    return True
def is_armstrong(n):
    if n &amp;lt; 0:
        return False
    digits = [int(digit) for digit in str(n)]
    power = len(digits)
    return sum(digit ** power for digit in digits) == n
def is_perfect(n):
    if n &amp;lt; 1:
        return False
    return sum(i for i in range(1, n // 2 + 1) if n % i == 0) == n

def get_fun_fact(n):
    if n &amp;lt; 0:
        return "Fun fact not available for negative numbers."
    try:
        url = f"http://numbersapi.com/{n}/math"
        with urllib.request.urlopen(url, timeout=5) as response:
            return response.read().decode("utf-8")
    except Exception:
        return "Fun fact not available."
def lambda_handler(event, context):
    query_params = event.get("queryStringParameters", {})
    number_str = query_params.get("number") if query_params else None

    if not number_str:
        return {
            "statusCode": 400,
            "headers": {
                "Access-Control-Allow-Origin": "*",
                "Access-Control-Allow-Methods": "GET",
                "Access-Control-Allow-Headers": "Content-Type"
            },
            "body": json.dumps({"error": "No number provided."})
        }

    try:
        number = int(float(number_str))
    except ValueError:
        return {
            "statusCode": 400,
            "headers": {
                "Access-Control-Allow-Origin": "*",
                "Access-Control-Allow-Methods": "GET",
                "Access-Control-Allow-Headers": "Content-Type"
            },
            "body": json.dumps({
                "error": "Invalid number format",
                "invalid_input": number_str  # Include the invalid input in the response
            })
        }

    properties = ["odd" if number % 2 else "even"]
    if is_armstrong(number):
        properties.insert(0, "armstrong")

    response_body = {
        "number": number,
        "is_prime": is_prime(number),
        "is_perfect": is_perfect(number),
        "properties": properties,
        "digit_sum": sum(int(d) for d in str(abs(number))),
        "fun_fact": get_fun_fact(number)
    }

    return {
        "statusCode": 200,
        "headers": {
            "Access-Control-Allow-Origin": "*",
            "Access-Control-Allow-Methods": "GET",
            "Access-Control-Allow-Headers": "Content-Type"
        },
        "body": json.dumps(response_body)
    }

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;After importing the code I test the code before deploying it was working&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%2F8ch29tig4p5s3e01ra6e.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%2F8ch29tig4p5s3e01ra6e.png" alt="Image description" width="800" height="301"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  How the API Works
&lt;/h1&gt;

&lt;p&gt;The API is designed to classify a number based on its properties and return some interesting facts. The flow works as follows:&lt;/p&gt;

&lt;p&gt;A user requests the API&lt;br&gt;
The API Gateway forwards the request to AWS Lambda&lt;br&gt;
AWS Lambda processes the request and generates a response&lt;br&gt;
The API Gateway sends the response back to the user&lt;/p&gt;

&lt;h1&gt;
  
  
  Setting Up API Gateway
&lt;/h1&gt;

&lt;ul&gt;
&lt;li&gt;Go to AWS API Gateway → Create API&lt;/li&gt;
&lt;li&gt;Choose REST API → New API&lt;/li&gt;
&lt;li&gt;Set Endpoint as Lambda Function&lt;/li&gt;
&lt;li&gt;Define Resource Path /api/classify-number&lt;/li&gt;
&lt;li&gt;Enable CORS (for cross-origin requests)&lt;/li&gt;
&lt;li&gt;Deploy the API to a stage (prod)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;After that I navigate to the &lt;code&gt;APIGateway&lt;/code&gt; to create the API and named it &lt;code&gt;NumberClassificationAPI&lt;/code&gt; then use GET to create the path &lt;code&gt;/api/classfiy-api&lt;/code&gt; and I deploy the stage using (prod) and I enable CORS then I deploy it.&lt;br&gt;
(&lt;a href="https://nr7acfudff.execute-api.us-east-1.amazonaws.com/prod/api/classify-number?number=371" rel="noopener noreferrer"&gt;https://nr7acfudff.execute-api.us-east-1.amazonaws.com/prod/api/classify-number?number=371&lt;/a&gt;)&lt;/p&gt;

&lt;p&gt;(&lt;a href="https://github.com/Bolarinwa2030/Lambda_function/tree/main" rel="noopener noreferrer"&gt;https://github.com/Bolarinwa2030/Lambda_function/tree/main&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%2Fn1vb1yokz8uer9v35fie.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%2Fn1vb1yokz8uer9v35fie.png" alt="Image description" width="800" height="377"&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%2Fvifnd41i2mrbmhdf1ydf.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%2Fvifnd41i2mrbmhdf1ydf.png" alt="Image description" width="800" height="307"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This is output&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Setting Up an NGINX Web Server on Azure and Local Machine: My DevOps Stage 0 Experience</title>
      <dc:creator>B.G.Skillz 🧑‍💻</dc:creator>
      <pubDate>Sun, 02 Feb 2025 13:05:03 +0000</pubDate>
      <link>https://dev.to/hormogbolahan20/setting-up-an-nginx-web-server-on-azure-and-local-machine-my-devops-stage-0-experience-1ipo</link>
      <guid>https://dev.to/hormogbolahan20/setting-up-an-nginx-web-server-on-azure-and-local-machine-my-devops-stage-0-experience-1ipo</guid>
      <description>&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;As part of my DevOps Stage 0 Intership, I was tasked with setting up and configuring &lt;strong&gt;NGINX&lt;/strong&gt; on a fresh Ubuntu Server. This Challenge aimed to test my ability to install and configure a web server while demonstrating and understanding of basic System Administration. In this blog, I document my approach, the challenges I faced and the lessons learned from the Task.&lt;br&gt;
&lt;strong&gt;Approach to Completing the Task&lt;/strong&gt;&lt;br&gt;
For me to successfully configure &lt;strong&gt;NGINX&lt;/strong&gt;, I followed a structured approach:&lt;br&gt;
I register as a new user on Azure so that I will be able to access the Cloud Infrastructure and create a new/fresh Ubuntu Server.&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%2Fm38zn0zp5435ojfr5xne.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%2Fm38zn0zp5435ojfr5xne.png" alt="Image description" width="800" height="426"&gt;&lt;/a&gt;&lt;br&gt;
After Create a new/fresh Ubuntu Server and selected all the necessary things I need to make the server work better.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Preparing the Server&lt;/strong&gt;&lt;br&gt;
I used &lt;strong&gt;MobaXterm&lt;/strong&gt; to connect to the Server using IP address, my Admin Username and the Password I set. Before installing NGINX, I updated my server to ensure all system packages were current&lt;br&gt;
&lt;code&gt;sudo apt update &amp;amp;&amp;amp; sudo apt upgrade -y&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Installing NGINX&lt;/strong&gt;&lt;br&gt;
I installed NGINX using:&lt;br&gt;
&lt;code&gt;sudo apt install nginx -y&lt;/code&gt;&lt;br&gt;
After the installation, I check to know if NGINX is running using command &lt;code&gt;sudo systemctl status nginx&lt;/code&gt; it shows&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%2Fu0x05ei3cx1dlc7tq5qw.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%2Fu0x05ei3cx1dlc7tq5qw.png" alt="Image description" width="800" height="422"&gt;&lt;/a&gt;&lt;br&gt;
It shows Active and Running and I enable and start nginx using &lt;code&gt;sudo systemctl enable nginx sudo systemctl start nginx&lt;/code&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Configuring Default Page&lt;/strong&gt;&lt;br&gt;
I then customized the default web page by modifying the index.html file located at at /var/www/html/index.html. Using the nano text editor, I added the required message needed. &lt;code&gt;sudo nano /var/www/html/index.html&lt;/code&gt; and I replaced the content in it with &lt;br&gt;
`&lt;br&gt;
&lt;/p&gt;

&lt;p&gt;&lt;br&gt;&lt;br&gt;
Welcome to HNG DevOps Internship &lt;br&gt;&lt;/p&gt;

&lt;h1&gt; Welcome to DevOps Stage 0- Bolarinwa Gbolahan/Bolarinwa&lt;/h1&gt;

&lt;p&gt;&lt;br&gt;
&lt;br&gt;
&lt;code&gt;&lt;br&gt;
After writing the code I save with Ctrl X then Y and Press Enter. I restart the NGINX using command &lt;/code&gt;sudo systemctl restart nginx`.&lt;/p&gt;


&lt;/li&gt;

&lt;li&gt;&lt;p&gt;&lt;strong&gt;Verifying the Configuration&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
I check if everything was working correctly, I tested the setup in a web browser by using my IP address and it works perfectly both on Local Machine and Azure Ubuntu Server&lt;/p&gt;&lt;/li&gt;

&lt;/ul&gt;

&lt;h1&gt;
  
  
  Challenges Faces and How I Overcame them
&lt;/h1&gt;

&lt;ol&gt;
&lt;li&gt;NGNIX Not starting after installation 
I encountered an issue where NGINX wouldn't start. Checking the service status with &lt;code&gt;sudo netstat -tulnp | grep :80&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Firewall Blocking HTTP Requests
After configuring NGINX, I realized my webpage wasn't accessible from a web browser. So I troubleshoot this by &lt;code&gt;sudo ufw status&lt;/code&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;h1&gt;
  
  
  How this task contribute to my DevOps Learning
&lt;/h1&gt;

&lt;p&gt;The task reinforced my understanding of Ubuntu System Administration, Web Server, NGINX Server, and networking.&lt;/p&gt;

&lt;h1&gt;
  
  
  References
&lt;/h1&gt;

&lt;p&gt;&lt;a href="https://hng.tech/hire/devops-engineers" rel="noopener noreferrer"&gt;DevOps Engineer&lt;/a&gt;&lt;br&gt;
&lt;a href="https://hng.tech/hire/cloud-engineers" rel="noopener noreferrer"&gt;Cloud Engineers&lt;/a&gt;&lt;br&gt;
&lt;a href="https://hng.tech/hire/platform-engineers" rel="noopener noreferrer"&gt;Platform Engineers&lt;/a&gt;&lt;/p&gt;

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