<?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: Joseph Ibeh</title>
    <description>The latest articles on DEV Community by Joseph Ibeh (@sir-j).</description>
    <link>https://dev.to/sir-j</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%2F1975529%2Fc6ac0540-1dd7-4c5c-b673-8ceb0d96851f.png</url>
      <title>DEV Community: Joseph Ibeh</title>
      <link>https://dev.to/sir-j</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/sir-j"/>
    <language>en</language>
    <item>
      <title>Terraform Commands Every Cloud Engineer Should Know</title>
      <dc:creator>Joseph Ibeh</dc:creator>
      <pubDate>Tue, 22 Apr 2025 07:18:10 +0000</pubDate>
      <link>https://dev.to/sir-j/terraform-commands-every-cloud-engineer-should-know-6of</link>
      <guid>https://dev.to/sir-j/terraform-commands-every-cloud-engineer-should-know-6of</guid>
      <description>&lt;p&gt;Infrastructure as Code (IaC) has revolutionized the way cloud environments are managed, and &lt;strong&gt;Terraform&lt;/strong&gt; stands out as one of the most popular IaC tools today. Whether you're provisioning compute resources, managing storage, or automating networking setups, Terraform provides a consistent and powerful CLI experience.&lt;/p&gt;

&lt;p&gt;In this article, I'll walk you through &lt;strong&gt;essential Terraform commands every Cloud Engineer should know&lt;/strong&gt;—especially if you're just getting started or want a solid foundation for managing infrastructure efficiently.&lt;/p&gt;




&lt;h2&gt;
  
  
  1. &lt;code&gt;terraform init&lt;/code&gt;
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;terraform init
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is the &lt;strong&gt;first command&lt;/strong&gt; you run when starting a new Terraform configuration. It initializes the working directory, downloads the required provider plugins, and prepares your project for further actions.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Use it when&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;You clone a new Terraform repo&lt;/li&gt;
&lt;li&gt;You add/change providers&lt;/li&gt;
&lt;li&gt;You're setting up a new module&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  2. &lt;code&gt;terraform validate&lt;/code&gt;
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;terraform validate
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This command checks your configuration files for syntax errors and ensures they're internally consistent.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Think of it as your syntax checker.&lt;/strong&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  3. &lt;code&gt;terraform plan&lt;/code&gt;
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;terraform plan
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is your &lt;strong&gt;preview command&lt;/strong&gt;. It shows what actions Terraform will take to reach the desired state, without actually making any changes.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Why it's important&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Avoid unintended resource changes&lt;/li&gt;
&lt;li&gt;Review planned changes with your team&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  4. &lt;code&gt;terraform apply&lt;/code&gt;
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;terraform apply
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This command executes the changes outlined in the plan. You’ll be prompted to approve before any infrastructure is provisioned or updated.&lt;/p&gt;

&lt;p&gt;You can auto-approve using:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;terraform apply &lt;span class="nt"&gt;-auto-approve&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Pro tip&lt;/strong&gt;: Avoid using &lt;code&gt;-auto-approve&lt;/code&gt; in production unless you really know what you're doing.&lt;/p&gt;




&lt;h2&gt;
  
  
  5. &lt;code&gt;terraform destroy&lt;/code&gt;
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;terraform destroy
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Need to tear down everything? This command &lt;strong&gt;removes all infrastructure&lt;/strong&gt; created by Terraform. Use with caution!&lt;/p&gt;




&lt;h2&gt;
  
  
  6. &lt;code&gt;terraform output&lt;/code&gt;
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;terraform output
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Displays the values of output variables from your configuration. This is useful for retrieving endpoints, resource IDs, and other important data post-deployment.&lt;/p&gt;




&lt;h2&gt;
  
  
  7. &lt;code&gt;terraform fmt&lt;/code&gt;
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;terraform &lt;span class="nb"&gt;fmt&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Automatically formats your Terraform code according to standard conventions. This keeps your code clean, readable, and consistent across teams.&lt;/p&gt;




&lt;h2&gt;
  
  
  8. &lt;code&gt;terraform show&lt;/code&gt;
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;terraform show
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Want to inspect your Terraform state? This command gives you a human-readable view of what's currently managed in your state file.&lt;/p&gt;




&lt;h2&gt;
  
  
  9. &lt;code&gt;terraform state&lt;/code&gt;
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;terraform state list
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Manage the current state of your resources. You can list, pull, move, or remove resources directly from the state file—but this command is &lt;strong&gt;powerful and risky&lt;/strong&gt;, so use with understanding.&lt;/p&gt;




&lt;h2&gt;
  
  
  10. &lt;code&gt;terraform taint&lt;/code&gt;
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;terraform taint &amp;lt;resource_name&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Marks a specific resource for destruction and recreation during the next &lt;code&gt;apply&lt;/code&gt;. Useful when a resource is in a bad state and you want to force a rebuild.&lt;/p&gt;




&lt;h2&gt;
  
  
  Bonus: &lt;code&gt;terraform import&lt;/code&gt;
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;terraform import &amp;lt;resource_type.resource_name&amp;gt; &amp;lt;resource_id&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This command lets you bring existing infrastructure under Terraform management. It doesn’t generate the code for you, but it links the resource to your state file.&lt;/p&gt;




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

&lt;p&gt;Mastering these Terraform commands is a game-changer for any cloud engineer. They form the core toolkit for managing, updating, and troubleshooting infrastructure as code. Whether you're deploying your first EC2 instance or managing multi-cloud environments, these commands will make your work efficient and reliable.&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;Got more Terraform tips or favorite commands?&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
Drop them in the comments—I’d love to hear from fellow DevOps and Cloud Engineering enthusiasts!&lt;/p&gt;

</description>
      <category>devops</category>
      <category>terraform</category>
      <category>cloudcomputing</category>
    </item>
    <item>
      <title>Building and Automating the Deployment of a Flask Application with Docker, GitHub, and CI/CD</title>
      <dc:creator>Joseph Ibeh</dc:creator>
      <pubDate>Fri, 11 Apr 2025 13:40:24 +0000</pubDate>
      <link>https://dev.to/sir-j/building-and-automating-the-deployment-of-a-flask-application-with-docker-github-and-cicd-2dc4</link>
      <guid>https://dev.to/sir-j/building-and-automating-the-deployment-of-a-flask-application-with-docker-github-and-cicd-2dc4</guid>
      <description>&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;This project demonstrates how to build, containerize, and deploy a simple Flask application with Docker, using GitHub for version control and GitHub Actions for Continuous Integration/Continuous Deployment (CI/CD). You will learn how to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Create a simple Flask web application.&lt;/li&gt;
&lt;li&gt;Containerize the application using Docker.&lt;/li&gt;
&lt;li&gt;Set up version control with Git and GitHub.&lt;/li&gt;
&lt;li&gt;Implement CI/CD pipelines using GitHub Actions to build and deploy the Docker image.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  ⚙️ Prerequisites
&lt;/h2&gt;

&lt;p&gt;Before you begin, ensure that you have the following tools installed:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Python&lt;/strong&gt;: A programming language for building web applications.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Flask&lt;/strong&gt;: A lightweight Python web framework.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Docker&lt;/strong&gt;: A platform for developing, shipping, and running applications in containers.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Git&lt;/strong&gt;: A version control system for tracking changes in code.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;GitHub&lt;/strong&gt;: A platform for hosting and sharing code repositories.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Docker Hub&lt;/strong&gt;: A cloud-based registry to share Docker images.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you don't have these installed, refer to their respective official websites for installation instructions.&lt;/p&gt;




&lt;h2&gt;
  
  
  ✅ Step 1: Create a Simple Flask Application
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Create a new folder for the project&lt;/strong&gt;:&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;mkdir &lt;/span&gt;flask-devops-app
&lt;span class="nb"&gt;cd &lt;/span&gt;flask-devops-app
&lt;/code&gt;&lt;/pre&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%2F5ollt3egy9w25z9m2l7u.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%2F5ollt3egy9w25z9m2l7u.png" alt="mkdir" width="520" height="234"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Set up a Python virtual environment&lt;/strong&gt;:&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;python &lt;span class="nt"&gt;-m&lt;/span&gt; venv venv
&lt;/code&gt;&lt;/pre&gt;

&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Activate the virtual environment&lt;/strong&gt;:&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;source &lt;/span&gt;venv/Scripts/activate  &lt;span class="c"&gt;# On Windows use: venv\Scripts\activate&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Install Flask&lt;/strong&gt;:&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;pip &lt;span class="nb"&gt;install &lt;/span&gt;flask
&lt;/code&gt;&lt;/pre&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%2Fbqagsnwqysl5s7etkm7t.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%2Fbqagsnwqysl5s7etkm7t.png" alt="contd" width="616" height="226"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Create the &lt;code&gt;app.py&lt;/code&gt; file&lt;/strong&gt;:&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# app.py
&lt;/span&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;flask&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Flask&lt;/span&gt;

&lt;span class="n"&gt;app&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Flask&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;__name__&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="nd"&gt;@app.route&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;/&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;hello&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Hello DevOps!&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;

&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;__name__&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;__main__&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;run&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;host&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;0.0.0.0&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;port&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;5000&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&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%2F0y26e7uzukn62atgsgxg.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%2F0y26e7uzukn62atgsgxg.png" alt="py file" width="594" height="304"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Run the app locally&lt;/strong&gt;:&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;python app.py
&lt;/code&gt;&lt;/pre&gt;

&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Visit &lt;code&gt;http://localhost:5000&lt;/code&gt; in your browser. You should see &lt;code&gt;"Hello DevOps!"&lt;/code&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&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%2Fk7vxid5rie3t40phlx4b.png" alt="hello devops" width="403" height="106"&gt;
&lt;/h2&gt;

&lt;h2&gt;
  
  
  ✅ Step 2: Containerize the Application
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Create a &lt;code&gt;Dockerfile&lt;/code&gt; in the same folder&lt;/strong&gt;:&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight docker"&gt;&lt;code&gt;&lt;span class="c"&gt;# Dockerfile&lt;/span&gt;
&lt;span class="k"&gt;FROM&lt;/span&gt;&lt;span class="s"&gt; python:3.9-slim&lt;/span&gt;

&lt;span class="k"&gt;WORKDIR&lt;/span&gt;&lt;span class="s"&gt; /app&lt;/span&gt;

&lt;span class="k"&gt;COPY&lt;/span&gt;&lt;span class="s"&gt; requirements.txt requirements.txt&lt;/span&gt;
&lt;span class="k"&gt;RUN &lt;/span&gt;pip &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-r&lt;/span&gt; requirements.txt

&lt;span class="k"&gt;COPY&lt;/span&gt;&lt;span class="s"&gt; . .&lt;/span&gt;

&lt;span class="k"&gt;CMD&lt;/span&gt;&lt;span class="s"&gt; ["python", "app.py"]&lt;/span&gt;

&lt;/code&gt;&lt;/pre&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%2F75ymp6d6czfjrihseafz.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%2F75ymp6d6czfjrihseafz.png" alt="dockerfile" width="493" height="292"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Generate &lt;code&gt;requirements.txt&lt;/code&gt;&lt;/strong&gt;:&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;pip freeze &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; requirements.txt
&lt;/code&gt;&lt;/pre&gt;

&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Create a &lt;code&gt;.dockerignore&lt;/code&gt; file&lt;/strong&gt;:&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;__pycache__/
*.pyc
venv/
&lt;/code&gt;&lt;/pre&gt;

&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Build the Docker image&lt;/strong&gt;:&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker build &lt;span class="nt"&gt;-t&lt;/span&gt; flask-devops-app &lt;span class="nb"&gt;.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&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%2F7sxbi73inoqmyflastxw.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%2F7sxbi73inoqmyflastxw.png" alt="dockerbuild" width="800" height="729"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Run the Docker container&lt;/strong&gt;:&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker run &lt;span class="nt"&gt;-p&lt;/span&gt; 5000:5000 flask-devops-app
&lt;/code&gt;&lt;/pre&gt;

&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Open &lt;code&gt;http://localhost:5000&lt;/code&gt; again and see your app running inside a Docker container.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&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%2Fppn8dxubog8pnufu3nv2.png" alt="docker running" width="792" height="219"&gt;
&lt;/h2&gt;

&lt;h2&gt;
  
  
  ✅ Step 3: Set Up Version Control
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Tools: Git + GitHub
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Initialize a Git repository&lt;/strong&gt;:&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git init
&lt;/code&gt;&lt;/pre&gt;

&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Create a &lt;code&gt;.gitignore&lt;/code&gt; file&lt;/strong&gt;:&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;venv/
__pycache__/
*.pyc
&lt;/code&gt;&lt;/pre&gt;

&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Commit your files&lt;/strong&gt;:&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git add &lt;span class="nb"&gt;.&lt;/span&gt;
git commit &lt;span class="nt"&gt;-m&lt;/span&gt; &lt;span class="s2"&gt;"Initial commit"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Create a GitHub repository and link it to your local repo&lt;/strong&gt;:&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git remote add origin https://github.com/YOUR_USERNAME/flask-devops-app.git
git branch &lt;span class="nt"&gt;-M&lt;/span&gt; main
git push &lt;span class="nt"&gt;-u&lt;/span&gt; origin main
&lt;/code&gt;&lt;/pre&gt;

&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&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%2F9w4ayx1hwt3zehw2rsg3.png" alt="git remote add" width="800" height="408"&gt;
&lt;/h2&gt;

&lt;h2&gt;
  
  
  ✅ Step 4: Implement CI/CD with GitHub Actions
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Tools: GitHub Actions, Docker Hub
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Create a &lt;code&gt;.github/workflows/docker-publish.yml&lt;/code&gt; file&lt;/strong&gt;:&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;mkdir&lt;/span&gt; &lt;span class="nt"&gt;-p&lt;/span&gt; .github/workflows
&lt;span class="nb"&gt;touch&lt;/span&gt; .github/workflows/docker-publish.yml
&lt;/code&gt;&lt;/pre&gt;

&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Edit the &lt;code&gt;docker-publish.yml&lt;/code&gt; file&lt;/strong&gt; and add the following content:&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="c1"&gt;# .github/workflows/docker-publish.yml&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;Build and Push Docker Image&lt;/span&gt;

&lt;span class="na"&gt;on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;push&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;branches&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;[&lt;/span&gt; &lt;span class="nv"&gt;main&lt;/span&gt; &lt;span class="pi"&gt;]&lt;/span&gt;

&lt;span class="na"&gt;jobs&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;build&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;runs-on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;ubuntu-latest&lt;/span&gt;

    &lt;span class="na"&gt;steps&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&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;Checkout code&lt;/span&gt;
        &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;actions/checkout@v3&lt;/span&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;Set up Docker Buildx&lt;/span&gt;
        &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;docker/setup-buildx-action@v2&lt;/span&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;Log in to Docker Hub&lt;/span&gt;
        &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;docker/login-action@v2&lt;/span&gt;
        &lt;span class="na"&gt;with&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;username&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${{ secrets.DOCKER_USERNAME }}&lt;/span&gt;
          &lt;span class="na"&gt;password&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${{ secrets.DOCKER_PASSWORD }}&lt;/span&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;Build and push image&lt;/span&gt;
        &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;docker/build-push-action@v5&lt;/span&gt;
        &lt;span class="na"&gt;with&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;context&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;.&lt;/span&gt;
          &lt;span class="na"&gt;push&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
          &lt;span class="na"&gt;tags&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;YOUR_DOCKERHUB_USERNAME/flask-devops-app:latest&lt;/span&gt;
&lt;/code&gt;&lt;/pre&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%2Fi1pk149np69aqutac5xc.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%2Fi1pk149np69aqutac5xc.png" alt="yml" width="634" height="619"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Add Docker Hub credentials as GitHub Secrets&lt;/strong&gt;:

&lt;ul&gt;
&lt;li&gt;Go to your GitHub repository → &lt;strong&gt;Settings&lt;/strong&gt; → &lt;strong&gt;Secrets and variables&lt;/strong&gt; → &lt;strong&gt;Actions&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Add the following secrets:

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;DOCKER_USERNAME&lt;/code&gt; → your Docker Hub username&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;DOCKER_PASSWORD&lt;/code&gt; → your Docker Hub password or access token&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&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%2Ftlgbv5tt2e911s109m0s.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%2Ftlgbv5tt2e911s109m0s.png" alt="credentials" width="800" height="356"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Push your code again&lt;/strong&gt;:&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git add &lt;span class="nb"&gt;.&lt;/span&gt;
git commit &lt;span class="nt"&gt;-m&lt;/span&gt; &lt;span class="s2"&gt;"Add CI/CD workflow"&lt;/span&gt;
git push
&lt;/code&gt;&lt;/pre&gt;

&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;GitHub Actions will now automatically build your Docker image and push it to Docker Hub whenever you push to the &lt;code&gt;main&lt;/code&gt; branch.&lt;/p&gt;




&lt;h2&gt;
  
  
  Final Output
&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%2F258pjoj8fqkpqfhquno9.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%2F258pjoj8fqkpqfhquno9.png" alt="triggered" width="800" height="503"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;✅ A live Flask app running inside a Docker container.&lt;/li&gt;
&lt;li&gt;✅ The source code is hosted on GitHub.&lt;/li&gt;
&lt;li&gt;✅ The Docker image is automatically built and pushed to Docker Hub on every commit.&lt;/li&gt;
&lt;/ul&gt;




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

&lt;p&gt;Congratulations! You've successfully created a simple Flask app, containerized it with Docker, set up version control with Git and GitHub, and implemented CI/CD with GitHub Actions. This project is a foundational step in building scalable and automated systems in DevOps.&lt;/p&gt;




&lt;h2&gt;
  
  
  Troubleshooting
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;If Docker is not running&lt;/strong&gt;: Ensure Docker Desktop is open and running.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;If you encounter permission issues with GitHub Actions&lt;/strong&gt;: Double-check your Docker Hub credentials in GitHub Secrets.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;If the Flask app does not load&lt;/strong&gt;: Ensure you are using the correct port and that the Docker container is running.
needs!&lt;/li&gt;
&lt;/ul&gt;

</description>
    </item>
    <item>
      <title>From Dockerfile to Deployment: A Simple Guide for New Developers</title>
      <dc:creator>Joseph Ibeh</dc:creator>
      <pubDate>Fri, 21 Feb 2025 13:05:57 +0000</pubDate>
      <link>https://dev.to/sir-j/from-dockerfile-to-deployment-a-simple-guide-for-new-developers-2mjh</link>
      <guid>https://dev.to/sir-j/from-dockerfile-to-deployment-a-simple-guide-for-new-developers-2mjh</guid>
      <description>&lt;p&gt;Containerization has become a game-changer in modern software development, making application deployment more efficient and scalable. If you're a new developer looking to understand Docker and how to containerize your applications, this guide will walk you through the essentials—from writing your first Dockerfile to running multi-container setups using Docker Compose.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;What Is Docker and Why Should You Use It?&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Docker is an open-source platform that enables developers to build, deploy, and run applications inside containers. Containers package all the dependencies an application needs to run, ensuring consistency across development, testing, and production environments.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Why Use Docker?&lt;/strong&gt;
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Consistent development and production environments.&lt;/li&gt;
&lt;li&gt;Simplifies application deployment.&lt;/li&gt;
&lt;li&gt;Enhances scalability and resource efficiency.&lt;/li&gt;
&lt;li&gt;Easier collaboration across teams.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Step-by-Step Guide to Writing a Dockerfile&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;A &lt;strong&gt;Dockerfile&lt;/strong&gt; is a text file that contains a series of instructions Docker uses to build an image. Here’s a simple example to help you get started:&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Example: Dockerfile for a Simple Node.js Application&lt;/strong&gt;
&lt;/h3&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%2Fuqsfa6r0l8ak5g7opzer.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%2Fuqsfa6r0l8ak5g7opzer.png" alt="Docker" width="613" height="379"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Explanation of Each Command:&lt;/strong&gt;
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;FROM&lt;/code&gt;: Specifies the base image for your application.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;WORKDIR&lt;/code&gt;: Sets the working directory inside the container.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;COPY&lt;/code&gt;: Copies files from your local machine into the container.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;RUN&lt;/code&gt;: Executes commands (e.g., installing dependencies).&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;EXPOSE&lt;/code&gt;: Informs Docker which port the app will use.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;CMD&lt;/code&gt;: Specifies the command that will run when the container starts.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Best Practices for Managing Docker Images and Containers&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;To ensure efficient and secure containerization, follow these best practices:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Use Small Base Images:&lt;/strong&gt; Smaller images reduce build time and improve security.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Minimize Layers:&lt;/strong&gt; Combine commands using &lt;code&gt;&amp;amp;&amp;amp;&lt;/code&gt; to minimize layers and optimize the image size.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Leverage .dockerignore:&lt;/strong&gt; Exclude unnecessary files from being copied into your container.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Tag Images Properly:&lt;/strong&gt; Use meaningful tags (e.g., &lt;code&gt;v1.0&lt;/code&gt;, &lt;code&gt;latest&lt;/code&gt;) for easier tracking.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Clean Up After Installation:&lt;/strong&gt; Remove unnecessary dependencies to keep the image lightweight.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Basic Docker Commands Every Developer Should Know&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Here are some essential Docker commands to help you get started:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Command&lt;/th&gt;
&lt;th&gt;Description&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;docker build -t app-name .&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Build an image from a Dockerfile&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;docker images&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;List all Docker images&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;docker run -d -p 3000:3000 app-name&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Run a container from an image&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;docker ps&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;List running containers&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;docker stop &amp;lt;container_id&amp;gt;&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Stop a running container&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;docker rm &amp;lt;container_id&amp;gt;&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Remove a stopped container&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;docker rmi &amp;lt;image_id&amp;gt;&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Remove an image&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;docker logs &amp;lt;container_id&amp;gt;&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;View logs from a running container&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Using Docker Compose for Multi-Container Applications&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;When your application relies on multiple services (like a database and a web server), &lt;strong&gt;Docker Compose&lt;/strong&gt; simplifies the process of running multi-container setups.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Example: docker-compose.yml for a Node.js App with MongoDB&lt;/strong&gt;
&lt;/h3&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%2F0ruhtbgzj4hc5if02kad.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%2F0ruhtbgzj4hc5if02kad.png" alt="yaml" width="355" height="253"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Explanation:&lt;/strong&gt;
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;version&lt;/code&gt;: Specifies the Docker Compose version.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;services&lt;/code&gt;: Defines the containers to run.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;web&lt;/code&gt;: Builds the app from your Dockerfile and maps port 3000.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;mongo&lt;/code&gt;: Pulls a MongoDB image and maps port 27017.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Running Your Docker Compose Application:&lt;/strong&gt;
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;Save the file as &lt;code&gt;docker-compose.yml&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Run the following command:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker-compose up
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;To stop the containers:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker-compose down
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;p&gt;Containerization with Docker is a powerful tool for modern developers, simplifying deployment and enhancing scalability. By mastering Dockerfiles, managing images and containers efficiently, and using Docker Compose for multi-container setups, you'll be well on your way to building robust applications.&lt;/p&gt;

</description>
      <category>devops</category>
      <category>docker</category>
      <category>cloudcomputing</category>
    </item>
    <item>
      <title>Building a Scalable Data Lake for Sports Analytics with AWS</title>
      <dc:creator>Joseph Ibeh</dc:creator>
      <pubDate>Mon, 17 Feb 2025 14:15:41 +0000</pubDate>
      <link>https://dev.to/sir-j/building-a-scalable-data-lake-for-sports-analytics-with-aws-53e2</link>
      <guid>https://dev.to/sir-j/building-a-scalable-data-lake-for-sports-analytics-with-aws-53e2</guid>
      <description>&lt;h2&gt;
  
  
  Sports Analytics Data Lake
&lt;/h2&gt;

&lt;p&gt;This project sets up a data lake to store and process NBA sports data using AWS services such as S3, AWS Glue, and Athena. It uses the SportsData.io API to fetch NBA player data and process it for analytics purposes. There are two main scripts in the project:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;setup_nba_data_lake.py&lt;/strong&gt;: This script sets up the data lake by creating the necessary AWS resources and fetching NBA data from the SportsData.io API.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;delete.py&lt;/strong&gt;: This script deletes the resources created during the setup, including S3 buckets, Glue database, and Athena query results.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Overview of AWS Services Used
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;S3 Buckets&lt;/strong&gt;: Used to store data in different formats (JSON files).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;AWS Glue&lt;/strong&gt;: A serverless integration service to catalog the data stored in S3 and load it into Athena.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Amazon Athena&lt;/strong&gt;: Allows querying of the data stored in S3 using SQL queries.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Interpretation of the Project
&lt;/h2&gt;

&lt;p&gt;This project is designed to automate the setup of a sports analytics data lake for NBA data. By using AWS services, it allows users to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Collect NBA player data from the SportsData.io API.&lt;/li&gt;
&lt;li&gt;Store the data in an S3 bucket.&lt;/li&gt;
&lt;li&gt;Catalog and structure the data using AWS Glue.&lt;/li&gt;
&lt;li&gt;Set up Athena to allow querying of the data stored in S3.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This approach provides a scalable, cost-efficient solution for analyzing large amounts of sports data and performing advanced analytics using SQL-based queries.&lt;/p&gt;




&lt;h2&gt;
  
  
  Steps to Set Up
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Prerequisites
&lt;/h3&gt;

&lt;p&gt;Before running the script, ensure you have the following:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Go to &lt;a href="https://sportsdata.io" rel="noopener noreferrer"&gt;Sportsdata.io&lt;/a&gt; and create a free account.&lt;/li&gt;
&lt;li&gt;At the top left, you should see "Developers"; hover over it to see "API Resources".&lt;/li&gt;
&lt;li&gt;Click on &lt;strong&gt;Introduction &amp;amp; Testing&lt;/strong&gt;, then select "SportsDataIO API Free Trial" and fill out the information. Ensure to select NBA for this tutorial.&lt;/li&gt;
&lt;li&gt;You will receive an email with the subject "Launch Developer Portal". Follow the link provided.&lt;/li&gt;
&lt;li&gt;By default, it takes you to the NFL section. On the left, click on &lt;strong&gt;NBA&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;Scroll down until you see &lt;strong&gt;"Standings"&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;Under &lt;strong&gt;"Query String Parameters"&lt;/strong&gt;, the value in the drop-down box is your API key.&lt;/li&gt;
&lt;li&gt;Copy this string as you will need to paste it into the script.&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  IAM Role/Permissions:
&lt;/h3&gt;

&lt;p&gt;Ensure the user or role running the script has the following permissions:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;S3&lt;/strong&gt;: &lt;code&gt;s3:CreateBucket&lt;/code&gt;, &lt;code&gt;s3:PutObject&lt;/code&gt;, &lt;code&gt;s3:DeleteBucket&lt;/code&gt;, &lt;code&gt;s3:ListBucket&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Glue&lt;/strong&gt;: &lt;code&gt;glue:CreateDatabase&lt;/code&gt;, &lt;code&gt;glue:CreateTable&lt;/code&gt;, &lt;code&gt;glue:DeleteDatabase&lt;/code&gt;, &lt;code&gt;glue:DeleteTable&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Athena&lt;/strong&gt;: &lt;code&gt;athena:StartQueryExecution&lt;/code&gt;, &lt;code&gt;athena:GetQueryResults&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;




&lt;h3&gt;
  
  
  Step 1: Open CloudShell Console
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;Go to &lt;a href="https://aws.amazon.com" rel="noopener noreferrer"&gt;aws.amazon.com&lt;/a&gt; and sign into your account.&lt;/li&gt;
&lt;li&gt;In the top right, next to the search bar, click the square with a &lt;code&gt;&amp;gt;_&lt;/code&gt; inside to open the CloudShell.&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%2Fmqegizujlj8qn543h3iu.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%2Fmqegizujlj8qn543h3iu.png" alt="shell" width="800" height="354"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 2: Create the &lt;code&gt;setup_nba_data_lake.py&lt;/code&gt; File
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;In the CLI (Command Line Interface), type:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;nano setup_nba_data_lake.py
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;Paste the following script into the file:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import boto3
import json
import time
import requests
from dotenv import load_dotenv
import os

# Load environment variables from .env file
load_dotenv()

# AWS configurations
region = "us-east-1"  # Replace with your preferred AWS region
bucket_name = "Jose-sports-analytics-data-lake"  # Change to a unique S3 bucket name
glue_database_name = "glue_nba_data_lake"
athena_output_location = f"s3://{bucket_name}/athena-results/"

# Sportsdata.io configurations (loaded from .env)
api_key = "SPORTS_DATA_API_KEY"  # Replace with your API key
nba_endpoint = "NBA_ENDPOINT"  # Get NBA endpoint from .env

# Use the hardcoded values from the script
api_key = SPORTS_DATA_API_KEY
nba_endpoint = NBA_ENDPOINT

# Create AWS clients
s3_client = boto3.client("s3", region_name=region)
glue_client = boto3.client("glue", region_name=region)
athena_client = boto3.client("athena", region_name=region)

def create_s3_bucket():
    """Create an S3 bucket for storing sports data."""
    try:
        if region == "us-east-1":
            s3_client.create_bucket(Bucket=bucket_name)
        else:
            s3_client.create_bucket(
                Bucket=bucket_name,
                CreateBucketConfiguration={"LocationConstraint": region},
            )
        print(f"S3 bucket '{bucket_name}' created successfully.")
    except Exception as e:
        print(f"Error creating S3 bucket: {e}")

def create_glue_database():
    """Create a Glue database for the data lake."""
    try:
        glue_client.create_database(
            DatabaseInput={
                "Name": glue_database_name,
                "Description": "Glue database for NBA sports analytics.",
            }
        )
        print(f"Glue database '{glue_database_name}' created successfully.")
    except Exception as e:
        print(f"Error creating Glue database: {e}")

def fetch_nba_data():
    """Fetch NBA player data from sportsdata.io."""
    try:
        headers = {"Ocp-Apim-Subscription-Key": api_key}
        response = requests.get(nba_endpoint, headers=headers)
        response.raise_for_status()  # Raise an error for bad status codes
        print("Fetched NBA data successfully.")
        return response.json()  # Return JSON response
    except Exception as e:
        print(f"Error fetching NBA data: {e}")
        return []

def convert_to_line_delimited_json(data):
    """Convert data to line-delimited JSON format."""
    print("Converting data to line-delimited JSON format...")
    return "\n".join([json.dumps(record) for record in data])

def upload_data_to_s3(data):
    """Upload NBA data to the S3 bucket."""
    try:
        # Convert data to line-delimited JSON
        line_delimited_data = convert_to_line_delimited_json(data)

        # Define S3 object key
        file_key = "raw-data/nba_player_data.jsonl"

        # Upload JSON data to S3
        s3_client.put_object(
            Bucket=bucket_name,
            Key=file_key,
            Body=line_delimited_data
        )
        print(f"Uploaded data to S3: {file_key}")
    except Exception as e:
        print(f"Error uploading data to S3: {e}")

def create_glue_table():
    """Create a Glue table for the data."""
    try:
        glue_client.create_table(
            DatabaseName=glue_database_name,
            TableInput={
                "Name": "nba_players",
                "StorageDescriptor": {
                    "Columns": [
                        {"Name": "PlayerID", "Type": "int"},
                        {"Name": "FirstName", "Type": "string"},
                        {"Name": "LastName", "Type": "string"},
                        {"Name": "Team", "Type": "string"},
                        {"Name": "Position", "Type": "string"},
                        {"Name": "Points", "Type": "int"}
                    ],
                    "Location": f"s3://{bucket_name}/raw-data/",
                    "InputFormat": "org.apache.hadoop.mapred.TextInputFormat",
                    "OutputFormat": "org.apache.hadoop.hive.ql.io.HiveIgnoreKeyTextOutputFormat",
                    "SerdeInfo": {
                        "SerializationLibrary": "org.openx.data.jsonserde.JsonSerDe"
                    },
                },
                "TableType": "EXTERNAL_TABLE",
            },
        )
        print(f"Glue table 'nba_players' created successfully.")
    except Exception as e:
        print(f"Error creating Glue table: {e}")

def configure_athena():
    """Set up Athena output location."""
    try:
        athena_client.start_query_execution(
            QueryString="CREATE DATABASE IF NOT EXISTS nba_analytics",
            QueryExecutionContext={"Database": glue_database_name},
            ResultConfiguration={"OutputLocation": athena_output_location},
        )
        print("Athena output location configured successfully.")
    except Exception as e:
        print(f"Error configuring Athena: {e}")

# Main workflow
def main():
    print("Setting up data lake for NBA sports analytics...")
    create_s3_bucket()
    time.sleep(5)  # Ensure bucket creation propagates
    create_glue_database()
    nba_data = fetch_nba_data()
    if nba_data:  # Only proceed if data was fetched successfully
        upload_data_to_s3(nba_data)
    create_glue_table()
    configure_athena()
    print("Data lake setup complete.")

if __name__ == "__main__":
    main()
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&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%2Fvge8tzuaqr4llp3hlmce.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%2Fvge8tzuaqr4llp3hlmce.png" alt="py script" width="800" height="357"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 3: Create the delete.py Script
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import boto3
from botocore.exceptions import ClientError

# Define the names of resources to delete
BUCKET_NAME = "Jose-sports-analytics-data-lake"
GLUE_DATABASE_NAME = "glue_nba_data_lake"

def delete_athena_query_results(bucket_name):
    """Delete Athena query results stored in the specified S3 bucket."""
    s3 = boto3.client("s3")
    try:
        print(f"Deleting Athena query results in bucket: {bucket_name}")
        objects = s3.list_objects_v2(Bucket=bucket_name, Prefix="athena-results/")
        if "Contents" in objects:
            for obj in objects["Contents"]:
                s3.delete_object(Bucket=bucket_name, Key=obj["Key"])
                print(f"Deleted Athena query result: {obj['Key']}")
    except ClientError as e:
        print(f"Error deleting Athena query results in bucket {bucket_name}: {e}")

def delete_s3_bucket(bucket_name):
    """Delete a specific S3 bucket and its contents."""
    s3 = boto3.client("s3")
    try:
        print(f"Deleting bucket: {bucket_name}")
        # Delete all objects in the bucket
        objects = s3.list_objects_v2(Bucket=bucket_name)
        if "Contents" in objects:
            for obj in objects["Contents"]:
                s3.delete_object(Bucket=bucket_name, Key=obj["Key"])
                print(f"Deleted object: {obj['Key']}")
        # Delete the bucket
        s3.delete_bucket(Bucket=bucket_name)
        print(f"Deleted bucket: {bucket_name}")
    except ClientError as e:
        print(f"Error deleting bucket {bucket_name}: {e}")

def delete_glue_resources(database_name):
    """Delete Glue database and associated tables."""
    glue = boto3.client("glue")
    try:
        print(f"Deleting Glue database: {database_name}")
        # Get tables in the database
        tables = glue.get_tables(DatabaseName=database_name)["TableList"]
        for table in tables:
            table_name = table["Name"]
            print(f"Deleting Glue table: {table_name} in database {database_name}")
            glue.delete_table(DatabaseName=database_name, Name=table_name)
        # Delete the database
        glue.delete_database(Name=database_name)
        print(f"Deleted Glue database: {database_name}")
    except ClientError as e:
        print(f"Error deleting Glue resources for database {database_name}: {e}")

def main():
    print("Deleting resources created during data lake setup...")
    # Delete the S3 bucket
    delete_s3_bucket(BUCKET_NAME)
    # Delete Glue resources
    delete_glue_resources(GLUE_DATABASE_NAME)
    # Delete Athena query results
    delete_athena_query_results(BUCKET_NAME)
    print("All specified resources deleted successfully.")

if __name__ == "__main__":
    main()
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&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%2F11czw72k2786q2w0dod8.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%2F11czw72k2786q2w0dod8.png" alt="delete" width="800" height="349"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;ls to see see the files and directories that are present in the current directory or the directory&lt;/strong&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%2F5swj3ogaxghztc1ge9i6.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%2F5swj3ogaxghztc1ge9i6.png" alt="ls" width="453" height="93"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Running the Scripts
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;python3 setup_nba_data_lake.py
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&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%2Fwhk92epgdkqt6x68arqp.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%2Fwhk92epgdkqt6x68arqp.png" alt="run script" width="800" height="228"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;N.b ignore the errors, it was because I ran the script twice&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Go to s3 bucket and open the Json file to get the data
&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%2Fpewp441cdtifm27zeqex.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%2Fpewp441cdtifm27zeqex.png" alt="s3 bucket" width="800" height="330"&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%2Ff6mah22i6455o7ebmgwf.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%2Ff6mah22i6455o7ebmgwf.png" alt="json file" width="800" height="356"&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%2Fonxc6p2gu0uhxnmw3hj4.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%2Fonxc6p2gu0uhxnmw3hj4.png" alt="json" width="800" height="362"&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%2Fmlsecp1kypo22qlapfp3.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%2Fmlsecp1kypo22qlapfp3.png" alt="json" width="800" height="365"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;To delete the resources, run:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;python3 delete.py
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Conclusion&lt;/strong&gt;&lt;br&gt;
This project demonstrates how to set up a data lake using AWS services and integrate data from an external API for sports analytics.&lt;/p&gt;

</description>
      <category>devops</category>
      <category>cloudcomputing</category>
      <category>aws</category>
      <category>api</category>
    </item>
    <item>
      <title>Building an NBA Game Day Notification System with AWS Lambda, SNS &amp; EventBridge</title>
      <dc:creator>Joseph Ibeh</dc:creator>
      <pubDate>Sat, 08 Feb 2025 06:46:50 +0000</pubDate>
      <link>https://dev.to/sir-j/building-an-nba-game-day-notification-system-with-aws-lambda-sns-eventbridge-54ho</link>
      <guid>https://dev.to/sir-j/building-an-nba-game-day-notification-system-with-aws-lambda-sns-eventbridge-54ho</guid>
      <description>&lt;h2&gt;
  
  
  🏀 NBA Game Day Notification System
&lt;/h2&gt;

&lt;p&gt;This project is an &lt;strong&gt;AWS Lambda-powered notification system&lt;/strong&gt; that sends NBA game updates via &lt;strong&gt;Amazon SNS (Simple Notification Service)&lt;/strong&gt;. It fetches game details from &lt;strong&gt;SportsData.io&lt;/strong&gt; and notifies subscribed users via email. The function runs on a scheduled &lt;strong&gt;Amazon EventBridge&lt;/strong&gt; rule.&lt;/p&gt;

&lt;h2&gt;
  
  
  Features
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Fetches NBA game data from &lt;strong&gt;SportsData.io API&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Sends real-time updates on &lt;strong&gt;game status, scores, and channels&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Uses &lt;strong&gt;AWS Lambda, SNS, and EventBridge&lt;/strong&gt; for automation&lt;/li&gt;
&lt;li&gt;Supports multiple game statuses: &lt;strong&gt;Final, In Progress, and Scheduled&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Prerequisites
&lt;/h2&gt;

&lt;p&gt;Before deploying, ensure you have:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;AWS Account&lt;/strong&gt; with Lambda, SNS, and EventBridge permissions&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;SportsData.io API Key&lt;/strong&gt; (Create a free API key &lt;a href="https://sportsdata.io" rel="noopener noreferrer"&gt;here&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Email Subscription&lt;/strong&gt; to the SNS topic&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Setup Instructions
&lt;/h2&gt;




&lt;h3&gt;
  
  
  1️⃣ Create an SNS Topic
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Open AWS SNS and create a new &lt;strong&gt;topic&lt;/strong&gt; named &lt;code&gt;gd_topic&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Subscribe an &lt;strong&gt;email address&lt;/strong&gt; to this topic and confirm the email subscription.&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%2Fa8mgoqpmh0yfpbhk3cm4.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%2Fa8mgoqpmh0yfpbhk3cm4.png" alt="sns topic" width="800" height="354"&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%2F18gn1nfxv4jdl4oo5qyv.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%2F18gn1nfxv4jdl4oo5qyv.png" alt="subscribe topic" width="800" height="352"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h3&gt;
  
  
  2️⃣ Create an IAM Role for Lambda
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Open &lt;strong&gt;IAM&lt;/strong&gt; → &lt;strong&gt;Roles&lt;/strong&gt; → &lt;strong&gt;Create Role&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;Select &lt;strong&gt;AWS Service → Lambda&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;Attach the &lt;strong&gt;AmazonSNSFullAccess&lt;/strong&gt; policy.&lt;/li&gt;
&lt;li&gt;Create a custom &lt;strong&gt;JSON policy&lt;/strong&gt; with the following:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"Version"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"2012-10-17"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"Statement"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"Effect"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Allow"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"Action"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"sns:Publish"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"Resource"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"arn:aws:sns:us-east-1:XXXXXXXXXXXX:gd_topic"&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Replace &lt;code&gt;XXXXXXXXXXXX&lt;/code&gt; with your AWS Account ID.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Name the role &lt;strong&gt;gd_lambda_role&lt;/strong&gt; and attach it to your Lambda function.&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%2Fkyt4cgmpejbo7hbnqcu2.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%2Fkyt4cgmpejbo7hbnqcu2.png" alt="role and policy" width="800" height="331"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h3&gt;
  
  
  3️⃣ Deploy the AWS Lambda Function
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Navigate to &lt;strong&gt;AWS Lambda&lt;/strong&gt; → &lt;strong&gt;Create Function&lt;/strong&gt; → &lt;strong&gt;Author from Scratch&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;Function Name: &lt;strong&gt;gd_notification&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Runtime: &lt;strong&gt;Python 3.13&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Attach &lt;strong&gt;gd_lambda_role&lt;/strong&gt; to the function.&lt;/li&gt;
&lt;li&gt;Paste the following &lt;strong&gt;Python script&lt;/strong&gt; into the function editor:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;json&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;urllib.request&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;boto3&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;datetime&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;datetime&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;timedelta&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;timezone&lt;/span&gt;

&lt;span class="c1"&gt;# Function to format NBA game data
&lt;/span&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;format_game_data&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;game&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;status&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;game&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Status&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Unknown&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;away_team&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;game&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;AwayTeam&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Unknown&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;home_team&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;game&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;HomeTeam&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Unknown&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;final_score&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;game&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;AwayTeamScore&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;N/A&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;-&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;game&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;HomeTeamScore&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;N/A&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
    &lt;span class="n"&gt;start_time&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;game&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;DateTime&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Unknown&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;channel&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;game&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Channel&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Unknown&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;status&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Final&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Game Status: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;status&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;away_team&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt; vs &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;home_team&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;Final Score: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;final_score&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;Start Time: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;start_time&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;Channel: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;channel&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
    &lt;span class="k"&gt;elif&lt;/span&gt; &lt;span class="n"&gt;status&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;InProgress&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Game Status: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;status&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;away_team&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt; vs &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;home_team&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;Current Score: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;final_score&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;Channel: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;channel&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
    &lt;span class="k"&gt;elif&lt;/span&gt; &lt;span class="n"&gt;status&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Scheduled&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Game Status: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;status&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;away_team&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt; vs &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;home_team&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;Start Time: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;start_time&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;Channel: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;channel&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
    &lt;span class="k"&gt;else&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Game Status: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;status&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;away_team&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt; vs &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;home_team&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;Details are unavailable.&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;

&lt;span class="c1"&gt;# Lambda function handler
&lt;/span&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;lambda_handler&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;event&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;api_key&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getenv&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;NBA_API_KEY&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;sns_topic_arn&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getenv&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;SNS_TOPIC_ARN&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;sns_client&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;boto3&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;client&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;sns&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="n"&gt;utc_now&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;datetime&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;now&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;timezone&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;utc&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;today_date&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;utc_now&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="nf"&gt;timedelta&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;hours&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="p"&gt;)).&lt;/span&gt;&lt;span class="nf"&gt;strftime&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;%Y-%m-%d&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;api_url&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;https://api.sportsdata.io/v3/nba/scores/json/GamesByDate/&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;today_date&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;?key=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;api_key&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;

    &lt;span class="k"&gt;try&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="n"&gt;urllib&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;urlopen&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;api_url&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="n"&gt;data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;loads&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;read&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;decode&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
    &lt;span class="k"&gt;except&lt;/span&gt; &lt;span class="nb"&gt;Exception&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Error fetching data: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;statusCode&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;500&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;body&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Error fetching data&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="n"&gt;messages&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nf"&gt;format_game_data&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;game&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;game&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="n"&gt;final_message&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;---&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;messages&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;messages&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;No games available for today.&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;

    &lt;span class="k"&gt;try&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;sns_client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;publish&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;TopicArn&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;sns_topic_arn&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Message&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;final_message&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Subject&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;NBA Game Updates&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Message published to SNS successfully.&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;except&lt;/span&gt; &lt;span class="nb"&gt;Exception&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Error publishing to SNS: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;statusCode&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;500&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;body&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Error publishing to SNS&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;statusCode&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;200&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;body&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Data processed and sent to SNS&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&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%2F287gblov3zaxy6sp93c4.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%2F287gblov3zaxy6sp93c4.png" alt="python script" width="800" height="352"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Click &lt;strong&gt;Deploy&lt;/strong&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%2Fu2s4b3yhkyuwlfh1q8sj.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%2Fu2s4b3yhkyuwlfh1q8sj.png" alt="test" width="800" height="351"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Add &lt;strong&gt;Environment Variables&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;NBA_API_KEY&lt;/code&gt;: Your SportsData.io API Key&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;SNS_TOPIC_ARN&lt;/code&gt;: ARN of your SNS Topic (e.g., &lt;code&gt;arn:aws:sns:us-east-1:XXXXXXXXXXXX:gd_topic&lt;/code&gt;)&lt;/li&gt;
&lt;/ul&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%2Fhan1x4eh9p2kjjgvwyey.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%2Fhan1x4eh9p2kjjgvwyey.png" alt="env variable" width="800" height="320"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Increase &lt;strong&gt;timeout&lt;/strong&gt; under &lt;em&gt;General Configuration&lt;/em&gt; to &lt;strong&gt;5 seconds or more&lt;/strong&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%2F95ztq9sk3sod5vv6runt.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%2F95ztq9sk3sod5vv6runt.png" alt="timeout" width="800" height="329"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h3&gt;
  
  
  4️⃣ Test the Lambda Function
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Click &lt;strong&gt;Test&lt;/strong&gt;, create a test event, and run it.&lt;/li&gt;
&lt;li&gt;Check your &lt;strong&gt;email inbox&lt;/strong&gt; for an NBA game update 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%2Fy1ot954y78vvvm12ucsy.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%2Fy1ot954y78vvvm12ucsy.png" alt="Email update" width="800" height="390"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h3&gt;
  
  
  5️⃣ Automate with AWS EventBridge
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Open &lt;strong&gt;Amazon EventBridge&lt;/strong&gt; → &lt;strong&gt;Create Rule&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Rule Name: &lt;strong&gt;gd_rule&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Schedule Pattern&lt;/strong&gt;:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;  0 9-23/2,0-2/2 * * ? *
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;em&gt;(Runs every 2 hours from 9 AM - 11 PM UTC and 12 AM - 2 AM UTC)&lt;/em&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Target&lt;/strong&gt;: AWS Lambda → &lt;strong&gt;NBA-GameDay-Notifier&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Click &lt;strong&gt;Create Rule&lt;/strong&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%2Fvps1w8qfec1r1c8wobcv.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%2Fvps1w8qfec1r1c8wobcv.png" alt="Event bridge" width="800" height="352"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  Email Notification
&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%2F4iewcqeczxpcw9xi3gv2.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%2F4iewcqeczxpcw9xi3gv2.png" alt="update" width="800" height="390"&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%2F5gzt90x3quqwg0231hqf.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%2F5gzt90x3quqwg0231hqf.png" alt="update 2" width="800" height="369"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  Summary
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;AWS SNS&lt;/strong&gt; sends game notifications to subscribed emails.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;AWS Lambda&lt;/strong&gt; fetches NBA data and publishes updates.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Amazon EventBridge&lt;/strong&gt; schedules function execution.&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>aws</category>
      <category>lambda</category>
      <category>eventbridge</category>
      <category>devops</category>
    </item>
    <item>
      <title>Building a Scalable Real-Time Weather Dashboard with Python, OpenWeather API, and AWS S3</title>
      <dc:creator>Joseph Ibeh</dc:creator>
      <pubDate>Sat, 18 Jan 2025 11:41:39 +0000</pubDate>
      <link>https://dev.to/sir-j/building-a-scalable-real-time-weather-dashboard-with-python-openweather-api-and-aws-s3-5mp</link>
      <guid>https://dev.to/sir-j/building-a-scalable-real-time-weather-dashboard-with-python-openweather-api-and-aws-s3-5mp</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%2F8y68piozjvgij0pxx5i0.jpg" 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%2F8y68piozjvgij0pxx5i0.jpg" alt="diagram" width="720" height="203"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Weather Dashboard Project
&lt;/h2&gt;

&lt;p&gt;The &lt;strong&gt;Weather Dashboard&lt;/strong&gt; is a Python-based project that pulls weather data from the OpenWeather API and uploads it to an AWS S3 bucket. It is designed to provide a simple interface for displaying weather information for different cities and saving the results to the cloud.&lt;/p&gt;

&lt;p&gt;This project leverages AWS S3 to store weather data, making it highly scalable, and uses Python to interact with the OpenWeather API.&lt;/p&gt;

&lt;h2&gt;
  
  
  Table of Contents
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Prerequisites&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Project Overview&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Core Features&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Tools Used&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Project Setup&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Environment Setup&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Running the Project&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Prerequisites
&lt;/h2&gt;

&lt;p&gt;Before starting this project, ensure you have the following:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Python 3.x&lt;/strong&gt;: Install Python from the &lt;a href="https://www.python.org/downloads/" rel="noopener noreferrer"&gt;official website&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;AWS Account&lt;/strong&gt;: Create an AWS account to access AWS S3.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;OpenWeather API Key&lt;/strong&gt;: Obtain an API key from the &lt;a href="https://openweathermap.org/" rel="noopener noreferrer"&gt;OpenWeather website&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;AWS CLI Installed&lt;/strong&gt;: Download and install the AWS CLI tool from the &lt;a href="https://aws.amazon.com/cli/" rel="noopener noreferrer"&gt;official website&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Basic Python Knowledge&lt;/strong&gt;: Familiarity with Python scripting, working with APIs, and environment variables.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Text Editor or IDE&lt;/strong&gt;: Use a development environment like VS Code, PyCharm, or any text editor of your choice.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Git Installed&lt;/strong&gt;: Ensure Git is installed for version control. Download it from the &lt;a href="https://git-scm.com/" rel="noopener noreferrer"&gt;Git website&lt;/a&gt;.&lt;/li&gt;
&lt;/ol&gt;

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

&lt;p&gt;This weather dashboard project fetches weather information for a given location using the &lt;strong&gt;OpenWeather API&lt;/strong&gt;. The data is then uploaded to an &lt;strong&gt;AWS S3 bucket&lt;/strong&gt; where it can be accessed remotely. The system is designed to be flexible, allowing users to specify different cities and view weather updates in real-time.&lt;/p&gt;

&lt;h3&gt;
  
  
  Core Features
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Fetches weather data from OpenWeather API.&lt;/li&gt;
&lt;li&gt;Uploads weather data to an AWS S3 bucket.&lt;/li&gt;
&lt;li&gt;Allows you to configure API keys and AWS credentials securely via environment variables.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Tools Used
&lt;/h2&gt;

&lt;p&gt;This project utilizes several tools and libraries to build the dashboard:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Python 3.x&lt;/strong&gt;: The main programming language for the project.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;boto3&lt;/strong&gt;: AWS SDK for Python used to interact with AWS S3.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;python-dotenv&lt;/strong&gt;: A library to read environment variables from a &lt;code&gt;.env&lt;/code&gt; file to keep sensitive data safe.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;requests&lt;/strong&gt;: A simple HTTP library for making API requests to OpenWeather.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;AWS CLI&lt;/strong&gt;: Command-line tool to interact with AWS services, such as configuring access keys and managing S3 buckets.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Project Setup
&lt;/h2&gt;

&lt;p&gt;Follow these steps to set up the project on your local machine.&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Create Project Structure
&lt;/h3&gt;

&lt;p&gt;weather-dashboard/&lt;br&gt;
├── src/&lt;br&gt;
│ ├── &lt;strong&gt;init&lt;/strong&gt;.py&lt;br&gt;
│ └── weather_dashboard.py&lt;br&gt;
├── .env&lt;br&gt;
├── tests/&lt;br&gt;
├── data/&lt;br&gt;
├── .gitignore&lt;br&gt;
└── README.md&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%2F8z8clgnnglv8pm87lnm4.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%2F8z8clgnnglv8pm87lnm4.png" alt="project structure" width="355" height="496"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Run the following commands to create the necessary directories and files:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;mkdir &lt;/span&gt;weather_dashboard_demo
&lt;span class="nb"&gt;cd &lt;/span&gt;weather_dashboard_demo
&lt;span class="nb"&gt;mkdir &lt;/span&gt;src tests data
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&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%2Fvv7lth51uxns4sgmf4m2.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%2Fvv7lth51uxns4sgmf4m2.png" alt="mkdir" width="649" height="264"&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%2Fyh8lbji00tgxoczdjf2z.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%2Fyh8lbji00tgxoczdjf2z.png" alt="src" width="760" height="73"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Create Files
&lt;/h3&gt;

&lt;p&gt;Create the required Python files and configuration files:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;touch src/__init__.py src/weather_dashboard.py
touch requirements.txt README.md .env
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&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%2F85dd4jppgwy2d414lk7o.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%2F85dd4jppgwy2d414lk7o.png" alt="init" width="634" height="73"&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%2Fs8eo6p50gk0n06tqp1pb.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%2Fs8eo6p50gk0n06tqp1pb.png" alt="req" width="658" height="81"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  3.  Initialize Git Repository
&lt;/h3&gt;

&lt;p&gt;Initialize a new Git repository and set up the main branch:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;git init
git branch -M main
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&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%2Fa4lx2xedz5vexuof6ifs.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%2Fa4lx2xedz5vexuof6ifs.png" alt="git init" width="800" height="96"&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%2Fswpfqlllw7sv6y7znty0.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%2Fswpfqlllw7sv6y7znty0.png" alt="git branch" width="729" height="73"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  4. Configure .gitignore
&lt;/h3&gt;

&lt;p&gt;Create a .gitignore file to ignore unnecessary files:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;echo ".env" &amp;gt;&amp;gt; .gitignore
echo "__pycache__/" &amp;gt;&amp;gt; .gitignore
echo "*.zip" &amp;gt;&amp;gt; .gitignore
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&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%2Fr48lifb0ct5rz4025q2m.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%2Fr48lifb0ct5rz4025q2m.png" alt="git ignore" width="721" height="316"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  5. Add Dependencies
&lt;/h3&gt;

&lt;p&gt;Add the required dependencies to requirements.txt:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;echo "boto3==1.26.137" &amp;gt;&amp;gt; requirements.txt
echo "python-dotenv==1.0.0" &amp;gt;&amp;gt; requirements.txt
echo "requests==2.28.2" &amp;gt;&amp;gt; requirements.txt
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&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%2Ftonkcu32evr1on6wplor.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%2Ftonkcu32evr1on6wplor.png" alt="boto3" width="699" height="160"&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%2Fjre0sfl558ta504detl9.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%2Fjre0sfl558ta504detl9.png" alt="requirement" width="721" height="81"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  6. Install Dependencies
&lt;/h3&gt;

&lt;p&gt;Run the following command to install the dependencies from requirements.txt:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;pip install -r requirements.txt
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&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%2F06vojayxcn929fr5hrhr.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%2F06vojayxcn929fr5hrhr.png" alt="pip install reqirement" width="800" height="137"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Environment Setup
&lt;/h2&gt;

&lt;h3&gt;
  
  
  1. AWS CLI Configuration
&lt;/h3&gt;

&lt;p&gt;Before interacting with AWS services like S3, you need to configure your AWS CLI with your access keys. This allows the Python script to communicate with AWS securely.&lt;br&gt;
To configure AWS CLI, run the following command:&lt;/p&gt;

&lt;p&gt;Run:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;aws configure

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

&lt;/div&gt;



&lt;p&gt;This will prompt you to enter your AWS credentials. You'll need your AWS Access Key ID and AWS Secret Access Key, which you can get from your AWS Management Console under IAM &amp;gt; Users &amp;gt; Your User &amp;gt; Security Credentials.&lt;/p&gt;

&lt;p&gt;You will also be prompted for the default region and default output format:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;AWS Access Key ID:&lt;/strong&gt; Your unique key that identifies your AWS account.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;AWS Secret Access Key:&lt;/strong&gt; A secret key that corresponds to your AWS Access Key ID.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Default region name:&lt;/strong&gt; This is typically something like us-east-1, us-west-2, etc. You can check the AWS S3 bucket region to match this.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Default output format:&lt;/strong&gt; Choose json for the output format, or leave it as the default (None).&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Example:
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ aws configure
AWS Access Key ID [None]: your-access-key-id
AWS Secret Access Key [None]: your-secret-access-key
Default region name [None]: us-east-1
Default output format [None]: json
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Check if AWS CLI is installed correctly by running:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;aws --version
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  2. Configure .env
&lt;/h3&gt;

&lt;p&gt;Create a .env file to store sensitive information like your API keys and AWS bucket name. Add the following entries:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;echo "OPENWEATHER_API_KEY=your key here" &amp;gt;&amp;gt; .env
echo "AWS_BUCKET_NAME=weather-dashboard-joseph" &amp;gt;&amp;gt; .env
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Make sure to replace your key here with your actual OpenWeather API key and weather-dashboard-joseph with your S3 bucket name.&lt;/p&gt;

&lt;h2&gt;
  
  
  Running the Project
&lt;/h2&gt;

&lt;p&gt;Here is the script that fetches weather data and uploads it to AWS S3:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import os
import json
import boto3
import requests
from datetime import datetime
from dotenv import load_dotenv

# Load environment variables
load_dotenv()

class WeatherDashboard:
    def __init__(self):
        self.api_key = os.getenv('OPENWEATHER_API_KEY')
        self.bucket_name = os.getenv('AWS_BUCKET_NAME')
        self.s3_client = boto3.client('s3')

    def create_bucket_if_not_exists(self):
        """Create S3 bucket if it doesn't exist"""
        try:
            self.s3_client.head_bucket(Bucket=self.bucket_name)
            print(f"Bucket {self.bucket_name} exists")
        except:
            print(f"Creating bucket {self.bucket_name}")
        try:
            # Simpler creation for us-east-1
            self.s3_client.create_bucket(Bucket=self.bucket_name)
            print(f"Successfully created bucket {self.bucket_name}")
        except Exception as e:
            print(f"Error creating bucket: {e}")

    def fetch_weather(self, city):
        """Fetch weather data from OpenWeather API"""
        base_url = "http://api.openweathermap.org/data/2.5/weather"
        params = {
            "q": city,
            "appid": self.api_key,
            "units": "imperial"
        }

        try:
            response = requests.get(base_url, params=params)
            response.raise_for_status()
            return response.json()
        except requests.exceptions.RequestException as e:
            print(f"Error fetching weather data: {e}")
            return None

    def save_to_s3(self, weather_data, city):
        """Save weather data to S3 bucket"""
        if not weather_data:
            return False

        timestamp = datetime.now().strftime('%Y%m%d-%H%M%S')
        file_name = f"weather-data/{city}-{timestamp}.json"

        try:
            weather_data['timestamp'] = timestamp
            self.s3_client.put_object(
                Bucket=self.bucket_name,
                Key=file_name,
                Body=json.dumps(weather_data),
                ContentType='application/json'
            )
            print(f"Successfully saved data for {city} to S3")
            return True
        except Exception as e:
            print(f"Error saving to S3: {e}")
            return False

def main():
    dashboard = WeatherDashboard()

    # Create bucket if needed
    dashboard.create_bucket_if_not_exists()

    cities = ["Philadelphia", "Seattle", "New York"]

    for city in cities:
        print(f"\nFetching weather for {city}...")
        weather_data = dashboard.fetch_weather(city)
        if weather_data:
            temp = weather_data['main']['temp']
            feels_like = weather_data['main']['feels_like']
            humidity = weather_data['main']['humidity']
            description = weather_data['weather'][0]['description']

            print(f"Temperature: {temp}°F")
            print(f"Feels like: {feels_like}°F")
            print(f"Humidity: {humidity}%")
            print(f"Conditions: {description}")

            # Save to S3
            success = dashboard.save_to_s3(weather_data, city)
            if success:
                print(f"Weather data for {city} saved to S3!")
        else:
            print(f"Failed to fetch weather data for {city}")

if __name__ == "__main__":
    main()
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&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%2Fkwpg6de1lryrcfgtd7yb.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%2Fkwpg6de1lryrcfgtd7yb.png" alt="script" width="800" height="423"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Run the Script
&lt;/h3&gt;

&lt;p&gt;Once the setup is complete, you can run the weather_dashboard.py script to fetch weather data and upload it to the AWS S3 bucket:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;python src/weather_dashboard.py
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This will pull the latest weather data from the OpenWeather API and upload it to your AWS S3 bucket.&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%2Fk0agey2nesmevdh4sywg.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%2Fk0agey2nesmevdh4sywg.png" alt="python output" width="800" height="462"&gt;&lt;/a&gt;  &lt;/p&gt;

&lt;h3&gt;
  
  
  2. Verify Your S3 Bucket
&lt;/h3&gt;

&lt;p&gt;Log in to your AWS account and navigate to your S3 bucket to verify that the weather data has been successfully uploaded. If you don't want to accumulate unnecessary costs, be sure to empty and delete the contents of your bucket after verification.&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%2Fv29f95801e1bcovp0z0i.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%2Fv29f95801e1bcovp0z0i.png" alt="s3 output 1" width="800" height="350"&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%2Fuvkg3k5v8cyxqzq9lyfv.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%2Fuvkg3k5v8cyxqzq9lyfv.png" alt="output 2" width="800" height="353"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>aws</category>
      <category>python</category>
      <category>cloud</category>
      <category>devops</category>
    </item>
    <item>
      <title>Building a Scalable Web Server on AWS: A Hands-On Guide to Linux, Apache, and SSL Configuration</title>
      <dc:creator>Joseph Ibeh</dc:creator>
      <pubDate>Wed, 08 Jan 2025 12:08:57 +0000</pubDate>
      <link>https://dev.to/sir-j/building-a-scalable-web-server-on-aws-a-hands-on-guide-to-linux-apache-and-ssl-configuration-3cmh</link>
      <guid>https://dev.to/sir-j/building-a-scalable-web-server-on-aws-a-hands-on-guide-to-linux-apache-and-ssl-configuration-3cmh</guid>
      <description>&lt;p&gt;&lt;strong&gt;Introduction&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
Building a web server from scratch is an essential skill for any cloud or DevOps engineer. This project walks you through provisioning a Linux server, installing Apache, deploying a custom HTML landing page, and securing the server with SSL encryption. Whether you're a beginner or looking to solidify your skills, this guide provides practical steps to help you deploy a scalable and secure web server.  &lt;/p&gt;
&lt;h3&gt;
  
  
  &lt;strong&gt;Objective&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;The main goals of this project are:  &lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Provision a Linux server on AWS.
&lt;/li&gt;
&lt;li&gt;Install and configure Apache as a web server.
&lt;/li&gt;
&lt;li&gt;Create and deploy a custom HTML landing page.
&lt;/li&gt;
&lt;li&gt;Configure networking to allow HTTP (port 80) and optionally HTTPS (port 443) traffic.
&lt;/li&gt;
&lt;li&gt;Secure the server with SSL encryption using Certbot.
&lt;/li&gt;
&lt;/ol&gt;
&lt;h3&gt;
  
  
  &lt;strong&gt;Tools and Technologies Used&lt;/strong&gt;
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Cloud Platform&lt;/strong&gt;: AWS (Amazon Web Services)
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Linux Distribution&lt;/strong&gt;: Ubuntu
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Web Server&lt;/strong&gt;: Apache
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;SSH&lt;/strong&gt;: For server connection and management
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;HTML&lt;/strong&gt;: To design the landing page
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Certbot&lt;/strong&gt;: To manage SSL certificates for HTTPS
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;
  
  
  &lt;strong&gt;Steps to Build the Project&lt;/strong&gt;
&lt;/h3&gt;
&lt;h4&gt;
  
  
  &lt;strong&gt;1. Provisioning the Server on AWS&lt;/strong&gt;
&lt;/h4&gt;

&lt;p&gt;&lt;strong&gt;Step 1: Sign In to AWS&lt;/strong&gt;  &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Go to the &lt;a href="https://aws.amazon.com/" rel="noopener noreferrer"&gt;AWS Management Console&lt;/a&gt;.
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Step 2: Launch a New Instance&lt;/strong&gt;  &lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Navigate to EC2 and click "Launch Instance."
&lt;/li&gt;
&lt;li&gt;Choose an Ubuntu Linux AMI (e.g., Ubuntu 22.04 LTS).
&lt;/li&gt;
&lt;li&gt;Configure instance settings:

&lt;ul&gt;
&lt;li&gt;Assign a public IP for accessibility.
&lt;/li&gt;
&lt;li&gt;Choose an instance type (e.g., t2.micro for free tier users).
&lt;/li&gt;
&lt;/ul&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%2Fzpe6fhuaejqo3unq5i6e.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%2Fzpe6fhuaejqo3unq5i6e.png" alt="aws log in" width="800" height="376"&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%2Fusspmf3bmwcw1r2ve5ie.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%2Fusspmf3bmwcw1r2ve5ie.png" alt="launch instance" width="800" height="346"&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%2F86f0v1hg1mgwojoh8vqv.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%2F86f0v1hg1mgwojoh8vqv.png" alt="server name" width="800" height="345"&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%2F7ghh4eyve3q4wt9fohp5.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%2F7ghh4eyve3q4wt9fohp5.png" alt="AMI" width="800" height="347"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 3: Configure Key Pair&lt;/strong&gt;  &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Create a new key pair and download the private key file (.pem).
&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%2Fb9cgtwqfdh6iv894kv39.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%2Fb9cgtwqfdh6iv894kv39.png" alt="Key pair" width="800" height="347"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 4: Configure Security Group&lt;/strong&gt;  &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Allow the following inbound rules:

&lt;ul&gt;
&lt;li&gt;HTTP (port 80)
&lt;/li&gt;
&lt;li&gt;HTTPS (port 443)
&lt;/li&gt;
&lt;li&gt;SSH (port 22)
&lt;/li&gt;
&lt;/ul&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%2Fepnrcauzkf179ehah07u.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%2Fepnrcauzkf179ehah07u.png" alt="SG" width="800" height="346"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 5: Launch the Instance&lt;/strong&gt;  &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Click "Launch Instance" and wait for it to start running.
&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%2F9ss4kp6ks6uo13unug6a.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%2F9ss4kp6ks6uo13unug6a.png" alt="launch instance" width="800" height="346"&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%2Fy7k6v2wngbs7037j6u56.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%2Fy7k6v2wngbs7037j6u56.png" alt="Instance running" width="800" height="346"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h4&gt;
  
  
  &lt;strong&gt;2. Connecting to the Server&lt;/strong&gt;
&lt;/h4&gt;

&lt;ol&gt;
&lt;li&gt;Open a terminal or Git Bash.
&lt;/li&gt;
&lt;li&gt;Use the private key to SSH into the server:
&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;   ssh &lt;span class="nt"&gt;-i&lt;/span&gt; path_to_private_key.pem ubuntu@public_ip_address  
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&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%2Flpifeiurlz2w75vcf893.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%2Flpifeiurlz2w75vcf893.png" alt="SSHing" width="800" height="347"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h4&gt;
  
  
  &lt;strong&gt;3. Setting Up the Web Server&lt;/strong&gt;
&lt;/h4&gt;

&lt;p&gt;-Switch to root user &lt;code&gt;sudo -i&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%2F8gu3z0w80bvzy5kasghp.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%2F8gu3z0w80bvzy5kasghp.png" alt="root user" width="415" height="51"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 1: Update the System&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;apt update &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nb"&gt;sudo &lt;/span&gt;apt upgrade &lt;span class="nt"&gt;-y&lt;/span&gt;  
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Step 2: Install Apache&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;apt &lt;span class="nb"&gt;install &lt;/span&gt;apache2 &lt;span class="nt"&gt;-y&lt;/span&gt;  
&lt;span class="nb"&gt;sudo &lt;/span&gt;systemctl start apache2  
&lt;span class="nb"&gt;sudo &lt;/span&gt;systemctl &lt;span class="nb"&gt;enable &lt;/span&gt;apache2  
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&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%2Fjqko6uy6ub63fxnl6ong.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%2Fjqko6uy6ub63fxnl6ong.png" alt="apache" width="800" height="510"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 3: Verify Apache Installation&lt;/strong&gt;  &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Open a browser and navigate to the server's public IP address. You should see the Apache default page.
&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  &lt;strong&gt;4. Deploying a Custom HTML Landing Page&lt;/strong&gt;
&lt;/h4&gt;

&lt;p&gt;&lt;strong&gt;Step 1: Create the HTML File&lt;/strong&gt;  &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Open the Apache default directory:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;  &lt;span class="nb"&gt;sudo &lt;/span&gt;vim /var/www/html/index.html  
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Add your custom HTML content:
&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%2Fxvpzo540uxm7s3vungei.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%2Fxvpzo540uxm7s3vungei.png" alt="html content" width="800" height="709"&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%2F9ocwgndwc3qb6bgtzorp.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%2F9ocwgndwc3qb6bgtzorp.png" alt="html content contd" width="800" height="763"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 2: Save and Exit&lt;/strong&gt;  &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 3: Test the Landing Page&lt;/strong&gt;  &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Open a browser and visit the server’s public IP address.
&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%2Fje4rtsegapiohjkqejxa.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%2Fje4rtsegapiohjkqejxa.png" alt="landing page 1" width="800" height="402"&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%2Ftvq16msych6t68tvsqm9.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%2Ftvq16msych6t68tvsqm9.png" alt="landing page 2 ns" width="800" height="401"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  &lt;strong&gt;5. Configuring SSL for HTTPS&lt;/strong&gt;
&lt;/h4&gt;

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

&lt;ul&gt;
&lt;li&gt;Purchase a domain name (e.g., &lt;code&gt;yourname.com&lt;/code&gt;).
&lt;/li&gt;
&lt;li&gt;Update your domain's DNS settings to point to your server's public IP address.
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Step 1: Install Certbot&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;apt &lt;span class="nb"&gt;install &lt;/span&gt;certbot python3-certbot-apache &lt;span class="nt"&gt;-y&lt;/span&gt;  
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Step 2: Obtain an SSL Certificate&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;certbot &lt;span class="nt"&gt;--apache&lt;/span&gt; &lt;span class="nt"&gt;-d&lt;/span&gt; yourname.com &lt;span class="nt"&gt;-d&lt;/span&gt; www.yourname.com  
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&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%2F92dpiw9zm2ys343554ok.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%2F92dpiw9zm2ys343554ok.png" alt="certbot" width="800" height="386"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 3: Verify HTTPS&lt;/strong&gt;  &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Open a browser and navigate to &lt;code&gt;https://yourname.com&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%2F4a4gjh96ebqqbb3oiq0t.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%2F4a4gjh96ebqqbb3oiq0t.png" alt="landing page s" width="800" height="400"&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%2Fznwbqtfpjjy8ohftx322.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%2Fznwbqtfpjjy8ohftx322.png" alt="landing page 2 s" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Conclusion&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;This project highlights the essential steps to provision a server, deploy a web server, and secure it with HTTPS. By following this guide, you’ll gain hands-on experience with server management, web hosting, and cloud technologies.  &lt;/p&gt;

&lt;p&gt;Feel free to customize this project and share your version with the tech community. Let’s keep building and learning together!  &lt;/p&gt;

</description>
      <category>aws</category>
      <category>linux</category>
    </item>
    <item>
      <title>Cloud Computing Simplified: Models, Services, and the Future of Technology</title>
      <dc:creator>Joseph Ibeh</dc:creator>
      <pubDate>Mon, 09 Dec 2024 12:33:55 +0000</pubDate>
      <link>https://dev.to/sir-j/cloud-computing-simplified-models-services-and-the-future-of-technology-n3f</link>
      <guid>https://dev.to/sir-j/cloud-computing-simplified-models-services-and-the-future-of-technology-n3f</guid>
      <description>&lt;p&gt;Cloud computing has changed how we store, access, and manage data. It offers flexible, affordable, and powerful solutions that help businesses and individuals focus on what matters most. As more organizations adopt cloud technologies, understanding the basics is becoming essential.  &lt;/p&gt;

&lt;p&gt;In this guide, I’ll explain cloud computing, break down its key models, introduce its services, and highlight how it’s shaping industries and innovation.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Table of Contents&lt;/strong&gt;  &lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Introduction&lt;/li&gt;
&lt;li&gt;Why Use Cloud Computing?&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Cloud Deployment Models&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;On-Premise Computing
&lt;/li&gt;
&lt;li&gt;Public Cloud
&lt;/li&gt;
&lt;li&gt;Private Cloud
&lt;/li&gt;
&lt;li&gt;Hybrid Cloud&lt;/li&gt;
&lt;li&gt;Community Cloud&lt;/li&gt;
&lt;li&gt;Multi-Cloud&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Cloud Services&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;IaaS
&lt;/li&gt;
&lt;li&gt;PaaS
&lt;/li&gt;
&lt;li&gt;SaaS
&lt;/li&gt;
&lt;li&gt;DaaS
&lt;/li&gt;
&lt;li&gt;STaaS
&lt;/li&gt;
&lt;li&gt;FaaS
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Conclusion&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;Introduction&lt;/strong&gt;  &lt;/p&gt;

&lt;p&gt;Cloud computing lets you access computing power over the internet instead of relying on expensive, on-site hardware. Whether you’re a business owner or a tech enthusiast, the cloud helps reduce costs, increase flexibility, and speed up innovation.  &lt;/p&gt;

&lt;p&gt;Let’s explore how it works, step by step.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Why Use Cloud Computing?&lt;/strong&gt;  &lt;/p&gt;

&lt;p&gt;Here are five reasons why businesses are embracing cloud computing:  &lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Cost Savings&lt;/strong&gt;: You only pay for what you use—no need to buy expensive hardware upfront.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Scalability&lt;/strong&gt;: Easily adjust resources as your needs grow or shrink.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Accessibility&lt;/strong&gt;: Work from anywhere with an internet connection.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Security&lt;/strong&gt;: Top providers offer advanced protections against cyber threats.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Speed&lt;/strong&gt;: Quickly develop, test, and deploy projects to stay ahead.
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Cloud computing simplifies IT so you can focus on building ideas instead of managing hardware.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Cloud Deployment Models&lt;/strong&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%2Fmdahu5f59pr1vbf00wdx.jpeg" 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%2Fmdahu5f59pr1vbf00wdx.jpeg" alt="Cloud deployment model" width="640" height="480"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Cloud computing can be set up in different ways, depending on your needs:  &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1. On-Premise Computing&lt;/strong&gt;&lt;br&gt;
This is the traditional approach where everything is managed in-house.  &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Pros&lt;/strong&gt;: Full control over data; suitable for strict security needs.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Cons&lt;/strong&gt;: Expensive and hard to scale.
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;2. Public Cloud&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
Public clouds are shared by multiple users and managed by providers like AWS or Google Cloud.  &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Pros&lt;/strong&gt;: Cost-effective and scalable.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Cons&lt;/strong&gt;: Less customization; potential security concerns.
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;3. Private Cloud&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
A private cloud is dedicated to one organization, offering more control.  &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Pros&lt;/strong&gt;: Highly secure and customizable.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Cons&lt;/strong&gt;: Expensive and complex to maintain.
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;4. Hybrid Cloud&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
Mixing private and public clouds for flexibility.  &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Pros&lt;/strong&gt;: Combines local security with public cloud scalability.
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;5. Community Cloud&lt;/strong&gt;&lt;br&gt;
A community cloud is a shared cloud infrastructure tailored for a specific group of users or organizations with shared concerns, such as compliance, security, or mission-critical goals.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Pros&lt;/strong&gt; Costs are shared among participating organizations, enabling secure collaboration within the community, with access limited to members, making it more secure than public clouds.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Cons:&lt;/strong&gt; Managing shared resources requires coordination among all parties and community clouds offer less scalability compared to public cloud solutions. Use Cases include healthcare with hospitals sharing patient data while ensuring HIPAA compliance, government agencies collaborating on secure joint initiatives, and education with universities sharing research infrastructure and tools.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;6. Multi-Cloud&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
Using services from multiple cloud providers.  &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Pros&lt;/strong&gt;: Using services from multiple cloud providers avoids reliance on a single provider while offering increased reliability through fault tolerance, improved disaster recovery, and higher system availability.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Cons&lt;/strong&gt;: Managing multiple cloud providers can introduce complexity, lead to higher operational costs, and increase security risks due to varying security protocols across providers.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Cloud Services&lt;/strong&gt;  &lt;/p&gt;

&lt;p&gt;Cloud computing isn’t just about storing data. Here are its main types of services:&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%2F67zekfoowzjyq6wwhawh.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%2F67zekfoowzjyq6wwhawh.png" alt="Cloud services" width="800" height="509"&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%2Fjhs5ujltkyo9s7q62x74.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%2Fjhs5ujltkyo9s7q62x74.png" alt="cloud services" width="574" height="534"&gt;&lt;/a&gt;&lt;br&gt;
&lt;strong&gt;1. Infrastructure as a Service (IaaS)&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
Think of IaaS as renting virtual servers and storage online.  &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Examples&lt;/strong&gt;: Amazon EC2, Azure Virtual Machines.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Uses&lt;/strong&gt;: Hosting websites, running applications.
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;2. Platform as a Service (PaaS)&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
PaaS provides tools to build and launch apps without managing the hardware.  &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Examples&lt;/strong&gt;: Heroku, Google App Engine.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Uses&lt;/strong&gt;: Streamlining app development.
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;3. Software as a Service (SaaS)&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
SaaS delivers ready-to-use apps over the internet, often subscription-based.  &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Examples&lt;/strong&gt;: Google Workspace, Salesforce.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Uses&lt;/strong&gt;: Productivity tools, CRM software.
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;4. Desktop as a Service (DaaS)&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
DaaS provides virtual desktops that can be accessed from any device.  &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Examples&lt;/strong&gt;: Amazon WorkSpaces, Citrix.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Uses&lt;/strong&gt;: Remote work setups.
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;5. Storage as a Service (STaaS)&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
STaaS offers flexible cloud storage for businesses and individuals.  &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Examples&lt;/strong&gt;: Amazon S3, Google Cloud Storage.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Uses&lt;/strong&gt;: Backups, disaster recovery.
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;6. Function as a Service (FaaS)&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
FaaS is about running code without managing servers, also known as serverless computing.  &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Examples&lt;/strong&gt;: AWS Lambda, Azure Functions.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Uses&lt;/strong&gt;: Event-driven apps like chatbots.
&lt;/li&gt;
&lt;/ul&gt;

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

&lt;p&gt;Cloud computing is transforming industries by making technology accessible, affordable, and efficient. From IaaS to SaaS, these services empower businesses to innovate faster and smarter.  &lt;/p&gt;

&lt;p&gt;The future of computing is in the cloud. Whether you’re just starting or looking to dive deeper, there’s no better time to explore its potential.  &lt;/p&gt;

</description>
    </item>
    <item>
      <title>The Language of the Internet: A Simple Guide to Communication Protocols</title>
      <dc:creator>Joseph Ibeh</dc:creator>
      <pubDate>Wed, 04 Dec 2024 16:32:19 +0000</pubDate>
      <link>https://dev.to/sir-j/the-language-of-the-internet-a-simple-guide-to-communication-protocols-543n</link>
      <guid>https://dev.to/sir-j/the-language-of-the-internet-a-simple-guide-to-communication-protocols-543n</guid>
      <description>&lt;p&gt;&lt;strong&gt;Table of Contents&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Introduction
&lt;/li&gt;
&lt;li&gt;What Are Communication Protocols?

&lt;ul&gt;
&lt;li&gt;2.1 Why Are Protocols Important?
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;The OSI Model

&lt;ul&gt;
&lt;li&gt;3.1 Layers of the OSI Model
&lt;/li&gt;
&lt;li&gt;3.2 Why the OSI Model Matters
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Common Types of Protocols

&lt;ul&gt;
&lt;li&gt;4.1 Common Everyday Protocols
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Conclusion&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;1. Introduction&lt;/strong&gt; &lt;/p&gt;

&lt;p&gt;Imagine you're mailing a birthday gift to a friend. For the gift to reach its destination, you’ll need the correct address, proper packaging, and a delivery service. In networking, &lt;strong&gt;communication protocols&lt;/strong&gt; act like these rules—they guide how data is packaged, sent, and delivered so devices can communicate.&lt;/p&gt;

&lt;p&gt;When you stream a video on YouTube, send an email, or browse Instagram, these rules ensure that everything works smoothly. This article will explain what communication protocols are, why they matter, and how they work in networking.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. What Are Communication Protocols?&lt;/strong&gt;  &lt;/p&gt;

&lt;p&gt;Communication protocols are like a universal language for devices, allowing them to understand and exchange data. These rules control how data is broken into smaller parts, sent, and reassembled at its destination.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2.1 Why Are Protocols Important?&lt;/strong&gt; &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Interoperability&lt;/strong&gt;:
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Example&lt;/strong&gt;: Imagine trying to charge your phone with a charger from another country. Without universal USB standards, it wouldn’t work. Similarly, protocols ensure devices from different manufacturers can connect and share information.  &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Efficiency&lt;/strong&gt;:
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Example&lt;/strong&gt;: When you stream a Netflix movie, protocols manage the flow of data so you don’t experience buffering.  &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Security&lt;/strong&gt;:
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Example&lt;/strong&gt;: When you shop online, HTTPS ensures your credit card details are encrypted and protected.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3. The OSI Model&lt;/strong&gt; &lt;/p&gt;

&lt;p&gt;The OSI model is like a team of delivery workers who handle a package in steps, from pickup to delivery. It breaks networking into &lt;strong&gt;seven layers&lt;/strong&gt;, with each layer performing a specific role to ensure successful communication.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3.1 Layers of the OSI Model&lt;/strong&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%2Fbskhsors57tfrpbnmd11.jpg" 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%2Fbskhsors57tfrpbnmd11.jpg" alt="OSI Model" width="560" height="456"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Physical Layer&lt;/strong&gt;:  &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;What it does&lt;/strong&gt;: Transmits raw data as electrical signals.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Example&lt;/strong&gt;: The cables connecting your Wi-Fi router to the internet.
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Data Link Layer&lt;/strong&gt;:  &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;What it does&lt;/strong&gt;: Ensures data isn’t lost or damaged.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Example&lt;/strong&gt;: When you print a document over Wi-Fi, this layer ensures the connection between your computer and printer is reliable.
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Network Layer&lt;/strong&gt;:  &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;What it does&lt;/strong&gt;: Finds the best route for data to travel.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Example&lt;/strong&gt;: Like GPS guiding a car, this layer helps emails travel through different networks to reach the correct inbox.
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Transport Layer&lt;/strong&gt;:  &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;What it does&lt;/strong&gt;: Ensures data is delivered without errors.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Example&lt;/strong&gt;: When you download a file, this layer checks all parts of the file are received in order.
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Session Layer&lt;/strong&gt;:  &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;What it does&lt;/strong&gt;: Manages conversations between devices.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Example&lt;/strong&gt;: Keeps your video call stable and ensures it doesn’t drop midway.
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Presentation Layer&lt;/strong&gt;:  &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;What it does&lt;/strong&gt;: Converts data into a readable format.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Example&lt;/strong&gt;: Translates a YouTube video’s file format so it can play on your browser.
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Application Layer&lt;/strong&gt;:  &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;What it does&lt;/strong&gt;: Interacts with you directly.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Example&lt;/strong&gt;: Loading Instagram photos or sending WhatsApp messages.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;3.2 Why the OSI Model Matters&lt;/strong&gt;  &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Easy Troubleshooting&lt;/strong&gt;: If your Zoom call fails, the OSI model helps engineers check whether the issue is in the network connection, session management, or video decoding.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Integration&lt;/strong&gt;: New tech, like 5G, can fit into specific OSI layers without affecting the rest.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;4. Common Types of Protocols&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
Protocols exist for every layer of the OSI model. Here are some examples you’ve probably encountered:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;4.1 Everyday Protocols You Use&lt;/strong&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%2F8jav4rnfg8gifb8rc2a4.jpeg" 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%2F8jav4rnfg8gifb8rc2a4.jpeg" alt="Protocols examples" width="761" height="403"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;HTTP/HTTPS (Application Layer)&lt;/strong&gt;:

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Example&lt;/strong&gt;: When you type a URL in your browser, HTTP fetches the webpage, while HTTPS encrypts it for safety.
&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

&lt;strong&gt;FTP (File Transfer Protocol)&lt;/strong&gt;:

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Example&lt;/strong&gt;: Uploading photos to Google Drive or downloading documents from a website.
&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

&lt;strong&gt;TCP (Transport Layer)&lt;/strong&gt;:

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Example&lt;/strong&gt;: Ensures your WhatsApp messages arrive in order, even if the network is unstable.
&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

&lt;strong&gt;UDP (User Datagram Protocol)&lt;/strong&gt;:

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Example&lt;/strong&gt;: Used in live gaming or video streaming, where speed matters more than reliability.
&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

&lt;strong&gt;IP (Network Layer)&lt;/strong&gt;:

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Example&lt;/strong&gt;: Works like a mailing address, ensuring your data gets to the right recipient.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;5. Conclusion&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
Communication protocols and the OSI model are like the invisible engines of the internet. They ensure smooth, efficient, and secure communication between devices. From browsing the web to sending messages, these systems work tirelessly to keep everything running.&lt;br&gt;
So next time you stream a video or send an email, you’ll know the magic that makes it happen!&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Mastering IP Addresses: A Comprehensive Guide to Understanding, Calculating, and Classifying Network Addresses</title>
      <dc:creator>Joseph Ibeh</dc:creator>
      <pubDate>Tue, 26 Nov 2024 06:38:36 +0000</pubDate>
      <link>https://dev.to/sir-j/mastering-ip-addresses-a-comprehensive-guide-to-understanding-calculating-and-classifying-46g8</link>
      <guid>https://dev.to/sir-j/mastering-ip-addresses-a-comprehensive-guide-to-understanding-calculating-and-classifying-46g8</guid>
      <description>&lt;p&gt;&lt;strong&gt;Table of Contents&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;What is an IP Address?&lt;/li&gt;
&lt;li&gt;Types of IP Addresses

&lt;ul&gt;
&lt;li&gt;Public IP Address&lt;/li&gt;
&lt;li&gt;Private IP Address&lt;/li&gt;
&lt;li&gt;Static IP Address&lt;/li&gt;
&lt;li&gt;Dynamic IP Address&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Classes of IP Addresses

&lt;ul&gt;
&lt;li&gt;Class A&lt;/li&gt;
&lt;li&gt;Class B&lt;/li&gt;
&lt;li&gt;Class C&lt;/li&gt;
&lt;li&gt;Class D&lt;/li&gt;
&lt;li&gt;Class E&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Netmask and Subnetting

&lt;ul&gt;
&lt;li&gt;What is a Netmask?&lt;/li&gt;
&lt;li&gt;Subnetting Explained&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;How to Convert an Octet to Binary&lt;/li&gt;
&lt;li&gt;How to Calculate IP Address and Netmask

&lt;ul&gt;
&lt;li&gt;Example Calculation&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;CIDR Notation&lt;/li&gt;
&lt;li&gt;Conclusion.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;Introduction&lt;/strong&gt;&lt;br&gt;
In the world of computer networking, an IP address (Internet Protocol address) is essential for identifying and communicating with devices over a network. Every device that connects to the internet or any other network must have a unique IP address. These addresses are crucial for routing data packets between devices across different networks, ensuring that information reaches its intended destination.&lt;br&gt;
In this article, we'll explore the following:&lt;br&gt;
What IP addresses are&lt;br&gt;
The different types of IP addresses&lt;br&gt;
The concept of netmasks&lt;br&gt;
How to calculate them&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1. What is an IP Address?&lt;/strong&gt;&lt;br&gt;
An IP address is a unique identifier assigned to a device or network interface on a network. It helps route traffic across the internet or local networks, allowing devices to locate and communicate with each other.&lt;br&gt;
There are two main versions of IP addresses:&lt;br&gt;
&lt;code&gt;IPv4&lt;/code&gt; (Internet Protocol version 4): The most widely used format, consisting of four 8-bit octets (32 bits), written as four decimal numbers separated by periods (e.g., 192.168.1.1).&lt;br&gt;
&lt;code&gt;IPv6&lt;/code&gt; (Internet Protocol version 6): Introduced to overcome the limitations of IPv4 (mainly address exhaustion), it uses 128-bit addresses, represented as eight 16-bit groups separated by colons (e.g., 2001:0db8:85a3:0000:0000:8a2e:0370:7334).&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. Types of IP Addresses&lt;/strong&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%2F4nikms337uf76phqpf2o.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%2F4nikms337uf76phqpf2o.png" alt="IP Types" width="685" height="448"&gt;&lt;/a&gt;&lt;br&gt;
IP addresses are categorized based on their usage and purpose. The main types include:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Public IP Address&lt;br&gt;
A public IP address is routable on the internet. These addresses are assigned to devices or networks by an Internet Service Provider (ISP) and are used for identifying devices on the internet, enabling communication with others over the web. Examples of public IP addresses include:8.8.8.8 (Google's public DNS server) 208.67.222.222 (OpenDNS server)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Private IP Address&lt;br&gt;
A private IP address is used within local networks, such as in homes, offices, or enterprise environments. These addresses are not routable over the internet but are used for internal communication. The private IP address ranges for IPv4 are:&lt;br&gt;
10.0.0.0 - 10.255.255.255&lt;br&gt;
172.16.0.0 - 172.31.255.255&lt;br&gt;
192.168.0.0 - 192.168.255.255&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Static IP Address: A static IP address is fixed and manually configured, such as a server with a permanent IP like 198.51.100.10.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Dynamic IP Address: A dynamic IP address is automatically assigned by a Dynamic Host Configuration Protocol (DHCP) server, such as a home computer with an IP like 192.168.1.5 that changes periodically.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;3.  Classes of IP Addresses&lt;/strong&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%2Fe1v055ousyg23bcq7rhz.jpeg" 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%2Fe1v055ousyg23bcq7rhz.jpeg" alt="IP classess" width="662" height="463"&gt;&lt;/a&gt;&lt;br&gt;
IP addresses are categorized into five classes, each serving different purposes based on the size of the network and the range of addresses required. The classes are as follows:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;Class A (0.0.0.0 to 127.255.255.255)&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Range: 1.0.0.0 - 127.255.255.255
&lt;/li&gt;
&lt;li&gt;Purpose: Designed for large networks, typically used by very large organizations, government bodies, and ISPs.&lt;/li&gt;
&lt;li&gt;Network Size: Up to 16 million hosts per network.&lt;/li&gt;
&lt;li&gt;Default Subnet Mask: &lt;code&gt;255.0.0.0&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Class B (128.0.0.0 to 191.255.255.255)&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Range: 128.0.0.0 - 191.255.255.255
&lt;/li&gt;
&lt;li&gt;Purpose: Suitable for medium-sized networks, such as universities or large businesses.&lt;/li&gt;
&lt;li&gt;Network Size: Up to 65,000 hosts per network.&lt;/li&gt;
&lt;li&gt;Default Subnet Mask: &lt;code&gt;255.255.0.0&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Class C (192.0.0.0 to 223.255.255.255)&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Range: 192.0.0.0 - 223.255.255.255
&lt;/li&gt;
&lt;li&gt;Purpose: Designed for smaller networks, typically used by small businesses and home networks.&lt;/li&gt;
&lt;li&gt;Network Size: Up to 254 hosts per network.&lt;/li&gt;
&lt;li&gt;Default Subnet Mask: &lt;code&gt;255.255.255.0&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Class D (224.0.0.0 to 239.255.255.255)  &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Range: 224.0.0.0 - 239.255.255.255
&lt;/li&gt;
&lt;li&gt;Purpose: Reserved for multicast addresses. These are used for one-to-many communication, like streaming media.&lt;/li&gt;
&lt;li&gt;Network Size: N/A (for multicast communication)&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Class E (240.0.0.0 to 255.255.255.255) &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Range: 240.0.0.0 - 255.255.255.255
&lt;/li&gt;
&lt;li&gt;Purpose: Reserved for experimental use and future applications. These addresses are not used in general networking.&lt;/li&gt;
&lt;li&gt;Network Size: N/A&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;4. Netmask and Subnetting&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What is a Netmask?&lt;/strong&gt;&lt;br&gt;
A netmask is a 32-bit number that defines the network portion of an IP address. It works by masking (or blocking out) the host part of the IP address, leaving only the network portion visible. A netmask helps devices determine whether a destination IP address is within the same local network or needs to be routed to another network.&lt;br&gt;
&lt;strong&gt;Example:&lt;/strong&gt;&lt;br&gt;
IP Address: 192.168.1.1&lt;br&gt;
Netmask: 255.255.255.0&lt;br&gt;
In this example, the first 24 bits (192.168.1) represent the network, and the remaining 8 bits (.1) represent the host.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Subnetting&lt;/strong&gt;&lt;br&gt;
Subnetting is the process of dividing a larger network into smaller subnetworks (subnets). By applying different netmasks, subnetting allows network administrators to efficiently allocate IP addresses and improve network performance. Subnetting is especially useful in large networks where it’s necessary to organize devices into logical groups for efficient routing.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;5. How to Convert an Octet to Binary&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Understand Binary Numbers&lt;br&gt;
Binary numbers use only 1s and 0s, and each position represents a power of 2, from right to left:&lt;br&gt;
128  |  64  |  32  |  16  |  8  |  4  |  2  |  1&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Convert the Decimal Number to Binary&lt;br&gt;
Start with the decimal number and determine how many times each power of 2 fits into it. Write 1 if the power of 2 fits, and 0 if it doesn’t.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Example: Convert 192 to Binary&lt;/p&gt;

&lt;p&gt;For 192: 128 fits, so write 1. Subtract 128 from 192 → 192 - 128 = 64 remains.&lt;/p&gt;

&lt;p&gt;64 fits, so write 1. Subtract 64 from 64 → 64 - 64 = 0 remains.&lt;/p&gt;

&lt;p&gt;Thus, 192 in binary is 11000000.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;6. How to Calculate IP Address and Netmask&lt;/strong&gt;&lt;br&gt;
To calculate the network address from an IP address and netmask, follow these steps:&lt;br&gt;
Convert both the IP address and netmask to binary.&lt;br&gt;
Perform a binary AND operation between the IP address and netmask.&lt;br&gt;
Convert the resulting binary network address back to decimal.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Example Calculation:&lt;/strong&gt; Converting IP Address and Netmask&lt;/p&gt;

&lt;p&gt;We will work with the IP address 192.168.1.10 and the netmask 255.255.255.0.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 1&lt;/strong&gt;: Understand Binary Number.&lt;br&gt;
In binary, each digit represents a power of 2. The place values (from right to left) are:&lt;br&gt;
128 | 64 | 32 | 16 | 8 | 4 | 2 | 1&lt;br&gt;
&lt;strong&gt;Step 2&lt;/strong&gt;: Convert the Decimal Number to Binary&lt;br&gt;
Convert 192 to Binary:&lt;br&gt;
The decimal number is 192. Let's figure out which powers of 2 fit into 192:&lt;br&gt;
128 fits into 192, so we write 1.&lt;br&gt;
Subtract 128 from 192 → 192 - 128 = 64 remains.&lt;br&gt;
64 fits into 64, so we write 1.&lt;br&gt;
Subtract 64 from 64 → 64 - 64 = 0 remains.&lt;br&gt;
So, 192 in binary is: 11000000&lt;br&gt;
Convert 168 to Binary:&lt;br&gt;
The decimal number is 168. Let's figure out which powers of 2 fit into 168:&lt;br&gt;
128 fits into 168, so we write 1.&lt;br&gt;
Subtract 128 from 168 → 168 - 128 = 40 remains.&lt;br&gt;
32 fits into 40, so we write 1.&lt;br&gt;
Subtract 32 from 40 → 40 - 32 = 8 remains.&lt;br&gt;
8 fits into 8, so we write 1.&lt;br&gt;
Subtract 8 from 8 → 8 - 8 = 0 remains.&lt;br&gt;
So, 168 in binary is: 10101000&lt;br&gt;
Convert 1 to Binary:&lt;br&gt;
The decimal number is 1. Let's figure out which powers of 2 fit into 1:&lt;br&gt;
1 fits into 1, so we write 1.&lt;br&gt;
No remainder, so the binary representation is just 00000001 (we need 8 bits for each octet).&lt;br&gt;
So, 1 in binary is: 00000001&lt;br&gt;
Convert 10 to Binary:&lt;br&gt;
The decimal number is 10. Let's figure out which powers of 2 fit into 10:&lt;br&gt;
8 fits into 10, so we write 1.&lt;br&gt;
Subtract 8 from 10 → 10 - 8 = 2 remains.&lt;br&gt;
2 fits into 2, so we write 1.&lt;br&gt;
Subtract 2 from 2 → 2 - 2 = 0 remains.&lt;br&gt;
So, 10 in binary is: 00001010&lt;br&gt;
&lt;strong&gt;Step 3&lt;/strong&gt;: Convert the Netmask to Binary&lt;br&gt;
Convert 255 to Binary:&lt;br&gt;
The decimal number is 255. Let's figure out which powers of 2 fit into 255:&lt;br&gt;
128 fits into 255, so we write 1.&lt;br&gt;
Subtract 128 from 255 → 255 - 128 = 127 remains.&lt;br&gt;
64 fits into 127, so we write 1.&lt;br&gt;
Subtract 64 from 127 → 127 - 64 = 63 remains.&lt;br&gt;
32 fits into 63, so we write 1.&lt;br&gt;
Subtract 32 from 63 → 63 - 32 = 31 remains.&lt;br&gt;
16 fits into 31, so we write 1.&lt;br&gt;
Subtract 16 from 31 → 31 - 16 = 15 remains.&lt;br&gt;
8 fits into 15, so we write 1.&lt;br&gt;
Subtract 8 from 15 → 15 - 8 = 7 remains.&lt;br&gt;
4 fits into 7, so we write 1.&lt;br&gt;
Subtract 4 from 7 → 7 - 4 = 3 remains.&lt;br&gt;
2 fits into 3, so we write 1.&lt;br&gt;
Subtract 2 from 3 → 3 - 2 = 1 remains.&lt;br&gt;
1 fits into 1, so we write 1.&lt;br&gt;
Subtract 1 from 1 → 1 - 1 = 0 remains.&lt;br&gt;
So, 255 in binary is: 11111111&lt;br&gt;
Convert 0 to Binary:&lt;br&gt;
The decimal number is 0. Let's figure out which powers of 2 fit into 0:&lt;br&gt;
0 does not fit into any powers of 2, so we write 0 for all bits.&lt;br&gt;
So, 0 in binary is: 00000000&lt;br&gt;
&lt;strong&gt;Step 4&lt;/strong&gt;: Perform the AND Operation&lt;br&gt;
Now we perform the bitwise AND operation (using the IP address and the netmask):&lt;br&gt;
IP Address in Binary:&lt;br&gt;
11000000.10101000.00000001.00001010&lt;br&gt;
Netmask in Binary:&lt;br&gt;
11111111.11111111.11111111.00000000&lt;br&gt;
Perform the AND operation on each bit:&lt;br&gt;
First octet (192) AND 255: 11000000 (IP) AND 11111111 (Netmask) = 11000000 Result: 192&lt;br&gt;
Second octet (168) AND 255: 10101000 (IP) AND 11111111 (Netmask) = 10101000 Result: 168&lt;br&gt;
Third octet (1) AND 255: 00000001 (IP) AND 11111111 (Netmask) = 00000001 Result: 1&lt;br&gt;
Fourth octet (10) AND 0: 00001010 (IP) AND 00000000 (Netmask) = 00000000 Result: 0&lt;br&gt;
Final Network Address:&lt;br&gt;
The result of the AND operation is the network address, which is:&lt;br&gt;
192.168.1.0&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 5&lt;/strong&gt;: Calculate the Broadcast Address&lt;br&gt;
To calculate the broadcast address, we take the network address and set all the host bits (the bits corresponding to 0s in the netmask) to 1s.&lt;br&gt;
Network Address in Binary: 11000000.10101000.00000001.00000000&lt;br&gt;
Change the host bits (the last octet, where the netmask is 0) to 1s: 11000000.10101000.00000001.11111111&lt;br&gt;
Now convert the broadcast address back to decimal:&lt;br&gt;
11000000 → 192&lt;br&gt;
10101000 → 168&lt;br&gt;
00000001 → 1&lt;br&gt;
11111111 → 255&lt;br&gt;
Thus, the broadcast address is:&lt;br&gt;
192.168.1.255&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;7. CIDR Notation&lt;/strong&gt;&lt;br&gt;
CIDR (Classless Inter-Domain Routing) notation is a shorthand way to specify IP addresses and netmasks. Instead of writing the netmask as four octets, CIDR uses a slash (&lt;code&gt;/&lt;/code&gt;) followed by the number of bits used for the network part.&lt;br&gt;
Example:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;192.168.1.0/24&lt;/code&gt; means an IP address with a 24-bit network portion (i.e., the netmask is &lt;code&gt;255.255.255.0&lt;/code&gt;)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;8. Conclusion&lt;/strong&gt;&lt;br&gt;
Understanding how IP addresses work, how to calculate network addresses, and how to convert between decimal and binary is crucial for anyone working with networking. Whether you're setting up a local network or managing larger enterprise systems, these fundamental concepts will help you better understand and manage IP addresses and subnets.&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Understanding Networking and Internet Infrastructure: A Global Overview with Insights from Nigeria</title>
      <dc:creator>Joseph Ibeh</dc:creator>
      <pubDate>Sat, 23 Nov 2024 12:54:25 +0000</pubDate>
      <link>https://dev.to/sir-j/understanding-networking-and-internet-infrastructure-a-global-overview-with-insights-from-nigeria-2h30</link>
      <guid>https://dev.to/sir-j/understanding-networking-and-internet-infrastructure-a-global-overview-with-insights-from-nigeria-2h30</guid>
      <description>&lt;p&gt;In today’s digital world, networking is the backbone of our online interactions, enabling everything from browsing websites to sending emails. While the mechanics of the internet are similar across the globe, the infrastructure that supports it varies by region. In this article, we’ll explore the basics of networking, how the internet works, and examine key components of internet infrastructure, with a special focus on emerging markets like Nigeria.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;How Does the Internet Work?&lt;/strong&gt;&lt;br&gt;
The internet is a vast network of interconnected computers and servers that communicate via the &lt;code&gt;Internet Protocol (IP)&lt;/code&gt;. This system allows data to travel from one device to another across various networks, regardless of location. Here’s a simplified breakdown of how it works:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1.Data Request:&lt;/strong&gt; When you access a website, your device sends a request to the server hosting that website.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2.Routing:&lt;/strong&gt; The request is routed through multiple routers, cables, and switches across several networks until it reaches the server.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3.Response:&lt;/strong&gt; The server processes the request and sends the requested data (e.g., a web page) back.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;4.Display:&lt;/strong&gt; Your browser receives and interprets the data to display the content.&lt;br&gt;
This seamless communication relies on critical infrastructure, such as cables, data centers, and regulatory bodies, which ensure efficient global connectivity.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Cables: Connecting the World and Emerging Markets Like Nigeria&lt;/strong&gt;&lt;br&gt;
Submarine cables are the lifeblood of global internet connectivity. These undersea cables transfer massive amounts of data between continents, forming the foundation for all internet traffic.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;SEA-ME-WE 3&lt;/strong&gt;: Connecting Asia, the Middle East, and Europe, this cable is a significant global artery for internet traffic.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;TEA-2:&lt;/strong&gt; Operating between the Americas and Europe, this cable helps serve a large part of transatlantic data needs.&lt;br&gt;
In Nigeria, submarine cables like &lt;code&gt;MainOne and Glo-1&lt;/code&gt;are improving connectivity, linking West Africa to Europe and other parts of the world. These cables enable faster internet speeds and improve access to global services, fueling Nigeria’s digital economy.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The Role of Internet Governance: IANA and Regional Authorities&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The Internet Assigned Numbers Authority (IANA) plays a crucial role in global internet governance. IANA manages:&lt;br&gt;
&lt;strong&gt;IP Addresses:&lt;/strong&gt; Unique identifiers assigned to devices on a network.&lt;br&gt;
&lt;strong&gt;Domain Names:&lt;/strong&gt; Human-readable names that direct to specific IP addresses.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;IANA&lt;/strong&gt; works alongside regional bodies like the &lt;code&gt;Africa Network Information Centre (AFRINIC)&lt;/code&gt;, which manages IP address allocation across Africa, including Nigeria. Similarly, organizations such as &lt;code&gt;ICANN and RIPE NCC&lt;/code&gt; ensure global coordination and allocation of internet resources.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Internet Exchange Points (IXPs): Improving Local Connectivity&lt;/strong&gt;&lt;br&gt;
IXPs are key locations where different internet networks exchange traffic. By allowing local traffic to stay within the region, IXPs reduce latency and cut down on the costs associated with sending data across borders.&lt;br&gt;
Globally recognized IXPs like &lt;code&gt;LINX (London Internet Exchange) and DE-CIX (Frankfurt)&lt;/code&gt; handle enormous volumes of traffic, enhancing the efficiency of internet services. In Nigeria, the &lt;code&gt;Internet Exchange Point of Nigeria (IXPN)&lt;/code&gt; plays a critical role, interconnecting local Internet Service Providers (ISPs) and data centers. This reduces international traffic and improves the internet experience for Nigerian users.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Data Centers: Powering the Digital World, from Global Giants to Local Players&lt;/strong&gt;&lt;br&gt;
Data centers are the heart of the internet, housing the servers and systems that power websites, cloud services, and apps. Globally, companies like &lt;code&gt;Amazon Web Services (AWS), Google, and Microsoft&lt;/code&gt;operate massive data centers across multiple continents.&lt;br&gt;
However, as the demand for local content and services grows, regions like West Africa are developing their own data centers to support businesses. In Nigeria, data centers such as &lt;code&gt;Rack Centre, MainOne Data Center, and MDXi&lt;/code&gt; are playing a key role in Nigeria’s digital transformation. These facilities support cloud services, e-commerce platforms, fintech, and more, driving the country’s digital economy forward.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Why Networking Matters: A Global Perspective&lt;/strong&gt;&lt;br&gt;
Networking is essential for the seamless functioning of the internet. It ensures efficient communication between devices and allows us to access global content instantly. Key takeaways include:&lt;br&gt;
&lt;strong&gt;-Global Connectivity:&lt;/strong&gt; Submarine cables and IXPs ensure smooth international data exchange, benefiting users worldwide.&lt;br&gt;
&lt;strong&gt;-Local Optimization:&lt;/strong&gt; IXPs and regional data centers improve internet speeds and reliability for local markets, such as Nigeria.&lt;br&gt;
&lt;strong&gt;-Support for Digital Services:&lt;/strong&gt; Data centers are the backbone of cloud services and digital platforms, supporting everything from e-commerce to online banking.&lt;/p&gt;

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

&lt;p&gt;The internet is a global network that connects us all, but the infrastructure supporting it is diverse and region-specific. While developed markets have advanced connectivity systems, emerging markets like Nigeria are rapidly catching up, with submarine cables, local IXPs, and data centers driving digital growth.&lt;/p&gt;

&lt;p&gt;As cloud engineers, developers, and tech enthusiasts, it's crucial to understand the foundational elements that make the internet work. From the cables that connect continents to the data centers that power local services, every part of this ecosystem contributes to seamless digital experience.&lt;/p&gt;

</description>
      <category>networking</category>
    </item>
    <item>
      <title>Ansible Demystified: Your Ultimate Guide to Simplifying IT Automation and Boosting DevOps Efficiency</title>
      <dc:creator>Joseph Ibeh</dc:creator>
      <pubDate>Wed, 20 Nov 2024 12:02:25 +0000</pubDate>
      <link>https://dev.to/sir-j/ansible-demystified-your-ultimate-guide-to-simplifying-it-automation-and-boosting-devops-efficiency-obh</link>
      <guid>https://dev.to/sir-j/ansible-demystified-your-ultimate-guide-to-simplifying-it-automation-and-boosting-devops-efficiency-obh</guid>
      <description>&lt;p&gt;As a cloud engineer or someone venturing into DevOps, you've probably heard of Ansible. But what exactly is it, and why should you care? Let’s break it down step by step, so even if you’re a beginner, by the end of this article, you'll have a good grasp of what Ansible is and how it works.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What is Ansible?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Ansible is an &lt;em&gt;open-source&lt;/em&gt; IT automation tool. It simplifies tasks like configuring servers, deploying applications, and managing networks. Think of Ansible as your personal assistant in IT, helping you automate repetitive tasks so you can focus on what truly matters.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Here’s why Ansible is awesome:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Agentless: No software needs to be installed on the managed systems; Ansible uses SSH.&lt;/li&gt;
&lt;li&gt;Simple YAML Syntax: Ansible uses &lt;em&gt;YAML&lt;/em&gt; (Yet Another Markup Language) for its configuration files, making it easy to learn and write.&lt;/li&gt;
&lt;li&gt;Idempotent: Running the same Ansible command multiple times won’t change anything if the desired state is already achieved.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Why Use Ansible&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Imagine you need to configure 10 servers with identical settings. Doing this manually can be error-prone and time-consuming. With Ansible, you can define the configuration once and apply it to all servers in a matter of seconds.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Key Benefits:&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Consistency: Ensures all servers are configured the same way.&lt;/li&gt;
&lt;li&gt;Scalability: Manage hundreds or thousands of servers effortlessly.&lt;/li&gt;
&lt;li&gt;Efficiency: Automates mundane tasks, saving time and reducing errors.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;How Does Ansible Work?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Ansible works by connecting to your managed nodes (servers, devices, etc.) via SSH, applying the instructions you define in &lt;em&gt;Playbooks&lt;/em&gt;. Here’s the basic flow:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1. Control Node:&lt;/strong&gt; The machine where Ansible is installed. It sends instructions.&lt;br&gt;
&lt;strong&gt;2. Managed Nodes:&lt;/strong&gt; Servers or devices Ansible configures.&lt;br&gt;
&lt;strong&gt;3. Playbooks:&lt;/strong&gt; Files written in YAML that describe what Ansible should do.&lt;br&gt;
&lt;strong&gt;4. Modules:&lt;/strong&gt; Pre-built scripts that perform specific tasks like installing software, creating users, or restarting services.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Getting Started with Ansible&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1. Install Ansible&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;To get started, install Ansible on your control node (e.g., your laptop or a dedicated server). Here's how to install it on Linux:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;apt update
&lt;span class="nb"&gt;sudo &lt;/span&gt;apt &lt;span class="nb"&gt;install &lt;/span&gt;ansible 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For Mac users, use Homebrew:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;brew &lt;span class="nb"&gt;install &lt;/span&gt;ansible
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Windows users can install Ansible via WSL or use a virtual machine.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Do You Need Python?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Yes, you need to have Python installed to use Ansible. Ansible relies on Python to execute tasks, both on the control node (where you run Ansible) and the managed nodes (target servers or devices). Ansible supports Python 2.7 or Python 3.5+.&lt;/p&gt;

&lt;p&gt;You can check if Python is installed by running:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;python &lt;span class="nt"&gt;--version&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;or&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;python3 &lt;span class="nt"&gt;--version&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To install Python, visit the &lt;a href="https://www.python.org" rel="noopener noreferrer"&gt;Python website&lt;/a&gt; or use a package manager like &lt;code&gt;apt&lt;/code&gt; for Linux or &lt;code&gt;brew&lt;/code&gt; for Mac. Once Python is installed, you can then install Ansible.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. Set Up Your SSH Key Authentication&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Ansible uses SSH to connect to remote servers. To make the process seamless and secure, it’s recommended to use SSH key authentication rather than passwords.&lt;/p&gt;

&lt;p&gt;Generate SSH Key Pair:&lt;br&gt;
On your control node (where Ansible is running), generate an SSH key pair if you don’t have one already. You can do this by running:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;ssh-keygen &lt;span class="nt"&gt;-t&lt;/span&gt; rsa &lt;span class="nt"&gt;-b&lt;/span&gt; 4096 &lt;span class="nt"&gt;-C&lt;/span&gt; &lt;span class="s2"&gt;"your_email@example.com"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This will create two files:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A private key (typically located at &lt;code&gt;~/.ssh/id_rsa&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;A public key (located at &lt;code&gt;~/.ssh/id_rsa.pub&lt;/code&gt;).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Copy the Public Key to Managed Nodes:&lt;br&gt;
Now, copy the public key to your managed nodes (the servers you want to manage). You can do this using the &lt;code&gt;ssh-copy-id&lt;/code&gt; command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;ssh-copy-id username@your_server_ip
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This will enable password-less SSH access from your control node to the managed nodes.&lt;/p&gt;

&lt;p&gt;Verify SSH Connectivity:&lt;br&gt;
Once the key is copied, test the SSH connection by running:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;ssh username@your_server_ip
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If everything is set up correctly, you should be able to log in without entering a password.&lt;/p&gt;

&lt;p&gt;Now your Ansible setup is ready to communicate with the managed nodes using SSH keys, providing a secure and efficient way to manage your infrastructure.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3. Set Up Your Inventory File&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Ansible needs to know which servers to manage. This is done using an inventory file. Create a file called &lt;code&gt;inventory&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ini"&gt;&lt;code&gt;&lt;span class="nn"&gt;[webservers]&lt;/span&gt;
&lt;span class="err"&gt;192.168.1.101&lt;/span&gt;
&lt;span class="err"&gt;192.168.1.102&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here, &lt;code&gt;[webservers]&lt;/code&gt; is a group name, and the IPs are the servers you want to manage.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;4. Write Your First Playbook&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;A  Playbook is where you define the tasks you want Ansible to perform. Here's an example playbook to install Nginx on your servers:&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;Install Nginx on web servers&lt;/span&gt;
  &lt;span class="na"&gt;hosts&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;webservers&lt;/span&gt;
  &lt;span class="na"&gt;become&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt; 
  &lt;span class="na"&gt;tasks&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&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;Install Nginx&lt;/span&gt;
      &lt;span class="na"&gt;apt&lt;/span&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;nginx&lt;/span&gt;
        &lt;span class="na"&gt;state&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;present&lt;/span&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;Ensure Nginx is running&lt;/span&gt;
      &lt;span class="na"&gt;service&lt;/span&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;nginx&lt;/span&gt;
        &lt;span class="na"&gt;state&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;started&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Save this file as &lt;code&gt;install_nginx.yaml&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;5. Run Your Playbook&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Run your playbook with the following command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;ansible-playbook &lt;span class="nt"&gt;-i&lt;/span&gt; inventory install_nginx.yaml
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Modularizing Playbooks with Roles&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Ansible roles help you organize playbooks into reusable, modular components. Each role contains specific tasks, variables, and files needed for a part of your infrastructure.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Creating a Role&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;To create a role, use the following command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;ansible-galaxy init my_role
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This creates a directory structure like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;my_role/
├── tasks/
│   └── main.yml           
├── handlers/
├── templates/
├── files/
├── vars/
├── defaults/
└── meta/
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;tasks/: This directory contains the main task file, &lt;code&gt;main.yml&lt;/code&gt;, where you define the tasks that the role will execute.
-handlers/: Define actions triggered by tasks, such as restarting a service.
-templates/: Store Jinja2 templates for configuration files that can be dynamically generated.
-files/: Contains static files that can be copied to managed systems.
-vars/: Used to define role-specific variables that can be referenced in tasks.
-defaults/: Contains default variables for the role, which can be overridden by higher-priority variables.
-meta/: Contains metadata about the role, such as dependencies or role requirements.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Using Roles in Playbooks&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Once you’ve created a role or installed one from Ansible Galaxy, you can use it in your playbook. Here’s how to reference and use a role:&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;Apply my role&lt;/span&gt;
  &lt;span class="na"&gt;hosts&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;webservers&lt;/span&gt;
  &lt;span class="na"&gt;roles&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;my_role&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Ansible Galaxy&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Ansible Galaxy is a central hub where you can find and share pre-built Ansible roles. Instead of building everything from scratch, you can leverage these roles to save time and effort. For example, roles like &lt;code&gt;geerlingguy.nginx&lt;/code&gt; help you quickly install and configure Nginx without needing to write all the tasks yourself.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;How to Use Roles from Ansible Galaxy:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;To use a role from Ansible Galaxy, follow these steps:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 1&lt;/strong&gt;: Install the Role from Galaxy&lt;/p&gt;

&lt;p&gt;You can easily install a role using the &lt;code&gt;ansible-galaxy install&lt;/code&gt; command. For instance, to install the &lt;code&gt;geerlingguy.nginx&lt;/code&gt; role, run the following command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;ansible-galaxy &lt;span class="nb"&gt;install &lt;/span&gt;geerlingguy.nginx
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This command downloads the role and places it in your local roles directory (usually &lt;code&gt;/etc/ansible/roles/&lt;/code&gt; or a directory you specify).&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 2&lt;/strong&gt;: Reference the Role in Your Playbook&lt;/p&gt;

&lt;p&gt;Once the role is installed, you can reference it in your playbook. In the playbook, you’ll define which hosts should execute the tasks in the role.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Example playbook&lt;/strong&gt; (&lt;code&gt;my_playbook.yaml&lt;/code&gt;):&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;Install Nginx using downloaded role&lt;/span&gt;
  &lt;span class="na"&gt;hosts&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;webservers&lt;/span&gt;
  &lt;span class="na"&gt;roles&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;geerlingguy.nginx&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here, &lt;code&gt;geerlingguy.nginx&lt;/code&gt; is the role you installed, and &lt;code&gt;webservers&lt;/code&gt; is the group of hosts that will run the tasks defined in that role.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 3&lt;/strong&gt;: Run the Playbook&lt;/p&gt;

&lt;p&gt;Finally, you can run your playbook with the &lt;code&gt;ansible-playbook&lt;/code&gt; command, which will execute the tasks on the specified hosts.&lt;/p&gt;

&lt;p&gt;Run the playbook like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;ansible-playbook &lt;span class="nt"&gt;-i&lt;/span&gt; inventory my_playbook.yaml
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Ansible will apply the &lt;code&gt;geerlingguy.nginx&lt;/code&gt; role on all the hosts defined under &lt;code&gt;webservers&lt;/code&gt; in your inventory file.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Handlers&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Handlers are tasks triggered only when another task notifies them. For example:&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="na"&gt;tasks&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&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;Update the configuration file&lt;/span&gt;
    &lt;span class="na"&gt;copy&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;src&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;my_config.conf&lt;/span&gt;
      &lt;span class="na"&gt;dest&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;/etc/my_app/&lt;/span&gt;
    &lt;span class="na"&gt;notify&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Restart the application&lt;/span&gt;

&lt;span class="na"&gt;handlers&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&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;Restart the application&lt;/span&gt;
    &lt;span class="na"&gt;service&lt;/span&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;my_app&lt;/span&gt;
      &lt;span class="na"&gt;state&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;restarted&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here, the handler &lt;code&gt;Restart the application&lt;/code&gt; runs only if the &lt;code&gt;copy&lt;/code&gt; task changes the configuration file.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Conditionals&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Ansible supports conditionals to execute tasks only when specific conditions are met. For example:&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;Install Nginx on Debian-based systems&lt;/span&gt;
  &lt;span class="na"&gt;apt&lt;/span&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;nginx&lt;/span&gt;
    &lt;span class="na"&gt;state&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;present&lt;/span&gt;
  &lt;span class="na"&gt;when&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;ansible_os_family == "Debian"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here, the task runs only if the operating system family is Debian.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Best Practices for Ansible&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Use Variables: Keep your playbooks flexible by using variables.&lt;/li&gt;
&lt;li&gt;Organize Playbooks: Use roles to structure your playbooks for reusability.&lt;/li&gt;
&lt;li&gt;Test Locally: Use Vagrant or Docker to test playbooks before applying them to production.&lt;/li&gt;
&lt;li&gt;Keep Secrets Secure: Use Ansible Vault to encrypt sensitive data like passwords.&lt;/li&gt;
&lt;/ol&gt;

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

&lt;p&gt;Ansible simplifies IT automation, making it easier for both beginners and experienced engineers to manage infrastructure efficiently. With its easy-to-understand YAML syntax, agentless architecture, and powerful features like roles, handlers, and conditionals, Ansible can save you time and effort while ensuring consistency and scalability.&lt;/p&gt;

</description>
      <category>ansible</category>
      <category>linux</category>
    </item>
  </channel>
</rss>
