<?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>Forem: bankolejohn</title>
    <description>The latest articles on Forem by bankolejohn (@bankolejohn).</description>
    <link>https://forem.com/bankolejohn</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%2F886751%2F4c239721-8c1c-474a-af04-fd307feda5ff.png</url>
      <title>Forem: bankolejohn</title>
      <link>https://forem.com/bankolejohn</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/bankolejohn"/>
    <language>en</language>
    <item>
      <title>𝗙𝗿𝗼𝗺 𝗜𝗱𝗲𝗮 𝘁𝗼 𝗜𝗺𝗽𝗮𝗰𝘁: 𝗨𝗻𝗱𝗲𝗿𝘀𝘁𝗮𝗻𝗱𝗶𝗻𝗴 𝘁𝗵𝗲 𝗥𝗲𝗮𝗹-𝗪𝗼𝗿𝗹𝗱 𝗠𝗟 𝗣𝗿𝗼𝗷𝗲𝗰𝘁 𝗪𝗼𝗿𝗸𝗳𝗹𝗼𝘄</title>
      <dc:creator>bankolejohn</dc:creator>
      <pubDate>Thu, 07 Aug 2025 11:56:17 +0000</pubDate>
      <link>https://forem.com/bankolejohn/--10ii</link>
      <guid>https://forem.com/bankolejohn/--10ii</guid>
      <description>&lt;p&gt;As I take intentional steps into the world of AI and Machine Learning, one thing has become clear: 𝘮𝘢𝘤𝘩𝘪𝘯𝘦 𝘭𝘦𝘢𝘳𝘯𝘪𝘯𝘨 𝘪𝘴 𝘯𝘰𝘵 𝘫𝘶𝘴𝘵 𝘢𝘣𝘰𝘶𝘵 𝘸𝘳𝘪𝘵𝘪𝘯𝘨 𝘤𝘰𝘥𝘦 𝘰𝘳 𝘵𝘳𝘢𝘪𝘯𝘪𝘯𝘨 𝘮𝘰𝘥𝘦𝘭𝘴 -it’s about solving real problems with clarity, structure, and purpose.&lt;/p&gt;

&lt;p&gt;Here’s a breakdown of the ML workflow I’ve been studying and practicing -not just from a technical view, but from a problem-solving mindset that aligns with real business needs:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;𝗗𝗲𝗳𝗶𝗻𝗲 𝘁𝗵𝗲 𝗣𝗿𝗼𝗯𝗹𝗲𝗺 𝗙𝗶𝗿𝘀𝘁, 𝗡𝗼𝘁 𝘁𝗵𝗲 𝗠𝗼𝗱𝗲𝗹&lt;br&gt;
Before touching data or algorithms, the first step is always asking:&lt;br&gt;
“What problem are we trying to solve, and why does it matter?”&lt;br&gt;
Are we predicting customer churn? Detecting fraud? Forecasting demand?&lt;br&gt;
This clarity influences everything that follows, from the type of data we collect to the model we build and how we measure success. A project that starts with a vague goal often leads to wasted effort. But one that starts with a 𝘄𝗲𝗹𝗹-𝗱𝗲𝗳𝗶𝗻𝗲𝗱 𝗼𝗯𝗷𝗲𝗰𝘁𝗶𝘃𝗲 𝗮𝗻𝗱 𝗺𝗲𝗮𝘀𝘂𝗿𝗮𝗯𝗹𝗲 𝘀𝘂𝗰𝗰𝗲𝘀𝘀 𝗰𝗿𝗶𝘁𝗲𝗿𝗶𝗮 is positioned to make real impact.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;𝗚𝗮𝘁𝗵𝗲𝗿 𝗮𝗻𝗱 𝗣𝗿𝗲𝗽𝗮𝗿𝗲 𝘁𝗵𝗲 𝗗𝗮𝘁𝗮&lt;br&gt;
Once the problem is clear, the next step is sourcing quality data from databases, logs, APIs, or even unstructured sources like text or images. But raw data is messy.&lt;br&gt;
We clean it, remove duplicates, handle missing values, and organize it for analysis. Then comes 𝗘𝘅𝗽𝗹𝗼𝗿𝗮𝘁𝗼𝗿𝘆 𝗗𝗮𝘁𝗮 𝗔𝗻𝗮𝗹𝘆𝘀𝗶𝘀 (𝗘𝗗𝗔) -using visualizations and statistics to understand patterns, correlations, and outliers. This step is critical. It helps us uncover insights and make smarter choices about feature engineering and model selection.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;𝗦𝗲𝗹𝗲𝗰𝘁 𝗮𝗻𝗱 𝗧𝗿𝗮𝗶𝗻 𝘁𝗵𝗲 𝗥𝗶𝗴𝗵𝘁 𝗠𝗼𝗱𝗲𝗹
Model selection isn’t about choosing the most advanced algorithm -𝗶𝘁’𝘀 𝗮𝗯𝗼𝘂𝘁 𝗰𝗵𝗼𝗼𝘀𝗶𝗻𝗴 𝘁𝗵𝗲 𝗿𝗶𝗴𝗵𝘁 𝘁𝗼𝗼𝗹 𝗳𝗼𝗿 𝘁𝗵𝗲 𝗷𝗼𝗯.
If the data is tabular, we might use decision trees or gradient boosting. For text or sequences, maybe transformers or RNNs. And sometimes, the simplest model works best.
It’s all about balancing accuracy, interpretability, and efficiency, especially in business scenarios where transparency and speed matter as much as results.&lt;/li&gt;
&lt;/ol&gt;


&lt;/li&gt;

&lt;li&gt;&lt;p&gt;𝗘𝘃𝗮𝗹𝘂𝗮𝘁𝗲 𝘄𝗶𝘁𝗵 𝘁𝗵𝗲 𝗥𝗶𝗴𝗵𝘁 𝗠𝗲𝘁𝗿𝗶𝗰𝘀&lt;br&gt;&lt;br&gt;
You can’t improve what you don’t measure and not all problems use the same yardstick.&lt;br&gt;&lt;br&gt;
• For classification, we look at accuracy, precision, recall, F1-score, and AUC-ROC.&lt;br&gt;&lt;br&gt;
• For regression, we use RMSE, MSE, and R².&lt;br&gt;&lt;br&gt;
• For anomaly detection, we focus on recall vs. precision trade-offs.&lt;br&gt;&lt;br&gt;
It’s not just about getting high scores. It’s about understanding what those scores mean in the real world because catching fraud or diagnosing disease has consequences beyond metrics.&lt;/p&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;𝗧𝘂𝗻𝗲, 𝗗𝗲𝗽𝗹𝗼𝘆, 𝗮𝗻𝗱 𝗠𝗼𝗻𝗶𝘁𝗼𝗿&lt;br&gt;&lt;br&gt;
After training, we fine-tune hyperparameters (like learning rates or tree depths) to boost performance without overfitting.&lt;br&gt;&lt;br&gt;
Then comes deployment -serving the model via APIs or integrating it into an application. But it doesn’t stop there. The real world changes. Data drifts. So, we 𝗺𝗼𝗻𝗶𝘁𝗼𝗿 𝗽𝗲𝗿𝗳𝗼𝗿𝗺𝗮𝗻𝗰𝗲 𝗼𝘃𝗲𝗿 𝘁𝗶𝗺𝗲, retrain when needed, and keep the system adaptive.&lt;/p&gt;&lt;/li&gt;

&lt;/ol&gt;

&lt;p&gt;𝗙𝗶𝗻𝗮𝗹 𝗧𝗵𝗼𝘂𝗴𝗵𝘁𝘀&lt;br&gt;
What I’ve learned is this: 𝗔 𝗴𝗼𝗼𝗱 𝗺𝗮𝗰𝗵𝗶𝗻𝗲 𝗹𝗲𝗮𝗿𝗻𝗶𝗻𝗴 𝗺𝗼𝗱𝗲𝗹 𝗶𝘀𝗻’𝘁 𝗷𝘂𝘀𝘁 𝘀𝗺𝗮𝗿𝘁 -𝗶𝘁’𝘀 𝘂𝘀𝗲𝗳𝘂𝗹, 𝗱𝗲𝗽𝗲𝗻𝗱𝗮𝗯𝗹𝗲, 𝗮𝗻𝗱 𝗮𝗹𝗶𝗴𝗻𝗲𝗱 𝘄𝗶𝘁𝗵 𝗿𝗲𝗮𝗹 𝗴𝗼𝗮𝗹𝘀.&lt;br&gt;
This workflow has helped me connect the dots between technical skills and real-world impact and it’s a big step in my AI/ML learning journey. I'm excited to keep building, exploring, and learning how to use ML to solve meaningful problems.&lt;br&gt;
Keep Learning!&lt;/p&gt;

&lt;h1&gt;
  
  
  MachineLearning #AI #MLOps #DevOps #DataScience #RealWorldAI #LearningInPublic #KeepBuilding #AWS #AIJourney
&lt;/h1&gt;

</description>
      <category>aiml</category>
      <category>devops</category>
      <category>workflow</category>
    </item>
    <item>
      <title>Setting Up NGINX on Ubuntu: HNG 12 DevOps Stage 0 Task</title>
      <dc:creator>bankolejohn</dc:creator>
      <pubDate>Wed, 05 Feb 2025 06:45:11 +0000</pubDate>
      <link>https://forem.com/bankolejohn/setting-up-nginx-on-ubuntu-hng-12-devops-stage-0-task-5fp2</link>
      <guid>https://forem.com/bankolejohn/setting-up-nginx-on-ubuntu-hng-12-devops-stage-0-task-5fp2</guid>
      <description>&lt;p&gt;Web servers are fundamental to DevOps, forming the backbone of web applications by handling requests and serving content efficiently. As part of the &lt;strong&gt;HNG&lt;/strong&gt; &lt;strong&gt;DevOps Stage 0&lt;/strong&gt; task, I installed and configured &lt;strong&gt;NGINX&lt;/strong&gt; on a fresh Ubuntu server to serve a custom HTML page. This task helped me solidify my understanding of web server configurations, system administration, and automation. In this blog post, I will walk through the step-by-step process of setting up NGINX, the challenges I faced, and the key learnings from this experience.&lt;/p&gt;




&lt;h2&gt;
  
  
  &lt;strong&gt;Task Requirements&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;The objective of this task was to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Install the &lt;strong&gt;NGINX&lt;/strong&gt; web server on a fresh Ubuntu instance.&lt;/li&gt;
&lt;li&gt;Configure it to serve a custom HTML page at &lt;code&gt;/var/www/html/index.html&lt;/code&gt; with the message:&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;"Welcome to DevOps Stage 0 - [Your Name]/[SlackName]"&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;(Replacing &lt;strong&gt;[Your Name]&lt;/strong&gt; with my real name and &lt;strong&gt;[SlackName]&lt;/strong&gt; with my Slack username.)&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Include links to &lt;strong&gt;DevOps Engineers&lt;/strong&gt; and &lt;strong&gt;Cloud Engineers&lt;/strong&gt; resources.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Step-by-Step Implementation&lt;/strong&gt;
&lt;/h2&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;1. Installing NGINX&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Before installing NGINX, I updated the package repository to ensure I was fetching the latest software versions:&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;Then, I installed NGINX using 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;&lt;span class="nb"&gt;sudo &lt;/span&gt;apt &lt;span class="nb"&gt;install &lt;/span&gt;nginx &lt;span class="nt"&gt;-y&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Once the installation was complete, I started and enabled the NGINX service:&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;systemctl start nginx
&lt;span class="nb"&gt;sudo &lt;/span&gt;systemctl &lt;span class="nb"&gt;enable &lt;/span&gt;nginx
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To verify that NGINX was running successfully, I checked its status:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;systemctl status nginx
&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%2F94zmpzvcpgf469ljl14c.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%2F94zmpzvcpgf469ljl14c.png" alt="Image description" width="800" height="337"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;A green "active" status confirmed that NGINX was operational.&lt;/p&gt;




&lt;h3&gt;
  
  
  &lt;strong&gt;2. Configuring NGINX to Serve a Custom HTML Page&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;NGINX serves files from &lt;code&gt;/var/www/html/&lt;/code&gt; by default. I edited the &lt;strong&gt;index.html&lt;/strong&gt; file in that directory to display my custom message.&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;nano /var/www/html/index.html
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I replaced the existing content with the following HTML:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="cp"&gt;&amp;lt;!DOCTYPE html&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;html&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;head&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;title&amp;gt;&lt;/span&gt;DevOps Stage 0&lt;span class="nt"&gt;&amp;lt;/title&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/head&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;body&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;h1&amp;gt;&lt;/span&gt;Welcome to DevOps Stage 0 - [Your Name]/[SlackName]&lt;span class="nt"&gt;&amp;lt;/h1&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;p&amp;gt;&lt;/span&gt;Explore more about DevOps roles:&lt;span class="nt"&gt;&amp;lt;/p&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;ul&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;li&amp;gt;&amp;lt;a&lt;/span&gt; &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;"https://hng.tech/hire/devops-engineers"&lt;/span&gt; &lt;span class="na"&gt;target=&lt;/span&gt;&lt;span class="s"&gt;"_blank"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;DevOps Engineers&lt;span class="nt"&gt;&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;li&amp;gt;&amp;lt;a&lt;/span&gt; &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;"https://hng.tech/hire/cloud-engineers"&lt;/span&gt; &lt;span class="na"&gt;target=&lt;/span&gt;&lt;span class="s"&gt;"_blank"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Cloud Engineers&lt;span class="nt"&gt;&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/ul&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/body&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/html&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;After saving and exiting (&lt;code&gt;CTRL + X&lt;/code&gt;, then &lt;code&gt;Y&lt;/code&gt;, and pressing &lt;code&gt;Enter&lt;/code&gt;), I restarted NGINX to apply the changes:&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;systemctl restart nginx
&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%2Fajznr7fa8toefyoiul19.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%2Fajznr7fa8toefyoiul19.png" alt="Image description" width="800" height="221"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h3&gt;
  
  
  &lt;strong&gt;3. Testing the Configuration&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;To verify that my setup was successful, I accessed the server's IP address in a web browser:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;http://your-server-ip
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Alternatively, I used &lt;code&gt;curl&lt;/code&gt; to fetch the web page:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl http://localhost
&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%2Fdqinvsayw0vwghsch2zw.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%2Fdqinvsayw0vwghsch2zw.png" alt="Image description" width="800" height="199"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Seeing my custom message confirmed that the NGINX setup was complete.&lt;/p&gt;




&lt;h2&gt;
  
  
  &lt;strong&gt;Challenges Faced and Solutions&lt;/strong&gt;
&lt;/h2&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;1. NGINX Not Starting&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Issue:&lt;/strong&gt; When I initially tried to start NGINX, I encountered an error stating that the service failed to start.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Solution:&lt;/strong&gt; Checking the logs with &lt;code&gt;sudo journalctl -u nginx --no-pager&lt;/code&gt; revealed that another service was using port 80. I identified the conflicting service using:&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;netstat &lt;span class="nt"&gt;-tulnp&lt;/span&gt; | &lt;span class="nb"&gt;grep&lt;/span&gt; :80
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Stopping the conflicting service and restarting NGINX resolved the issue:&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;systemctl stop apache2
&lt;span class="nb"&gt;sudo &lt;/span&gt;systemctl disable apache2
&lt;span class="nb"&gt;sudo &lt;/span&gt;systemctl restart nginx
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h3&gt;
  
  
  &lt;strong&gt;2. Changes Not Reflecting in Browser&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Issue:&lt;/strong&gt; After modifying &lt;code&gt;index.html&lt;/code&gt;, my browser still displayed the old page.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Solution:&lt;/strong&gt; I cleared the browser cache and restarted NGINX. I also verified file permissions to ensure NGINX had read access:&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 chmod &lt;/span&gt;644 /var/www/html/index.html
&lt;span class="nb"&gt;sudo &lt;/span&gt;systemctl restart nginx
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  &lt;strong&gt;Key Learnings from This Task&lt;/strong&gt;
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Understanding Web Server Deployment:&lt;/strong&gt; Setting up and configuring NGINX deepened my understanding of web server management and static content delivery.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Troubleshooting System Services:&lt;/strong&gt; Debugging NGINX startup issues provided hands-on experience with Linux system services and networking.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Automation Possibilities:&lt;/strong&gt; This manual process highlighted the potential for automating server setup with tools like &lt;strong&gt;Ansible&lt;/strong&gt; or &lt;strong&gt;Terraform&lt;/strong&gt;.&lt;/li&gt;
&lt;/ol&gt;




&lt;h2&gt;
  
  
  &lt;strong&gt;How This Task Supports My Career Goals&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Completing this task is a stepping stone in my &lt;strong&gt;DevOps journey&lt;/strong&gt;. The ability to configure web servers is essential for DevOps Engineers, who manage infrastructure and CI/CD pipelines. Understanding how &lt;strong&gt;NGINX&lt;/strong&gt; serves as a reverse proxy and load balancer is also valuable for roles like &lt;strong&gt;Site Reliability Engineers&lt;/strong&gt; and &lt;strong&gt;Cloud Engineers&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;If you're looking to hire professionals in these fields, check out:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://hng.tech/hire/devops-engineers" rel="noopener noreferrer"&gt;DevOps Engineers&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://hng.tech/hire/cloud-engineers" rel="noopener noreferrer"&gt;Cloud Engineers&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This hands-on experience has reinforced my ability to work with production-grade web servers, a critical skill in modern DevOps practices.&lt;/p&gt;




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

&lt;p&gt;Setting up NGINX from scratch on an Ubuntu server was an insightful exercise in configuring and troubleshooting a web server. From installation to serving a custom web page, this task helped me build a solid foundation in &lt;strong&gt;Linux system administration&lt;/strong&gt; and &lt;strong&gt;web server management&lt;/strong&gt;. As I continue my DevOps learning path, I look forward to automating such deployments using &lt;strong&gt;Infrastructure as Code (IaC)&lt;/strong&gt; tools like Terraform and Ansible.&lt;/p&gt;

&lt;p&gt;This challenge was a rewarding experience, and I am excited about more DevOps tasks ahead in the HNG program!&lt;/p&gt;

</description>
      <category>nginx</category>
      <category>devops</category>
    </item>
    <item>
      <title>Week 20 3MTT WEEKLY REFLECTION</title>
      <dc:creator>bankolejohn</dc:creator>
      <pubDate>Thu, 07 Nov 2024 09:49:46 +0000</pubDate>
      <link>https://forem.com/bankolejohn/week-20-3mtt-weekly-reflection-24gl</link>
      <guid>https://forem.com/bankolejohn/week-20-3mtt-weekly-reflection-24gl</guid>
      <description>&lt;h1&gt;
  
  
  My3MTT #3MTTWeeklyReflection
&lt;/h1&gt;

&lt;p&gt;In reflecting on my 3MTT journey, my proudest accomplishment has been mastering the core principles of CI/CD. Creating automated build, test, and deployment pipelines with GitHub Actions has allowed me to streamline workflows, improve efficiency, and boost project reliability. This achievement has given me hands-on experience in delivering consistent results and deepened my understanding of the DevOps lifecycle.&lt;/p&gt;

&lt;p&gt;The biggest challenge I faced was learning Kubernetes. Initially, I struggled to understand its concepts and found cluster management and container orchestration intimidating. To tackle this, I dedicated extra time to tutorials, sought advice from mentors, and practiced setting up simple clusters. Each small success in Kubernetes has boosted my confidence and provided a clearer understanding of the technology.&lt;/p&gt;

&lt;p&gt;Moving forward, I want to continue improving my Kubernetes skills. Gaining expertise in container orchestration will allow me to deploy scalable, resilient applications and will be a significant step toward my goal of becoming a well-rounded DevOps engineer.&lt;/p&gt;

&lt;p&gt;@3mttNigeria, @IHSTowers, @NITDANigeria&lt;/p&gt;

</description>
      <category>devops</category>
      <category>reflection</category>
    </item>
    <item>
      <title>3MTT Week 19 Task: "Quick Impact Challenge"</title>
      <dc:creator>bankolejohn</dc:creator>
      <pubDate>Wed, 30 Oct 2024 12:10:27 +0000</pubDate>
      <link>https://forem.com/bankolejohn/3mtt-week-19-task-quick-impact-challenge-3jfd</link>
      <guid>https://forem.com/bankolejohn/3mtt-week-19-task-quick-impact-challenge-3jfd</guid>
      <description>&lt;p&gt;**&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Week 19 Task: "Quick Impact Challenge"&lt;br&gt;
**&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;For this week's Impact Challenge, I focused on increasing participation in my 3MTT group by initiating a “Favorite DevOps Tool” activity. The idea was simple: encourage group members to share a tool or productivity tip that has helped them in their DevOps journey. I posted a prompt with engaging language and a clear call-to-action, using tags like #My3MTT and #3MTTWeeklyReflection to tie it into the program’s community initiatives.&lt;/p&gt;

&lt;p&gt;Within 24 hours, the response was encouraging. Many group members chimed in with their favorite tools, including Docker, Jenkins, and Terraform, and shared quick tips for boosting productivity, such as using task automation and command-line shortcuts. The responses created a ripple effect, sparking further discussion as people asked questions and commented on each other’s posts.&lt;/p&gt;

&lt;p&gt;This activity not only increased engagement but also helped group members discover new tools and best practices. The positive impact was immediate; members appreciated the opportunity to share insights, and the sense of community felt stronger. Overall, this small initiative made a noticeable difference in participation and knowledge sharing within the group.&lt;/p&gt;

&lt;h1&gt;
  
  
  My3MTT #3MTTWeeklyReflection
&lt;/h1&gt;

</description>
      <category>3mttweeklyreflection</category>
      <category>my3mtt</category>
    </item>
    <item>
      <title>Creating and Managing Docker Containers for a Simple Node.js Application</title>
      <dc:creator>bankolejohn</dc:creator>
      <pubDate>Mon, 07 Oct 2024 13:13:10 +0000</pubDate>
      <link>https://forem.com/bankolejohn/creating-and-managing-docker-containers-for-a-simple-nodejs-application-3d04</link>
      <guid>https://forem.com/bankolejohn/creating-and-managing-docker-containers-for-a-simple-nodejs-application-3d04</guid>
      <description>&lt;p&gt;Docker is a powerful tool that enables developers to package applications and their dependencies into a portable container, making it easy to deploy and run anywhere. In this article, we'll walk through building a Docker image for a simple Node.js application, and cover key commands for managing Docker containers. This includes writing a Dockerfile, building the image, and running the container.&lt;/p&gt;

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

&lt;ul&gt;
&lt;li&gt;Basic knowledge of Docker.&lt;/li&gt;
&lt;li&gt;Docker installed on your machine.&lt;/li&gt;
&lt;li&gt;Node.js and npm installed for testing the app locally.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Step 1: Create a Simple Node.js Application
&lt;/h2&gt;

&lt;p&gt;First, let’s set up a basic Node.js application. Create a new directory for your project and initialize it:&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;node-docker-app
&lt;span class="nb"&gt;cd &lt;/span&gt;node-docker-app
npm init &lt;span class="nt"&gt;-y&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Next, create an &lt;code&gt;index.js&lt;/code&gt; file with the following content:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// index.js&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;express&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;express&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;app&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;express&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;PORT&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;PORT&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="mi"&gt;3000&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="nx"&gt;app&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="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;send&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Hello, Docker!&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;listen&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;PORT&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`Server is running on port &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;PORT&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Install &lt;code&gt;express&lt;/code&gt; as a dependency:&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;



&lt;p&gt;Now you have a basic Node.js app that responds with "Hello, Docker!" at the root URL.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 2: Write the Dockerfile
&lt;/h2&gt;

&lt;p&gt;A Dockerfile is a script that contains instructions for building a Docker image. Create a file named &lt;code&gt;Dockerfile&lt;/code&gt; in your project directory and add the following content:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight docker"&gt;&lt;code&gt;&lt;span class="c"&gt;# Use the official Node.js image as the base image&lt;/span&gt;
&lt;span class="k"&gt;FROM&lt;/span&gt;&lt;span class="s"&gt; node:18&lt;/span&gt;

&lt;span class="c"&gt;# Set the working directory inside the container&lt;/span&gt;
&lt;span class="k"&gt;WORKDIR&lt;/span&gt;&lt;span class="s"&gt; /app&lt;/span&gt;

&lt;span class="c"&gt;# Copy package.json and package-lock.json to the working directory&lt;/span&gt;
&lt;span class="k"&gt;COPY&lt;/span&gt;&lt;span class="s"&gt; package*.json ./&lt;/span&gt;

&lt;span class="c"&gt;# Install dependencies&lt;/span&gt;
&lt;span class="k"&gt;RUN &lt;/span&gt;npm &lt;span class="nb"&gt;install&lt;/span&gt;

&lt;span class="c"&gt;# Copy the rest of the application files&lt;/span&gt;
&lt;span class="k"&gt;COPY&lt;/span&gt;&lt;span class="s"&gt; . .&lt;/span&gt;

&lt;span class="c"&gt;# Expose the port the app runs on&lt;/span&gt;
&lt;span class="k"&gt;EXPOSE&lt;/span&gt;&lt;span class="s"&gt; 3000&lt;/span&gt;

&lt;span class="c"&gt;# Define the command to run the app&lt;/span&gt;
&lt;span class="k"&gt;CMD&lt;/span&gt;&lt;span class="s"&gt; ["node", "index.js"]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Explanation of Dockerfile Commands
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;FROM&lt;/code&gt;: Specifies the base image. We use the official Node.js image.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;WORKDIR&lt;/code&gt;: Sets the working directory inside the container to &lt;code&gt;/app&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;COPY&lt;/code&gt;: Copies files from your local machine to the working directory inside the container.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;RUN&lt;/code&gt;: Executes commands in the Docker image (e.g., &lt;code&gt;npm install&lt;/code&gt; to install dependencies).&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;EXPOSE&lt;/code&gt;: Exposes port 3000 to allow the application to be accessible.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;CMD&lt;/code&gt;: Defines the command to run when the container starts.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Step 3: Build the Docker Image
&lt;/h2&gt;

&lt;p&gt;With the Dockerfile in place, build the Docker image using 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;docker build &lt;span class="nt"&gt;-t&lt;/span&gt; node-docker-app &lt;span class="nb"&gt;.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;-t node-docker-app&lt;/code&gt;: Tags the image with a name for easy reference.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;.&lt;/code&gt;: Refers to the current directory, which contains the Dockerfile.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Once the build is complete, you can list the Docker images on your system:&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;



&lt;p&gt;This should show the &lt;code&gt;node-docker-app&lt;/code&gt; image you just built.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 4: Run the Docker Container
&lt;/h2&gt;

&lt;p&gt;Now that we have an image, let's run a container from it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker run &lt;span class="nt"&gt;-p&lt;/span&gt; 3000:3000 node-docker-app
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;-p 3000:3000&lt;/code&gt;: Maps port 3000 on your local machine to port 3000 in the container.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;node-docker-app&lt;/code&gt;: The name of the image to run.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Once the container is running, you can open your browser and navigate to &lt;code&gt;http://localhost:3000&lt;/code&gt; to see your app in action. It should display "Hello, Docker!".&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 5: Managing Docker Containers
&lt;/h2&gt;

&lt;h3&gt;
  
  
  List Running Containers
&lt;/h3&gt;

&lt;p&gt;To see the currently running containers, use:&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;



&lt;p&gt;This will show you the container ID, image name, and other details about running containers.&lt;/p&gt;

&lt;h3&gt;
  
  
  Stop a Container
&lt;/h3&gt;

&lt;p&gt;To stop a running container, use:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker stop &amp;lt;container_id&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Replace &lt;code&gt;&amp;lt;container_id&amp;gt;&lt;/code&gt; with the ID of your container, which you can get from &lt;code&gt;docker ps&lt;/code&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Remove a Container
&lt;/h3&gt;

&lt;p&gt;To remove a stopped container, use:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker &lt;span class="nb"&gt;rm&lt;/span&gt; &amp;lt;container_id&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Remove an Image
&lt;/h3&gt;

&lt;p&gt;If you want to remove the Docker image, use:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker rmi node-docker-app
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Make sure that no containers are using the image before you try to remove it.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 6: Pushing the Docker Image to Docker Hub (Optional)
&lt;/h2&gt;

&lt;p&gt;If you want to share your Docker image, you can push it to Docker Hub:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;Log in to Docker Hub:&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker login
&lt;/code&gt;&lt;/pre&gt;

&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Tag the image with your Docker Hub username:&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker tag node-docker-app yourusername/node-docker-app
&lt;/code&gt;&lt;/pre&gt;

&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Push the image to Docker Hub:&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker push yourusername/node-docker-app
&lt;/code&gt;&lt;/pre&gt;

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

&lt;p&gt;Now, anyone can pull and run your image using:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker pull yourusername/node-docker-app
docker run &lt;span class="nt"&gt;-p&lt;/span&gt; 3000:3000 yourusername/node-docker-app
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;p&gt;In this article, we created a simple Node.js application and packaged it into a Docker container using a Dockerfile. We went through building, running, and managing the Docker image, and even pushing it to Docker Hub for easy distribution. Docker simplifies the process of deploying applications by providing a consistent runtime environment, making it a valuable tool for developers.&lt;/p&gt;

</description>
      <category>docker</category>
      <category>node</category>
      <category>simpleapplication</category>
    </item>
    <item>
      <title>Setting Up a Basic CI/CD Pipeline with Automated Build and Test Stages</title>
      <dc:creator>bankolejohn</dc:creator>
      <pubDate>Mon, 30 Sep 2024 10:38:07 +0000</pubDate>
      <link>https://forem.com/bankolejohn/setting-up-a-basic-cicd-pipeline-with-automated-build-and-test-stages-10ik</link>
      <guid>https://forem.com/bankolejohn/setting-up-a-basic-cicd-pipeline-with-automated-build-and-test-stages-10ik</guid>
      <description>&lt;p&gt;In today's fast-paced development environments, Continuous Integration and Continuous Deployment (CI/CD) pipelines play a crucial role in ensuring rapid, reliable, and automated software releases. This article will walk you through setting up a basic CI/CD pipeline, focusing on automated build and test stages. Additionally, we'll identify the key stages of a CI/CD pipeline and explore how they can be automated with modern tools.&lt;/p&gt;

&lt;h3&gt;
  
  
  What is CI/CD?
&lt;/h3&gt;

&lt;p&gt;CI/CD stands for Continuous Integration and Continuous Deployment (or Delivery). CI focuses on automating the integration of code changes from multiple contributors, while CD automates the process of delivering that integrated code to production. Together, they streamline the software development lifecycle, improving efficiency, reliability, and speed.&lt;/p&gt;

&lt;h3&gt;
  
  
  Key Stages of a CI/CD Pipeline
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Source Control&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;This is the first stage where developers push their code changes. A version control system (VCS) like Git is used to manage and track code changes.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Automation Tool&lt;/strong&gt;: GitHub, GitLab, Bitbucket, or other Git-based platforms.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Build&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;In this stage, the code is compiled and necessary dependencies are installed. For interpreted languages like JavaScript (Node.js), Python, or Ruby, this might involve installing libraries or setting up the environment.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Automation Tool&lt;/strong&gt;: GitHub Actions, Jenkins, CircleCI.&lt;/li&gt;
&lt;li&gt;Example: A Node.js project could use &lt;code&gt;npm install&lt;/code&gt; to set up dependencies and then run build commands like &lt;code&gt;npm run build&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Test&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Automated testing ensures that the new changes don't break existing features. Tests can include unit tests, integration tests, or end-to-end tests.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Automation Tool&lt;/strong&gt;: Jest (JavaScript), PyTest (Python), Mocha, etc.&lt;/li&gt;
&lt;li&gt;Example: For a Node.js project, you can automate tests by running &lt;code&gt;npm test&lt;/code&gt; or using a CI service like GitHub Actions to run tests on each pull request.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Deploy&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;In this stage, the code is deployed to staging or production environments. This ensures that the pipeline can continuously deploy updates to live environments without human intervention.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Automation Tool&lt;/strong&gt;: Docker, Kubernetes, AWS CodeDeploy, GitHub Actions, Jenkins.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Monitoring and Feedback&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;After deployment, monitoring is crucial to ensure the system is working as expected. Feedback loops inform the team of issues, allowing rapid fixes.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Automation Tool&lt;/strong&gt;: Prometheus, Grafana, Datadog.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Setting Up a Basic CI/CD Pipeline with GitHub Actions
&lt;/h3&gt;

&lt;p&gt;Let's focus on creating a simple CI/CD pipeline for a Node.js project using &lt;strong&gt;GitHub Actions&lt;/strong&gt;. This will cover the build and test stages.&lt;/p&gt;

&lt;h4&gt;
  
  
  Step 1: Define a GitHub Workflow
&lt;/h4&gt;

&lt;p&gt;In your GitHub repository, create a new directory called &lt;code&gt;.github/workflows&lt;/code&gt; and add a YAML file, such as &lt;code&gt;ci.yml&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="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Node.js CI Pipeline&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="s"&gt;main&lt;/span&gt;
  &lt;span class="na"&gt;pull_request&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="s"&gt;main&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 Node.js&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/setup-node@v3&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;node-version&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;16'&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 dependencies&lt;/span&gt;
        &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;npm install&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;Run build&lt;/span&gt;
        &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;npm run build&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;Run tests&lt;/span&gt;
        &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;npm test&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Step 2: Automating the Build Stage
&lt;/h4&gt;

&lt;p&gt;The pipeline begins by checking out the repository's code and setting up Node.js (version 16 in this case). It installs the project's dependencies using &lt;code&gt;npm install&lt;/code&gt; and runs the build command, typically &lt;code&gt;npm run build&lt;/code&gt;.&lt;/p&gt;

&lt;h4&gt;
  
  
  Step 3: Automating the Test Stage
&lt;/h4&gt;

&lt;p&gt;After building the project, it automatically runs tests using &lt;code&gt;npm test&lt;/code&gt;. This ensures that every push and pull request goes through proper testing before merging or deployment.&lt;/p&gt;

&lt;h4&gt;
  
  
  Step 4: Extending to Deployment
&lt;/h4&gt;

&lt;p&gt;For deployment, you can add additional steps in the workflow to deploy the code to services like AWS, Heroku, or Docker. Here's a quick example for AWS deployment:&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;Deploy to AWS&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;appleboy/scp-action@v0.1.2&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;host&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${{ secrets.AWS_HOST }}&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.AWS_USER }}&lt;/span&gt;
          &lt;span class="na"&gt;key&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${{ secrets.AWS_KEY }}&lt;/span&gt;
          &lt;span class="na"&gt;source&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;./"&lt;/span&gt;
          &lt;span class="na"&gt;target&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;/var/www/html"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Tools for Automating Each CI/CD Stage
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Source Control&lt;/strong&gt;: Git, GitHub, GitLab.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Build&lt;/strong&gt;: GitHub Actions, Jenkins, CircleCI.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Test&lt;/strong&gt;: Jest, PyTest, Mocha, Selenium.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Deploy&lt;/strong&gt;: Docker, Kubernetes, AWS CodeDeploy, Ansible.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Monitoring&lt;/strong&gt;: Prometheus, Grafana, New Relic.&lt;/li&gt;
&lt;/ul&gt;

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

&lt;p&gt;Setting up a CI/CD pipeline with automated build and test stages ensures rapid feedback and higher code quality. By utilizing modern automation tools, you can ensure that your project is tested and deployed consistently with minimal manual intervention. This process is vital for maintaining code reliability and enabling frequent deployments in fast-moving development environments.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;This article gives one a good foundation for setting up a simple CI/CD flow.&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>cicd</category>
      <category>automation</category>
    </item>
    <item>
      <title>DevOPs Week 2: ALC Assignment</title>
      <dc:creator>bankolejohn</dc:creator>
      <pubDate>Tue, 10 Sep 2024 19:51:09 +0000</pubDate>
      <link>https://forem.com/bankolejohn/devops-week-2-alc-assignment-5c79</link>
      <guid>https://forem.com/bankolejohn/devops-week-2-alc-assignment-5c79</guid>
      <description>&lt;h2&gt;
  
  
  A Comprehensive Guide to Committing a Repository to GitHub Using Git
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Understanding Git and GitHub
&lt;/h3&gt;

&lt;p&gt;Before diving into the steps, let's clarify the roles of Git and GitHub:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Git:&lt;/strong&gt; A distributed version control system that tracks changes to files and directories. It's primarily used for managing source code.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;GitHub:&lt;/strong&gt; A web-based hosting service for software development projects that use Git. It provides features like collaboration, issue tracking, and project management.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Setting Up Your Environment
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Install Git:&lt;/strong&gt; Download and install Git from &lt;a href="https://git-scm.com/downloads" rel="noopener noreferrer"&gt;https://git-scm.com/downloads&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Configure Git:&lt;/strong&gt; Open your terminal or command prompt and set your username and email address:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;   git config &lt;span class="nt"&gt;--global&lt;/span&gt; user.name &lt;span class="s2"&gt;"Your Name"&lt;/span&gt;
   git config &lt;span class="nt"&gt;--global&lt;/span&gt; user.email &lt;span class="s2"&gt;"your.email@example.com"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Creating a Repository on GitHub
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Log in to GitHub:&lt;/strong&gt; Visit &lt;a href="https://github.com" rel="noopener noreferrer"&gt;https://github.com&lt;/a&gt; and log in to your account.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Create a New Repository:&lt;/strong&gt; Click the "New repository" button, provide a name and description, and choose the repository's visibility (public or private).&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Cloning the Repository Locally
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Copy the Repository URL:&lt;/strong&gt; From your GitHub repository's page, copy the HTTPS clone URL.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Clone the Repository:&lt;/strong&gt; Open your terminal and navigate to the desired directory. Use the &lt;code&gt;git clone&lt;/code&gt; command:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;   git clone &amp;lt;repository_url&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This creates a local copy of the repository on your machine.&lt;/p&gt;

&lt;h3&gt;
  
  
  Making Changes and Committing
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Navigate to the Repository:&lt;/strong&gt; Open a terminal and navigate to the cloned repository's directory.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Make Changes:&lt;/strong&gt; Modify files or create new ones as needed.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Stage Changes:&lt;/strong&gt; Use &lt;code&gt;git add&lt;/code&gt; to stage files for commit:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;   git add &amp;lt;filename&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Or, to stage all changes in the current directory:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;   git add &lt;span class="nb"&gt;.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Commit Changes:&lt;/strong&gt; Create a commit using &lt;code&gt;git commit&lt;/code&gt;:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;   git commit &lt;span class="nt"&gt;-m&lt;/span&gt; &lt;span class="s2"&gt;"Clear and concise commit message"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Replace "Clear and concise commit message" with a meaningful description of your changes.&lt;/p&gt;

&lt;h3&gt;
  
  
  Pushing Changes to GitHub
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Push to Remote Repository:&lt;/strong&gt; Use &lt;code&gt;git push&lt;/code&gt; to send your local commits to the remote GitHub repository:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;   git push origin &amp;lt;branch_name&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Replace &lt;code&gt;&amp;lt;branch_name&amp;gt;&lt;/code&gt; with the branch you're currently on (usually &lt;code&gt;main&lt;/code&gt; or &lt;code&gt;master&lt;/code&gt;).&lt;/p&gt;

&lt;h3&gt;
  
  
  Additional Tips
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Branches:&lt;/strong&gt; Use Git branches to work on different features or bug fixes simultaneously. Create branches with &lt;code&gt;git branch &amp;lt;branch_name&amp;gt;&lt;/code&gt; and switch between them with &lt;code&gt;git checkout &amp;lt;branch_name&amp;gt;&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Pull Requests:&lt;/strong&gt; To collaborate with others, create pull requests on GitHub to propose changes to a repository.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Remote Repositories:&lt;/strong&gt; You can add multiple remote repositories to your local project. This is useful for collaborating with others or working on different versions of the same code.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Ignoring Files:&lt;/strong&gt; Use a &lt;code&gt;.gitignore&lt;/code&gt; file to specify files or directories that Git should ignore.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;By following these steps and incorporating best practices, you'll be well-equipped to effectively commit your repositories to GitHub using Git.&lt;/p&gt;

</description>
    </item>
    <item>
      <title>How I Overcame Course Access and Assignment Submission Challenges in the 3MTT Program</title>
      <dc:creator>bankolejohn</dc:creator>
      <pubDate>Tue, 10 Sep 2024 13:24:25 +0000</pubDate>
      <link>https://forem.com/bankolejohn/how-i-overcame-course-access-and-assignment-submission-challenges-in-the-3mtt-program-1f24</link>
      <guid>https://forem.com/bankolejohn/how-i-overcame-course-access-and-assignment-submission-challenges-in-the-3mtt-program-1f24</guid>
      <description>&lt;p&gt;&lt;strong&gt;Introduction:&lt;/strong&gt;&lt;br&gt;
As a participant in the 3MTT program, recently upgraded from Cohort 3 to Cohort 2, I encountered unexpected challenges. Navigating course access and submitting assignments felt overwhelming initially. However, through the power of community and collaboration, I was able to resolve these issues and keep my learning on track.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The Challenges:&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Accessing Courses&lt;/strong&gt;: Upon moving to Cohort 2, I had difficulty figuring out how to access the relevant courses.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Submitting Assignments&lt;/strong&gt;: I also needed clarity on how to submit my assignments in a way that would allow mentors and peers to provide feedback.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;The Solutions:&lt;/strong&gt;&lt;br&gt;
I turned to the &lt;strong&gt;Telegram community&lt;/strong&gt; for help, where my colleagues provided invaluable guidance. Here’s how I solved each challenge:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Accessing Courses&lt;/strong&gt;: I was advised to audit the courses before accessing them. This simple tip allowed me to view and enroll in the materials I needed.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Submitting Assignments&lt;/strong&gt;: I learned that making my Google Drive links publicly accessible was essential. This ensured that others could view my work and leave comments. &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Key Takeaways:&lt;/strong&gt;&lt;br&gt;
This experience reinforced the importance of community in overcoming obstacles. Asking questions, receiving feedback, and collaborating with others in the program made a significant difference in resolving my challenges quickly.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Conclusion:&lt;/strong&gt;&lt;br&gt;
Facing challenges is part of any learning journey, but the support of peers and mentors can make all the difference. In the 3MTT program, I’ve learned that when in doubt, turning to the community is always a good solution.&lt;/p&gt;

&lt;h1&gt;
  
  
  My3MTT #3MTTWeeklyReflection @3mttNigeria @IHSTowers @NITDANigeria
&lt;/h1&gt;

</description>
    </item>
    <item>
      <title>DevOps vs. Traditional Approaches: Navigating the Shift in Software Development</title>
      <dc:creator>bankolejohn</dc:creator>
      <pubDate>Mon, 26 Aug 2024 13:40:02 +0000</pubDate>
      <link>https://forem.com/bankolejohn/devops-vs-traditional-approaches-navigating-the-shift-in-software-development-3d88</link>
      <guid>https://forem.com/bankolejohn/devops-vs-traditional-approaches-navigating-the-shift-in-software-development-3d88</guid>
      <description>&lt;h3&gt;
  
  
  DevOps vs. Traditional Software Development: A Comparative Analysis
&lt;/h3&gt;

&lt;p&gt;In the rapidly evolving world of software development, organizations continuously seek methodologies that enhance efficiency, improve collaboration, and accelerate delivery. Two prominent approaches in this domain are the &lt;strong&gt;Traditional Software Development&lt;/strong&gt; model and the &lt;strong&gt;DevOps&lt;/strong&gt; methodology. While both aim to produce reliable software, their philosophies, practices, and outcomes differ significantly.&lt;/p&gt;

&lt;h4&gt;
  
  
  1. &lt;strong&gt;Philosophy and Culture&lt;/strong&gt;
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Traditional Approach&lt;/strong&gt;: Traditionally, software development has been characterized by a clear separation of roles. Developers focus on writing code, while operations teams are responsible for deployment and maintenance. This siloed structure often leads to miscommunication, delays, and a lack of shared responsibility for the end product.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;DevOps Approach&lt;/strong&gt;: DevOps, short for Development and Operations, embodies a culture of collaboration. It emphasizes breaking down silos, promoting cross-functional teams where developers, operations, QA, and even security teams work together from the outset. This shared responsibility ensures that all team members are aligned with the same goals, fostering a culture of continuous improvement and accountability.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  2. &lt;strong&gt;Development and Release Cycles&lt;/strong&gt;
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Traditional Approach&lt;/strong&gt;: Traditional software development often follows a linear, waterfall model, where each phase—requirements gathering, design, coding, testing, and deployment—is completed sequentially. This can result in long release cycles, sometimes taking months or even years, which can delay the delivery of new features and updates to end users.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;DevOps Approach&lt;/strong&gt;: In contrast, DevOps embraces agile principles, promoting shorter, iterative development cycles. Continuous Integration (CI) and Continuous Deployment (CD) are core practices in DevOps, enabling teams to release small, incremental updates frequently. This rapid release cycle not only accelerates time-to-market but also allows for quicker feedback and iterative improvements.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  3. &lt;strong&gt;Collaboration and Communication&lt;/strong&gt;
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Traditional Approach&lt;/strong&gt;: Communication in traditional software development is often formal and follows a top-down hierarchy. Teams work independently, passing completed work to the next department in the chain, which can lead to bottlenecks and a lack of transparency.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;DevOps Approach&lt;/strong&gt;: DevOps fosters a culture of open communication and collaboration. With tools like Slack, JIRA, and automated pipelines, teams can collaborate in real-time, share progress, and resolve issues faster. This transparency ensures that everyone is on the same page, reducing friction and promoting a more cohesive workflow.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  4. &lt;strong&gt;Infrastructure Management&lt;/strong&gt;
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Traditional Approach&lt;/strong&gt;: Infrastructure management in traditional development is typically manual and separate from the development process. Operations teams manage servers, networking, and other infrastructure components independently, which can lead to slow provisioning and scaling.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;DevOps Approach&lt;/strong&gt;: DevOps introduces Infrastructure as Code (IaC), where infrastructure is treated as software. Tools like Terraform, Ansible, and Kubernetes allow teams to automate the provisioning and management of infrastructure, making it scalable, repeatable, and version-controlled. This automation reduces human error, speeds up deployments, and enhances the ability to scale rapidly in response to demand.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  5. &lt;strong&gt;Quality and Security&lt;/strong&gt;
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Traditional Approach&lt;/strong&gt;: In traditional models, quality assurance (QA) and security are often addressed at the end of the development cycle. This can lead to significant delays if issues are discovered late in the process, requiring extensive rework.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;DevOps Approach&lt;/strong&gt;: DevOps integrates quality and security into every stage of the development lifecycle. Practices like Test-Driven Development (TDD), Continuous Testing, and DevSecOps (security as code) ensure that code quality and security are maintained throughout the development process. This proactive approach reduces the risk of defects and vulnerabilities, leading to more reliable software.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  6. &lt;strong&gt;Customer Feedback and Adaptability&lt;/strong&gt;
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Traditional Approach&lt;/strong&gt;: Due to long release cycles, customer feedback in traditional development often comes late, making it challenging to adapt to changing requirements. This can result in a product that meets the original specifications but not the evolving needs of the market.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;DevOps Approach&lt;/strong&gt;: With its emphasis on continuous delivery, DevOps enables teams to gather and act on customer feedback quickly. This iterative process allows for rapid adaptation to changing market conditions, ensuring that the software remains relevant and valuable to users.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

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

&lt;p&gt;The shift from traditional software development to DevOps represents a fundamental change in how software is built, tested, and delivered. By breaking down silos, automating processes, and fostering a culture of collaboration, DevOps offers a more agile, efficient, and customer-focused approach to software development. Organizations that embrace DevOps are better equipped to navigate the complexities of modern software delivery, ensuring that they can deliver high-quality software at speed.&lt;/p&gt;

&lt;p&gt;Whether you're a seasoned developer or new to the field, understanding these differences is crucial for navigating the ever-evolving landscape of software development. Embracing the DevOps mindset can open doors to more innovative, efficient, and impactful ways of working.&lt;/p&gt;

</description>
    </item>
    <item>
      <title>DEPLOYING "HNG_BOILERPLATE" EXPRESSJS APPLICATION (BACKEND) TO PROD SERVER</title>
      <dc:creator>bankolejohn</dc:creator>
      <pubDate>Sat, 24 Aug 2024 21:49:48 +0000</pubDate>
      <link>https://forem.com/bankolejohn/deploying-the-backend-of-hngboilerplate-expressjs-application-to-prod-server-1d35</link>
      <guid>https://forem.com/bankolejohn/deploying-the-backend-of-hngboilerplate-expressjs-application-to-prod-server-1d35</guid>
      <description>&lt;h4&gt;
  
  
  Overview
&lt;/h4&gt;

&lt;p&gt;This documentation details the deployment process of the backend of an Express.js boilerplate application to a production environment on an EC2 Ubuntu server using a GitHub Actions workflow. The deployment process includes setting up necessary dependencies, pulling the latest code, running tests, building the backend, and ensuring it runs as a service.&lt;/p&gt;

&lt;h4&gt;
  
  
  Prerequisites
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;EC2 Ubuntu Server:&lt;/strong&gt; Running Ubuntu, with SSH access.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Node.js 20&lt;/strong&gt; installed on the server.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;npm&lt;/strong&gt; installed on the server.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Nginx&lt;/strong&gt; installed and configured as a reverse proxy.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;GitHub Repository:&lt;/strong&gt; Hosting the Express.js boilerplate code.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;GitHub Actions Runner:&lt;/strong&gt; Installed and configured on the server to execute the deployment workflow.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Certbot&lt;/strong&gt; for SSL certificate management.&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  Dependencies
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Node.js 20&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;npm&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Nginx&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Yarn&lt;/strong&gt; (for managing Node.js dependencies)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;GitHub Actions Runner&lt;/strong&gt; (self-hosted runner)&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  Deployment Workflow
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Deploy to production&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="s"&gt;prod&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;deploy&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;bp_runner&lt;/span&gt;
    &lt;span class="na"&gt;defaults&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="na"&gt;working-directory&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;/var/www/aihomework/boilerplate/prod&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="na"&gt;with&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;fetch-depth&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;0&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;Setup Node.js&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/setup-node@v3&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;node-version&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;20'&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;Remove old actions remote URL&lt;/span&gt;
        &lt;span class="na"&gt;continue-on-error&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;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;|&lt;/span&gt;
            &lt;span class="s"&gt;git remote rm action&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;Stash or remove local changes&lt;/span&gt;
        &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;|&lt;/span&gt;
            &lt;span class="s"&gt;if git diff --quiet; then&lt;/span&gt;
              &lt;span class="s"&gt;echo "No local changes to stash."&lt;/span&gt;
            &lt;span class="s"&gt;else&lt;/span&gt;
              &lt;span class="s"&gt;echo "Stashing local changes..."&lt;/span&gt;
              &lt;span class="s"&gt;git stash --include-untracked || echo "Failed to stash changes. Attempting to reset..."&lt;/span&gt;
              &lt;span class="s"&gt;git reset --hard || exit 1&lt;/span&gt;
            &lt;span class="s"&gt;fi&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;Pull from GitHub&lt;/span&gt;
        &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;pull&lt;/span&gt;
        &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;|&lt;/span&gt;
            &lt;span class="s"&gt;remote_repo="https://${GITHUB_ACTOR}:${{ secrets.GITHUB_TOKEN }}@github.com/${GITHUB_REPOSITORY}.git"&lt;/span&gt;
            &lt;span class="s"&gt;git remote add action $remote_repo&lt;/span&gt;
            &lt;span class="s"&gt;git pull $remote_repo prod&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 dependencies&lt;/span&gt;
        &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;yarn install --frozen-lockfile&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;Run tests&lt;/span&gt;
        &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;yarn test&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 the application&lt;/span&gt;
        &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;yarn build &amp;amp;&amp;amp; sudo rm -rf build&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;Setup and restart service&lt;/span&gt;
        &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;|&lt;/span&gt;
          &lt;span class="s"&gt;sudo cp server-script/aihomeworkprod.service /etc/systemd/system&lt;/span&gt;
          &lt;span class="s"&gt;sudo systemctl daemon-reload&lt;/span&gt;
          &lt;span class="s"&gt;sudo systemctl restart aihomeworkprod.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;Verify deployment&lt;/span&gt;
        &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;|&lt;/span&gt;
          &lt;span class="s"&gt;echo "Waiting for service to start..."&lt;/span&gt;
          &lt;span class="s"&gt;sleep 10&lt;/span&gt;
          &lt;span class="s"&gt;if sudo systemctl is-active --quiet aihomeworkprod.service; then&lt;/span&gt;
            &lt;span class="s"&gt;echo "Deployment successful!"&lt;/span&gt;
          &lt;span class="s"&gt;else&lt;/span&gt;
            &lt;span class="s"&gt;echo "Deployment failed!"&lt;/span&gt;
            &lt;span class="s"&gt;exit 1&lt;/span&gt;
          &lt;span class="s"&gt;fi&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h5&gt;
  
  
  1. &lt;strong&gt;Triggering the Workflow&lt;/strong&gt;
&lt;/h5&gt;

&lt;ul&gt;
&lt;li&gt;The workflow is triggered by a push to the &lt;code&gt;prod&lt;/code&gt; branch.&lt;/li&gt;
&lt;/ul&gt;

&lt;h5&gt;
  
  
  2. &lt;strong&gt;Checking Out the Code&lt;/strong&gt;
&lt;/h5&gt;

&lt;ul&gt;
&lt;li&gt;The &lt;code&gt;actions/checkout@v3&lt;/code&gt; action pulls the latest code from the &lt;code&gt;prod&lt;/code&gt; branch, ensuring the full history is retrieved (&lt;code&gt;fetch-depth: 0&lt;/code&gt;).&lt;/li&gt;
&lt;/ul&gt;

&lt;h5&gt;
  
  
  3. &lt;strong&gt;Setting Up Node.js&lt;/strong&gt;
&lt;/h5&gt;

&lt;ul&gt;
&lt;li&gt;The workflow installs Node.js version 20 using the &lt;code&gt;actions/setup-node@v3&lt;/code&gt; action.&lt;/li&gt;
&lt;/ul&gt;

&lt;h5&gt;
  
  
  4. &lt;strong&gt;Managing Git Remotes and Local Changes&lt;/strong&gt;
&lt;/h5&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Remove Old Remote URL:&lt;/strong&gt; Deletes any existing remote URL to prevent conflicts.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Stash or Remove Local Changes:&lt;/strong&gt; Uncommitted changes are stashed or reset to maintain a clean working directory.&lt;/li&gt;
&lt;/ul&gt;

&lt;h5&gt;
  
  
  5. &lt;strong&gt;Pulling Latest Changes&lt;/strong&gt;
&lt;/h5&gt;

&lt;ul&gt;
&lt;li&gt;The latest changes are pulled from the &lt;code&gt;prod&lt;/code&gt; branch using the GitHub token for authentication.&lt;/li&gt;
&lt;/ul&gt;

&lt;h5&gt;
  
  
  6. &lt;strong&gt;Installing Dependencies&lt;/strong&gt;
&lt;/h5&gt;

&lt;ul&gt;
&lt;li&gt;Node.js dependencies are installed using &lt;code&gt;yarn install --frozen-lockfile&lt;/code&gt; to ensure consistency with the &lt;code&gt;yarn.lock&lt;/code&gt; file.&lt;/li&gt;
&lt;/ul&gt;

&lt;h5&gt;
  
  
  7. &lt;strong&gt;Running Tests&lt;/strong&gt;
&lt;/h5&gt;

&lt;ul&gt;
&lt;li&gt;Tests are executed using &lt;code&gt;yarn test&lt;/code&gt; to verify the stability of the backend before deployment.&lt;/li&gt;
&lt;/ul&gt;

&lt;h5&gt;
  
  
  8. &lt;strong&gt;Building the Backend&lt;/strong&gt;
&lt;/h5&gt;

&lt;ul&gt;
&lt;li&gt;The backend is built using &lt;code&gt;yarn build&lt;/code&gt;, and previous build artifacts are removed to prevent conflicts.&lt;/li&gt;
&lt;/ul&gt;

&lt;h5&gt;
  
  
  9. &lt;strong&gt;Setting Up and Restarting the Service&lt;/strong&gt;
&lt;/h5&gt;

&lt;ul&gt;
&lt;li&gt;The service file (&lt;code&gt;aihomeworkprod.service&lt;/code&gt;) is copied to the &lt;code&gt;/etc/systemd/system&lt;/code&gt; directory, and the systemd manager configuration is reloaded. The service is restarted to apply the latest changes.&lt;/li&gt;
&lt;/ul&gt;

&lt;h5&gt;
  
  
  10. &lt;strong&gt;Verifying Deployment&lt;/strong&gt;
&lt;/h5&gt;

&lt;ul&gt;
&lt;li&gt;The workflow waits for the service to start and checks its status. If the service is active, the deployment is successful; otherwise, it fails.&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  Service Configuration (&lt;code&gt;aihomeworkprod.service&lt;/code&gt;)
&lt;/h4&gt;

&lt;p&gt;The service file defines how the backend of the Express.js application runs on the server. Below is a sample service configuration:&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;[Unit]&lt;/span&gt;
&lt;span class="py"&gt;Description&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;Express.js Backend Application - Production&lt;/span&gt;
&lt;span class="py"&gt;After&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;network.target&lt;/span&gt;

&lt;span class="nn"&gt;[Service]&lt;/span&gt;
&lt;span class="py"&gt;ExecStart&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;/usr/bin/node /var/www/aihomework/boilerplate/prod/build/index.js&lt;/span&gt;
&lt;span class="py"&gt;WorkingDirectory&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;/var/www/aihomework/boilerplate/prod&lt;/span&gt;
&lt;span class="py"&gt;Restart&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;always&lt;/span&gt;
&lt;span class="py"&gt;User&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;www-data&lt;/span&gt;
&lt;span class="py"&gt;Group&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;www-data&lt;/span&gt;
&lt;span class="py"&gt;Environment&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;NODE_ENV=production&lt;/span&gt;
&lt;span class="py"&gt;Environment&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;PORT=3000&lt;/span&gt;

&lt;span class="nn"&gt;[Install]&lt;/span&gt;
&lt;span class="py"&gt;WantedBy&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;multi-user.target&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Nginx Configuration
&lt;/h4&gt;

&lt;p&gt;Nginx is used as a reverse proxy to route incoming traffic to the Express.js backend application. The following Nginx configuration includes the SSL setup using Certbot:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight nginx"&gt;&lt;code&gt;&lt;span class="k"&gt;server&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kn"&gt;listen&lt;/span&gt; &lt;span class="mi"&gt;80&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kn"&gt;server_name&lt;/span&gt; &lt;span class="s"&gt;your-domain.com&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="kn"&gt;location&lt;/span&gt; &lt;span class="n"&gt;/&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="kn"&gt;proxy_pass&lt;/span&gt; &lt;span class="s"&gt;http://localhost:3000&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="kn"&gt;proxy_http_version&lt;/span&gt; &lt;span class="mf"&gt;1.1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="kn"&gt;proxy_set_header&lt;/span&gt; &lt;span class="s"&gt;Upgrade&lt;/span&gt; &lt;span class="nv"&gt;$http_upgrade&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="kn"&gt;proxy_set_header&lt;/span&gt; &lt;span class="s"&gt;Connection&lt;/span&gt; &lt;span class="s"&gt;'upgrade'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="kn"&gt;proxy_set_header&lt;/span&gt; &lt;span class="s"&gt;Host&lt;/span&gt; &lt;span class="nv"&gt;$host&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="kn"&gt;proxy_cache_bypass&lt;/span&gt; &lt;span class="nv"&gt;$http_upgrade&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="kn"&gt;listen&lt;/span&gt; &lt;span class="mi"&gt;443&lt;/span&gt; &lt;span class="s"&gt;ssl&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;# managed by Certbot&lt;/span&gt;
    &lt;span class="kn"&gt;ssl_certificate&lt;/span&gt; &lt;span class="n"&gt;/etc/letsencrypt/live/your-domain.com/fullchain.pem&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;# managed by Certbot&lt;/span&gt;
    &lt;span class="kn"&gt;ssl_certificate_key&lt;/span&gt; &lt;span class="n"&gt;/etc/letsencrypt/live/your-domain.com/privkey.pem&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;# managed by Certbot&lt;/span&gt;
    &lt;span class="kn"&gt;include&lt;/span&gt; &lt;span class="n"&gt;/etc/letsencrypt/options-ssl-nginx.conf&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;# managed by Certbot&lt;/span&gt;
    &lt;span class="kn"&gt;ssl_dhparam&lt;/span&gt; &lt;span class="n"&gt;/etc/letsencrypt/ssl-dhparams.pem&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;# managed by Certbot&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h5&gt;
  
  
  SSL Certificate Setup
&lt;/h5&gt;

&lt;p&gt;To obtain SSL certificates and configure Nginx with HTTPS, you can use the following command with Certbot:&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;--nginx&lt;/span&gt; &lt;span class="nt"&gt;-d&lt;/span&gt; your-domain.com
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This command will automatically configure Nginx with SSL, obtaining certificates from Let’s Encrypt.&lt;/p&gt;

&lt;h4&gt;
  
  
  Final Steps
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Ensure Nginx is configured&lt;/strong&gt; to point to the backend’s port.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Enable and start the systemd service&lt;/strong&gt;: &lt;code&gt;sudo systemctl enable aihomeworkprod.service&lt;/code&gt; and &lt;code&gt;sudo systemctl start aihomeworkprod.service&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Monitor the service&lt;/strong&gt; using &lt;code&gt;sudo systemctl status aihomeworkprod.service&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  NOTE
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Ensure that you update the .env file with the required variables in order to ensure the application runs successfully.&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  Conclusion
&lt;/h4&gt;

&lt;p&gt;This documentation outlines the automated deployment process for the backend of the Express.js boilerplate application, ensuring that the latest changes are consistently deployed to the production environment. By following the above steps, the backend can be reliably updated and maintained on the EC2 Ubuntu server with SSL-secured access.&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Linux User Creation Bash Script - HNG 11 DevOPs Task</title>
      <dc:creator>bankolejohn</dc:creator>
      <pubDate>Thu, 04 Jul 2024 12:03:36 +0000</pubDate>
      <link>https://forem.com/bankolejohn/linux-user-creation-bash-script-hng-11-devops-task-2k68</link>
      <guid>https://forem.com/bankolejohn/linux-user-creation-bash-script-hng-11-devops-task-2k68</guid>
      <description>&lt;h1&gt;
  
  
  Technical Article
&lt;/h1&gt;

&lt;h2&gt;
  
  
  Automating User Creation in Linux with a Bash Script
&lt;/h2&gt;

&lt;p&gt;As a SysOps engineer, managing users and groups efficiently is crucial, especially when onboarding new developers. Automating this process ensures consistency and saves time. Here, I will walk you through a Bash script, create_users.sh, designed to create users and groups, set up home directories, generate random passwords, and log all actions.&lt;/p&gt;

&lt;h3&gt;
  
  
  Script Overview
&lt;/h3&gt;

&lt;p&gt;The script reads a text file containing usernames and groups, creates users and groups, sets up home directories, generates random passwords, and logs actions to /var/log/user_management.log. Passwords are securely stored in /var/secure/user_passwords.txt.&lt;/p&gt;

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

&lt;p&gt;Ensure you have root or sudo privileges as the script requires administrative access to create users and groups.&lt;/p&gt;

&lt;h3&gt;
  
  
  Script Breakdown
&lt;/h3&gt;

&lt;h4&gt;
  
  
  Generate Random Password:
&lt;/h4&gt;

&lt;p&gt;Generating a random password using OpenSSL ensures that each user gets a secure, unpredictable password.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;generate_password() {
    openssl rand -base64 12
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Check Input File:
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;if [ -z "$1" ]; then
    echo "Usage: $0 &amp;lt;input-file&amp;gt;"
    exit 1
fi
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This checks if the user has provided the required input file. If not, it provides a usage message and exits the script. This ensures the script is used correctly.&lt;/p&gt;

&lt;h4&gt;
  
  
  Set Up Logging and Secure Password Storage:
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;LOG_FILE="/var/log/user_management.log"
PASSWORD_FILE="/var/secure/user_passwords.txt"
mkdir -p /var/secure
touch $LOG_FILE
chmod 644 $LOG_FILE
touch $PASSWORD_FILE
chmod 600 $PASSWORD_FILE
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Setting up a log file allows tracking of actions, which is crucial for troubleshooting and auditing. Storing passwords securely with restricted permissions ensures that only authorized users can access them, enhancing security.&lt;/p&gt;

&lt;h4&gt;
  
  
  Read and Process Input File:
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;while IFS=';' read -r username groups; do
    username=$(echo "$username" | xargs)
    groups=$(echo "$groups" | xargs)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Reading the input file line by line and trimming whitespace ensures that each user and their groups are handled correctly, preventing issues with extra spaces.&lt;/p&gt;

&lt;h4&gt;
  
  
  Create User and Personal Group:
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;if id "$username" &amp;amp;&amp;gt;/dev/null; then
    echo "User $username already exists." | tee -a $LOG_FILE
    continue
fi
useradd -m -g "$username" "$username"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Checking if the user exists prevents errors from trying to recreate existing users. Creating a personal group for each user is a common practice to isolate permissions, and then creating the user with that group ensures proper setup.&lt;/p&gt;

&lt;h4&gt;
  
  
  Assign Additional Groups:
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;if [ -n "$groups" ]; then
    IFS=',' read -ra ADDR &amp;lt;&amp;lt;&amp;lt; "$groups"
    for group in "${ADDR[@]}"; do
        group=$(echo "$group" | xargs)
        if getent group "$group" &amp;amp;&amp;gt;/dev/null; then
            usermod -aG "$group" "$username"
            echo "User $username added to group $group." | tee -a $LOG_FILE
        else
            echo "Group $group does not exist. Skipping for user $username." | tee -a $LOG_FILE
        fi
    done
fi
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Adding users to multiple groups allows for flexible permission management, enabling users to have access to different resources as needed. Creating missing groups on the fly ensures smooth execution without manual intervention.&lt;/p&gt;

&lt;h4&gt;
  
  
  Set Home Directory Permissions:
&lt;/h4&gt;

&lt;p&gt;Setting strict permissions ensures that only the user can access their home directory, enhancing security and privacy. Changing ownership ensures that the user has full control over their own files.&lt;br&gt;
&lt;/p&gt;

&lt;p&gt;```chmod 700 "/home/$username"&lt;br&gt;
chown "$username:$username" "/home/$username"&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;



#### Generate and Set Password:



```password=$(generate_password)
echo "$username,$password" &amp;gt;&amp;gt; $PASSWORD_FILE
echo "$username:$password" | chpasswd
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Storing passwords securely and setting them for users automates the process, ensuring each user has a unique, strong password. This is crucial for maintaining security standards.&lt;/p&gt;
&lt;h4&gt;
  
  
  Logging and Completion:
&lt;/h4&gt;



&lt;p&gt;&lt;code&gt;echo "User creation process completed." | tee -a $LOG_FILE&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;p&gt;Logging the completion of the process provides a clear end point for auditing purposes and ensures that administrators are aware of the script's progress and any issues that may have occurred.&lt;/p&gt;

&lt;h5&gt;
  
  
  script running successfully on AWS ubuntu 22.04
&lt;/h5&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fgithub.com%2Fbankolejohn%2F-Linux-User-Creation-Bash-Script%2Fassets%2F76499525%2Ffd7bc86d-cfa9-4f6c-b244-bc90136c9d6c" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fgithub.com%2Fbankolejohn%2F-Linux-User-Creation-Bash-Script%2Fassets%2F76499525%2Ffd7bc86d-cfa9-4f6c-b244-bc90136c9d6c" alt="task_1"&gt;&lt;/a&gt;&lt;/p&gt;

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

&lt;p&gt;Automating user creation in Linux with a Bash script streamlines the onboarding process, ensuring efficiency and security. By following the steps outlined above, you can easily manage user accounts and groups in a consistent manner.&lt;/p&gt;

&lt;p&gt;For more information about the HNG Internship and opportunities to enhance your skills, visit the HNG Internship website [&lt;a href="https://hng.tech/internship" rel="noopener noreferrer"&gt;https://hng.tech/internship&lt;/a&gt;] and learn how you can hire top talents from the program [ &lt;a href="https://hng.tech/hire" rel="noopener noreferrer"&gt;https://hng.tech/hire&lt;/a&gt;]&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Microsoft Powerup Program</title>
      <dc:creator>bankolejohn</dc:creator>
      <pubDate>Mon, 04 Mar 2024 14:32:09 +0000</pubDate>
      <link>https://forem.com/bankolejohn/microsoft-powerup-program-45cf</link>
      <guid>https://forem.com/bankolejohn/microsoft-powerup-program-45cf</guid>
      <description>&lt;p&gt;I am thrilled to embark on my journey as a participant in the &lt;strong&gt;Microsoft PowerUp Program&lt;/strong&gt;. Throughout this experience, I will gain a deep understanding of the Microsoft Power Platform and harness the power of tools such as Power Apps, Power Automate, Power Virtual Agents, Power Pages, and Power BI to create innovative solutions for various business requirements.&lt;/p&gt;

&lt;p&gt;Follow me, as I keep you updated, sharing valuable knowledge throughout my journey.&lt;/p&gt;

&lt;p&gt;If you have any questions as regards this program, do ask in the comment section.&lt;/p&gt;

&lt;p&gt;See you in my next post...&lt;/p&gt;

&lt;h1&gt;
  
  
  microsoftPowerUpProgram #microsoftpowerbi #microsoftpowerautomate #microsoftpowerapps #microsoftpowervirtualagents #microsoftpowerpages
&lt;/h1&gt;

</description>
      <category>microsoftpowerupprogram</category>
    </item>
  </channel>
</rss>
