<?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: Faruq2991</title>
    <description>The latest articles on Forem by Faruq2991 (@faruq2991).</description>
    <link>https://forem.com/faruq2991</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%2F1534784%2Fbcdbdec5-3f64-4a13-810c-cbda16c9106f.png</url>
      <title>Forem: Faruq2991</title>
      <link>https://forem.com/faruq2991</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/faruq2991"/>
    <language>en</language>
    <item>
      <title>Setting Up Jenkins SSH Build Agents: A Complete Troubleshooting Guide</title>
      <dc:creator>Faruq2991</dc:creator>
      <pubDate>Sat, 10 Jan 2026 04:13:31 +0000</pubDate>
      <link>https://forem.com/faruq2991/setting-up-jenkins-ssh-build-agents-a-complete-troubleshooting-guide-3pl</link>
      <guid>https://forem.com/faruq2991/setting-up-jenkins-ssh-build-agents-a-complete-troubleshooting-guide-3pl</guid>
      <description>&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;In modern DevOps practices, distributed builds are essential for scalability and efficiency. Jenkins, one of the most popular CI/CD tools, supports this through its agent (formerly called slave) architecture. This guide walks through the complete process of configuring multiple Linux servers as SSH build agents in Jenkins, including all the troubleshooting steps for common issues you'll likely encounter.&lt;/p&gt;

&lt;h2&gt;
  
  
  What Problem Does This Solve?
&lt;/h2&gt;

&lt;h3&gt;
  
  
  The Challenge
&lt;/h3&gt;

&lt;p&gt;When running Jenkins in a production environment, you often face these limitations:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Resource Constraints&lt;/strong&gt;: The Jenkins controller (master) server has limited CPU, memory, and disk space&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Build Isolation&lt;/strong&gt;: Running all builds on the controller can cause conflicts between different projects&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Scalability&lt;/strong&gt;: As your organization grows, a single server cannot handle increased build loads&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Platform Diversity&lt;/strong&gt;: Different projects may require different operating systems or tools&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  The Solution: Distributed Build Architecture
&lt;/h3&gt;

&lt;p&gt;By configuring multiple servers as Jenkins agents, you achieve:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Horizontal Scaling&lt;/strong&gt;: Distribute builds across multiple machines&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Resource Optimization&lt;/strong&gt;: Execute builds on dedicated servers with appropriate resources&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Build Isolation&lt;/strong&gt;: Each agent can have specific tools and configurations&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Parallel Execution&lt;/strong&gt;: Run multiple builds simultaneously across different agents&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;High Availability&lt;/strong&gt;: If one agent fails, others continue working&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  My Setup Requirements
&lt;/h2&gt;

&lt;p&gt;For this implementation, I needed to configure three application servers as Jenkins SSH build agents:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Agent Name&lt;/th&gt;
&lt;th&gt;Server Hostname&lt;/th&gt;
&lt;th&gt;User&lt;/th&gt;
&lt;th&gt;Remote Directory&lt;/th&gt;
&lt;th&gt;Label&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;App_server_1&lt;/td&gt;
&lt;td&gt;stapp01&lt;/td&gt;
&lt;td&gt;tony&lt;/td&gt;
&lt;td&gt;/home/tony/jenkins&lt;/td&gt;
&lt;td&gt;stapp01&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;App_server_2&lt;/td&gt;
&lt;td&gt;stapp02&lt;/td&gt;
&lt;td&gt;steve&lt;/td&gt;
&lt;td&gt;/home/steve/jenkins&lt;/td&gt;
&lt;td&gt;stapp02&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;App_server_3&lt;/td&gt;
&lt;td&gt;stapp03&lt;/td&gt;
&lt;td&gt;banner&lt;/td&gt;
&lt;td&gt;/home/banner/jenkins&lt;/td&gt;
&lt;td&gt;stapp03&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

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

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

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Jenkins Controller&lt;/strong&gt;: A running Jenkins instance with admin access&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Agent Servers&lt;/strong&gt;: Linux servers accessible via SSH&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Network Connectivity&lt;/strong&gt;: Jenkins controller can reach agent servers on port 22&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;User Accounts&lt;/strong&gt;: Valid user accounts on each agent server with appropriate permissions&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;SSH Credentials&lt;/strong&gt;: SSH keys or passwords for authentication&lt;/li&gt;
&lt;/ol&gt;

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

&lt;h3&gt;
  
  
  Step 1: Install SSH Build Agents Plugin
&lt;/h3&gt;

&lt;p&gt;The first step is ensuring Jenkins has the necessary plugin to manage SSH-based agents.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Log into Jenkins with admin credentials (in my case: username &lt;code&gt;admin&lt;/code&gt;, password &lt;code&gt;Adm!n321&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;Navigate to &lt;strong&gt;Manage Jenkins&lt;/strong&gt; → &lt;strong&gt;Manage Plugins&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Click the &lt;strong&gt;Available&lt;/strong&gt; tab&lt;/li&gt;
&lt;li&gt;Search for "SSH Build Agents" plugin&lt;/li&gt;
&lt;li&gt;Select the plugin and click &lt;strong&gt;Install without restart&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Check &lt;strong&gt;"Restart Jenkins when installation is complete and no jobs are running"&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Wait for Jenkins to restart (this may take 1-2 minutes)&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;Important Note&lt;/strong&gt;: If the Jenkins UI appears stuck after restart, simply refresh your browser page.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 2: Configure SSH Credentials
&lt;/h3&gt;

&lt;p&gt;Before adding agents, you need to set up SSH credentials that Jenkins will use to connect to each server.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Go to &lt;strong&gt;Manage Jenkins&lt;/strong&gt; → &lt;strong&gt;Manage Credentials&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Click on &lt;strong&gt;(global)&lt;/strong&gt; domain&lt;/li&gt;
&lt;li&gt;Click &lt;strong&gt;Add Credentials&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Configure as follows:

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Kind&lt;/strong&gt;: SSH Username with private key&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Scope&lt;/strong&gt;: Global&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;ID&lt;/strong&gt;: Give it a meaningful name (e.g., &lt;code&gt;tony-ssh-key&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Username&lt;/strong&gt;: Enter the SSH username (e.g., &lt;code&gt;tony&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Private Key&lt;/strong&gt;: Select "Enter directly" and paste your private key, or select "From a file on Jenkins controller"&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Click &lt;strong&gt;OK&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Repeat for each user (steve and banner)&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Step 3: Add the First Agent (App_server_1)
&lt;/h3&gt;

&lt;p&gt;Now let's configure the first agent node:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Navigate to &lt;strong&gt;Manage Jenkins&lt;/strong&gt; → &lt;strong&gt;Manage Nodes and Clouds&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Click &lt;strong&gt;New Node&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Enter node name: &lt;code&gt;App_server_1&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Select &lt;strong&gt;Permanent Agent&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Click &lt;strong&gt;Create&lt;/strong&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Configure the node with these settings:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Name&lt;/strong&gt;: &lt;code&gt;App_server_1&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Description&lt;/strong&gt;: App Server 1 Build Agent (optional)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Number of executors&lt;/strong&gt;: &lt;code&gt;2&lt;/code&gt; (adjust based on server capacity)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Remote root directory&lt;/strong&gt;: &lt;code&gt;/home/tony/jenkins&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Labels&lt;/strong&gt;: &lt;code&gt;stapp01&lt;/code&gt; (important for targeting builds to specific agents)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Usage&lt;/strong&gt;: Use this node as much as possible&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Launch method&lt;/strong&gt;: Launch agents via SSH

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Host&lt;/strong&gt;: &lt;code&gt;stapp01&lt;/code&gt; (or IP address if DNS not configured)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Credentials&lt;/strong&gt;: Select the credentials you created for tony&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Host Key Verification Strategy&lt;/strong&gt;: Non verifying Verification Strategy (for initial setup)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Port&lt;/strong&gt;: &lt;code&gt;22&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

&lt;strong&gt;Availability&lt;/strong&gt;: Keep this agent online as much as possible&lt;/li&gt;

&lt;/ul&gt;

&lt;p&gt;Click &lt;strong&gt;Save&lt;/strong&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 4: Repeat for Additional Agents
&lt;/h3&gt;

&lt;p&gt;Follow the same process for App_server_2 and App_server_3:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;For App_server_2:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Name: &lt;code&gt;App_server_2&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Remote root directory: &lt;code&gt;/home/steve/jenkins&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Labels: &lt;code&gt;stapp02&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Host: &lt;code&gt;stapp02&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Credentials: steve's credentials&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;For App_server_3:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Name: &lt;code&gt;App_server_3&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Remote root directory: &lt;code&gt;/home/banner/jenkins&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Labels: &lt;code&gt;stapp03&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Host: &lt;code&gt;stapp03&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Credentials: banner's credentials&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Troubleshooting: Problems Encountered and Solutions
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Problem 1: Java Not Found on Agent
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Error Message:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;[SSH] Starting agent process: cd "/home/tony/jenkins" &amp;amp;&amp;amp; java -jar remoting.jar...
bash: line 1: java: command not found
Agent JVM has terminated. Exit code=127
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Root Cause&lt;/strong&gt;: Java Runtime Environment (JRE) is not installed on the agent server.&lt;/p&gt;

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

&lt;p&gt;SSH into each agent server and install Java:&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="c"&gt;# SSH into the server&lt;/span&gt;
ssh tony@stapp01

&lt;span class="c"&gt;# Switch to root user&lt;/span&gt;
&lt;span class="nb"&gt;sudo &lt;/span&gt;su -

&lt;span class="c"&gt;# Install Java 17 (see Problem 2 for why version 17)&lt;/span&gt;
yum &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-y&lt;/span&gt; java-17-openjdk java-17-openjdk-devel

&lt;span class="c"&gt;# Verify installation&lt;/span&gt;
java &lt;span class="nt"&gt;-version&lt;/span&gt;

&lt;span class="c"&gt;# Exit root&lt;/span&gt;
&lt;span class="nb"&gt;exit&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Repeat for all agent servers (stapp02 with user steve, stapp03 with user banner).&lt;/p&gt;

&lt;h3&gt;
  
  
  Problem 2: Java Version Mismatch (Critical Issue)
&lt;/h3&gt;

&lt;p&gt;This was the most challenging issue I encountered.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Error Message:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;java.lang.UnsupportedClassVersionError: hudson/slaves/SlaveComputer$SlaveVersion 
has been compiled by a more recent version of the Java Runtime 
(class file version 61.0), this version of the Java Runtime only 
recognizes class file versions up to 55.0
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Root Cause Analysis&lt;/strong&gt;: &lt;/p&gt;

&lt;p&gt;This error indicates a Java version compatibility issue:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Class file version 61.0&lt;/strong&gt; = Compiled with Java 17&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Class file version 55.0&lt;/strong&gt; = Running with Java 11&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The Jenkins controller was running on Java 17, but I initially installed Java 11 on the agent servers. Java bytecode is forward-compatible but not backward-compatible, meaning code compiled with Java 17 cannot run on Java 11.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Understanding Java Version Numbers:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Java 8 = class version 52.0&lt;/li&gt;
&lt;li&gt;Java 11 = class version 55.0&lt;/li&gt;
&lt;li&gt;Java 17 = class version 61.0&lt;/li&gt;
&lt;li&gt;Java 21 = class version 65.0&lt;/li&gt;
&lt;/ul&gt;

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

&lt;p&gt;Upgrade all agent servers to Java 17:&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="c"&gt;# SSH into each agent server&lt;/span&gt;
ssh tony@stapp01
&lt;span class="nb"&gt;sudo &lt;/span&gt;su -

&lt;span class="c"&gt;# Remove old Java 11 installation&lt;/span&gt;
yum remove &lt;span class="nt"&gt;-y&lt;/span&gt; java-11-openjdk java-11-openjdk-devel

&lt;span class="c"&gt;# Install Java 17&lt;/span&gt;
yum &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-y&lt;/span&gt; java-17-openjdk java-17-openjdk-devel

&lt;span class="c"&gt;# Verify the correct version is installed&lt;/span&gt;
java &lt;span class="nt"&gt;-version&lt;/span&gt;
&lt;span class="c"&gt;# Should output: openjdk version "17.x.x"&lt;/span&gt;

&lt;span class="c"&gt;# Optional: Set JAVA_HOME environment variable&lt;/span&gt;
&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s1"&gt;'export JAVA_HOME=/usr/lib/jvm/java-17-openjdk'&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; ~/.bashrc
&lt;span class="nb"&gt;source&lt;/span&gt; ~/.bashrc

&lt;span class="nb"&gt;exit&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Important Rule&lt;/strong&gt;: Always ensure agent Java version matches or exceeds the Jenkins controller Java version.&lt;/p&gt;

&lt;h3&gt;
  
  
  Problem 3: Missing Jenkins Working Directory
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Error Symptoms&lt;/strong&gt;: Agent connects but fails to execute builds with permission errors.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Root Cause&lt;/strong&gt;: The remote root directory specified in the agent configuration doesn't exist or has incorrect permissions.&lt;/p&gt;

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

&lt;p&gt;Create the directories on each agent server:&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="c"&gt;# On App Server 1&lt;/span&gt;
ssh tony@stapp01
&lt;span class="nb"&gt;mkdir&lt;/span&gt; &lt;span class="nt"&gt;-p&lt;/span&gt; /home/tony/jenkins
&lt;span class="nb"&gt;chmod &lt;/span&gt;755 /home/tony/jenkins
&lt;span class="nb"&gt;ls&lt;/span&gt; &lt;span class="nt"&gt;-la&lt;/span&gt; /home/tony/jenkins

&lt;span class="c"&gt;# On App Server 2&lt;/span&gt;
ssh steve@stapp02
&lt;span class="nb"&gt;mkdir&lt;/span&gt; &lt;span class="nt"&gt;-p&lt;/span&gt; /home/steve/jenkins
&lt;span class="nb"&gt;chmod &lt;/span&gt;755 /home/steve/jenkins

&lt;span class="c"&gt;# On App Server 3&lt;/span&gt;
ssh banner@stapp03
&lt;span class="nb"&gt;mkdir&lt;/span&gt; &lt;span class="nt"&gt;-p&lt;/span&gt; /home/banner/jenkins
&lt;span class="nb"&gt;chmod &lt;/span&gt;755 /home/banner/jenkins
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Permissions Explanation&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;755&lt;/code&gt; means: owner can read/write/execute, group and others can read/execute&lt;/li&gt;
&lt;li&gt;This is necessary for Jenkins to create subdirectories and store build artifacts&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Problem 4: SSH Connection Issues
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Potential Errors:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Connection timeout&lt;/li&gt;
&lt;li&gt;Authentication failed&lt;/li&gt;
&lt;li&gt;Host key verification failed&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Troubleshooting Steps:&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Test SSH connectivity manually:&lt;/strong&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;ssh tony@stapp01
&lt;span class="c"&gt;# If this fails, the issue is not Jenkins-specific&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Check firewall rules:&lt;/strong&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# On the agent server&lt;/span&gt;
&lt;span class="nb"&gt;sudo &lt;/span&gt;firewall-cmd &lt;span class="nt"&gt;--list-all&lt;/span&gt;
&lt;span class="c"&gt;# Ensure port 22 is open&lt;/span&gt;

&lt;span class="c"&gt;# If needed, add the rule&lt;/span&gt;
&lt;span class="nb"&gt;sudo &lt;/span&gt;firewall-cmd &lt;span class="nt"&gt;--permanent&lt;/span&gt; &lt;span class="nt"&gt;--add-service&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;ssh
&lt;span class="nb"&gt;sudo &lt;/span&gt;firewall-cmd &lt;span class="nt"&gt;--reload&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Verify SSH service is running:&lt;/strong&gt;
&lt;/li&gt;
&lt;/ol&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 status sshd
&lt;span class="nb"&gt;sudo &lt;/span&gt;systemctl start sshd
&lt;span class="nb"&gt;sudo &lt;/span&gt;systemctl &lt;span class="nb"&gt;enable &lt;/span&gt;sshd
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Check SSH key permissions:&lt;/strong&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Private key on Jenkins controller should be 600&lt;/span&gt;
&lt;span class="nb"&gt;chmod &lt;/span&gt;600 ~/.ssh/id_rsa

&lt;span class="c"&gt;# Public key on agent server should be in authorized_keys&lt;/span&gt;
&lt;span class="nb"&gt;cat&lt;/span&gt; ~/.ssh/id_rsa.pub &lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; ~/.ssh/authorized_keys
&lt;span class="nb"&gt;chmod &lt;/span&gt;600 ~/.ssh/authorized_keys
&lt;span class="nb"&gt;chmod &lt;/span&gt;700 ~/.ssh
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Verification and Testing
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Step 1: Check Agent Status
&lt;/h3&gt;

&lt;p&gt;After configuration, verify all agents are online:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Go to &lt;strong&gt;Manage Jenkins&lt;/strong&gt; → &lt;strong&gt;Manage Nodes and Clouds&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;All three agents should show a green checkmark indicating they're online&lt;/li&gt;
&lt;li&gt;Click on each agent to view the system information and log&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Step 2: Review Agent Logs
&lt;/h3&gt;

&lt;p&gt;Click on each agent name and check the logs for:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Successful Connection Log:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;[SSH] Opening SSH connection to stapp01:22.
[SSH] Authentication successful.
[SSH] Starting agent process: cd "/home/tony/jenkins" &amp;amp;&amp;amp; java -jar remoting.jar...
INFO: Using /home/tony/jenkins/remoting as a remoting work directory
&amp;lt;===[JENKINS REMOTING CAPACITY]===&amp;gt;channel started
Remoting version: 3.xx
Agent successfully connected and online
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Step 3: Test Build Execution
&lt;/h3&gt;

&lt;p&gt;Create a simple test job to verify agents work correctly:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Create a new &lt;strong&gt;Freestyle project&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;In &lt;strong&gt;General&lt;/strong&gt; section, check &lt;strong&gt;Restrict where this project can be run&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Enter label expression: &lt;code&gt;stapp01&lt;/code&gt; (to test first agent)&lt;/li&gt;
&lt;li&gt;In &lt;strong&gt;Build&lt;/strong&gt; section, add &lt;strong&gt;Execute shell&lt;/strong&gt; build step:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"Testing on &lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;&lt;span class="nb"&gt;hostname&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
java &lt;span class="nt"&gt;-version&lt;/span&gt;
&lt;span class="nb"&gt;whoami
pwd&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;Save and click &lt;strong&gt;Build Now&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Check the console output to verify it ran on the correct agent&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Repeat this test for each label (stapp02, stapp03).&lt;/p&gt;

&lt;h2&gt;
  
  
  Best Practices and Recommendations
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Security
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Use SSH Keys&lt;/strong&gt;: Prefer SSH key authentication over passwords&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Host Key Verification&lt;/strong&gt;: In production, use "Known hosts file Verification Strategy" instead of non-verifying&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Principle of Least Privilege&lt;/strong&gt;: Agent user accounts should have minimal necessary permissions&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Network Segmentation&lt;/strong&gt;: Place Jenkins agents in a secure network zone&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Performance
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Executor Configuration&lt;/strong&gt;: Set number of executors based on CPU cores (typically 1-2 per core)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Disk Space&lt;/strong&gt;: Ensure adequate disk space in remote root directory (workspaces can grow large)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Memory&lt;/strong&gt;: Monitor agent memory usage and adjust Java heap size if needed using JVM Options in node configuration&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Monitoring
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Agent Health&lt;/strong&gt;: Regularly check agent status in Jenkins UI&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Log Monitoring&lt;/strong&gt;: Review agent logs for warnings or errors&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Resource Usage&lt;/strong&gt;: Monitor CPU, memory, and disk usage on agent servers&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Build Queue&lt;/strong&gt;: Watch for builds waiting for available executors&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Maintenance
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Java Updates&lt;/strong&gt;: Keep Java versions updated on both controller and agents&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Jenkins Updates&lt;/strong&gt;: Update Jenkins and plugins regularly&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Agent Cleanup&lt;/strong&gt;: Periodically clean up old workspaces to free disk space&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Backup&lt;/strong&gt;: Include agent configurations in Jenkins backup strategy&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Using Labels Effectively
&lt;/h2&gt;

&lt;p&gt;Labels are powerful for routing builds to appropriate agents:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Example Use Cases:&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;By Application:&lt;/strong&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight groovy"&gt;&lt;code&gt;&lt;span class="n"&gt;pipeline&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;agent&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt; &lt;span class="n"&gt;label&lt;/span&gt; &lt;span class="s1"&gt;'stapp01'&lt;/span&gt; &lt;span class="o"&gt;}&lt;/span&gt;  &lt;span class="c1"&gt;// Run on specific app server&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Multiple Labels:&lt;/strong&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# In agent configuration, labels: "linux docker maven"&lt;/span&gt;
&lt;span class="c"&gt;# In pipeline, agent { label 'linux &amp;amp;&amp;amp; maven' }&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Load Balancing:&lt;/strong&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Don't specify label to use any available agent&lt;/span&gt;
agent any
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Common Pitfalls to Avoid
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Version Mismatches&lt;/strong&gt;: Always match Java versions between controller and agents&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Insufficient Resources&lt;/strong&gt;: Don't overload agents with too many executors&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Ignoring Logs&lt;/strong&gt;: Agent logs provide valuable troubleshooting information&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Hardcoding Hostnames&lt;/strong&gt;: Use labels instead of hardcoding specific node names in jobs&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Poor Credential Management&lt;/strong&gt;: Rotate SSH keys regularly and use Jenkins credential store&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Automated Setup Script
&lt;/h2&gt;

&lt;p&gt;For future deployments, here's a script to automate agent preparation:&lt;/p&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
bash
#!/bin/bash
# prepare_jenkins_agent.sh
# Run this script on each agent server

set -e

JENKINS_USER=$1
JENKINS_DIR="/home/${JENKINS_USER}/jenkins"

echo "=== Preparing Jenkins Agent for user: ${JENKINS_USER} ==="

# Install Java 17
echo "Installing Java 17..."
sudo yum remove -y java-11-openjdk java-11-openjdk-devel 2&amp;gt;/dev/null || true
sudo yum install -y java-17-openjdk java-17-openjdk-devel

# Verify Java installation
echo "Verifying Java installation..."
java -version

# Create Jenkins directory
echo "Creating Jenkins working directory..."
mkdir -p "${JENKINS_DIR}"
chmod 755 "${JENKINS_DIR}"

# Set JAVA_HOME
echo "Setting JAVA_HOME..."
echo 'export JAVA_HOME=/usr/lib/jvm/java-17-openjdk'
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

</description>
      <category>beginners</category>
      <category>devops</category>
      <category>cloud</category>
      <category>cloudcomputing</category>
    </item>
    <item>
      <title>Understanding CDNs: The Heroes Behind Fast Websites</title>
      <dc:creator>Faruq2991</dc:creator>
      <pubDate>Wed, 15 Oct 2025 13:21:57 +0000</pubDate>
      <link>https://forem.com/faruq2991/understanding-cdns-the-heroes-behind-fast-websites-546b</link>
      <guid>https://forem.com/faruq2991/understanding-cdns-the-heroes-behind-fast-websites-546b</guid>
      <description>&lt;p&gt;A &lt;strong&gt;Content Delivery Network (CDN)&lt;/strong&gt; is a globally distributed network of proxy servers used primarily to deliver content from locations closer to the user. CDNs are considered a type of cache.&lt;/p&gt;

&lt;p&gt;The main goal of a CDN is to minimize request latency for users who are geographically far from the origin servers.&lt;/p&gt;

&lt;h3&gt;
  
  
  Function and Components
&lt;/h3&gt;

&lt;p&gt;A CDN is composed of geographically dispersed servers that cache content from the original server (the origin) and deliver it to users from the nearest CDN server. This geographical distribution of servers often includes hundreds of "points of presence".&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Content Served by CDNs:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;CDNs generally serve static files, such as:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  HTML, CSS, and JavaScript files/bundles&lt;/li&gt;
&lt;li&gt;  Images and photos&lt;/li&gt;
&lt;li&gt;  Videos&lt;/li&gt;
&lt;li&gt;  Static assets&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Some CDNs, such as Amazon's CloudFront, also support dynamic content.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;CDN Workflow:&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt; When a user requests a file using a URL provided by the CDN provider.&lt;/li&gt;
&lt;li&gt; The request is routed to the CDN server closest to the user.&lt;/li&gt;
&lt;li&gt; If the CDN server has the requested content in its cache (&lt;em&gt;cache hit&lt;/em&gt;), it delivers it directly to the user.&lt;/li&gt;
&lt;li&gt; If the content is not in the cache (&lt;em&gt;cache miss&lt;/em&gt;), the CDN server requests the file from the origin (which could be a web server or cloud storage like Amazon S3).&lt;/li&gt;
&lt;li&gt; The origin returns the content, optionally including an HTTP header, Time-to-Live (TTL), which defines how long the content should be cached.&lt;/li&gt;
&lt;li&gt; The CDN caches the content and delivers it to the user. Subsequent requests for the same content are served from the cache until the TTL expires.&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Types of CDNs
&lt;/h3&gt;

&lt;p&gt;CDNs can generally be classified into two models: Push and Pull:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Type&lt;/th&gt;
&lt;th&gt;Description&lt;/th&gt;
&lt;th&gt;Content Management&lt;/th&gt;
&lt;th&gt;Best suited for&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Push CDNs&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Receive new content whenever changes occur on the origin server. The content is uploaded directly to the CDN by the content owner.&lt;/td&gt;
&lt;td&gt;Minimizes network traffic since content is uploaded only when new or changed, but maximizes storage on the CDN.&lt;/td&gt;
&lt;td&gt;Sites with a small amount of traffic or content that is not often updated.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Pull CDNs&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Grab new content from the origin server only when the first user requests it. This leaves the content on your server, requiring you to rewrite URLs to point to the CDN.&lt;/td&gt;
&lt;td&gt;Minimizes storage space on the CDN. However, files might be repulled if they expire before they change, potentially causing redundant traffic.&lt;/td&gt;
&lt;td&gt;Sites with heavy traffic, as traffic is spread out more evenly.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h3&gt;
  
  
  Benefits of using a CDN
&lt;/h3&gt;

&lt;p&gt;CDNs offer significant advantages for system design, especially for high-scale, user-facing applications:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt; &lt;strong&gt;Reduced Latency and Improved Performance:&lt;/strong&gt; Users receive content from data centers close to them, significantly reducing latency and boosting performance. In video streaming, the edge server closest to the user delivers the video with very little latency.&lt;/li&gt;
&lt;li&gt; &lt;strong&gt;Reduced Load on Origin Servers:&lt;/strong&gt; CDNs fulfill requests for cached content, lessening the burden on the origin servers and databases.&lt;/li&gt;
&lt;li&gt; &lt;strong&gt;High Availability and Scalability:&lt;/strong&gt; CDNs are resilient against hardware failures and can handle high traffic loads. By shifting static assets to a CDN, it contributes to meeting high availability requirements.&lt;/li&gt;
&lt;li&gt; &lt;strong&gt;Stateless Architecture:&lt;/strong&gt; Using a CDN helps make your origin server architecture more stateless.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;CDNs are often incorporated into comprehensive system designs. For example, consistent hashing is a technique used in large-scale systems like the Akamai CDN to distribute load across caches.&lt;/p&gt;

&lt;h3&gt;
  
  
  Disadvantages and Considerations
&lt;/h3&gt;

&lt;p&gt;While CDNs are crucial for scaling, several factors must be considered:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;strong&gt;Cost:&lt;/strong&gt; CDNs are run by third-party providers, and charges are incurred for data transfers in and out. Costs can be substantial for large volumes of data transfer. To save costs, only the most popular content (e.g., 20% of videos) may be served via CDN, with less popular content served from cheaper storage.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Stale Content:&lt;/strong&gt; If content is updated on the origin server before the TTL expires, the CDN may serve stale data. Setting an appropriate cache expiry time is critical; if too long, content might not be fresh, and if too short, it causes repeat reloading from the origin.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Configuration:&lt;/strong&gt; Using a CDN requires changing URLs for static content to point to the CDN domain.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;CDN Fallback:&lt;/strong&gt; A strategy is required for when the CDN fails (a temporary outage); clients should be able to detect the issue and request resources directly from the origin.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Invalidation:&lt;/strong&gt; Files can be removed from the CDN cache before their TTL expires using vendor-provided APIs or by using object versioning (e.g., adding a version number to the URL).&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Dynamic Content:&lt;/strong&gt; Dynamic content that changes frequently or tasks requiring complex server-side logic might still need to hit the origin server instead of the CDN.
&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%2Fxpon9h6vez3aa0q4cg26.png" alt="CDN Illustration" width="800" height="800"&gt;
&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>webdev</category>
      <category>beginners</category>
      <category>architecture</category>
      <category>softwaredevelopment</category>
    </item>
    <item>
      <title>Why is AWS Lambda so EXPENSIVE: A Comprehensive Guide to AWS Lambda Cost Optimization</title>
      <dc:creator>Faruq2991</dc:creator>
      <pubDate>Sat, 19 Apr 2025 16:56:51 +0000</pubDate>
      <link>https://forem.com/faruq2991/why-is-aws-lambda-so-expensive-a-comprehensive-guide-to-aws-lambda-cost-optimization-2l4f</link>
      <guid>https://forem.com/faruq2991/why-is-aws-lambda-so-expensive-a-comprehensive-guide-to-aws-lambda-cost-optimization-2l4f</guid>
      <description>&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;In the world of cloud computing, serverless architecture has revolutionized the way developers build and deploy applications. At the forefront of this shift is AWS Lambda, Amazon’s event-driven, serverless compute service that lets you run code without provisioning or managing servers. You simply write your code, upload it to Lambda, and AWS takes care of the rest—scaling, fault tolerance, and availability. And best of all, &lt;strong&gt;you only pay for what you use&lt;/strong&gt;. This makes Lambda an attractive choice for startups, enterprise developers, organizations, and DevOps teams looking to reduce operational overhead.&lt;/p&gt;

&lt;p&gt;However, this pay-per-use model also introduces new challenges. Costs can sneak up on you if your functions are not optimized. Excessive memory allocation, inefficient code, or frequent invocations can drive up your bill—especially as your usage scales. This is where &lt;strong&gt;cost optimization&lt;/strong&gt; becomes crucial. Understanding how AWS charges for Lambda and implementing smart strategies to control those costs can mean the difference between a lean cloud budget and unexpected overages.&lt;/p&gt;

&lt;p&gt;In this guide, we’ll explore everything you need to know about optimizing AWS Lambda costs, from how Lambda pricing works to advanced techniques like power tuning and provisioning strategies. Whether you're just starting with Lambda or looking to fine-tune your architecture, this guide will give you the tools and insights to build cost-effective, serverless applications on AWS.&lt;/p&gt;

&lt;h2&gt;
  
  
  AWS Lambda Pricing Model Explained
&lt;/h2&gt;

&lt;p&gt;Before diving into cost optimization techniques, it is important to understand how AWS Lambda pricing works. The Lambda cost structure is designed to be simple and scalable, but it has a few &lt;strong&gt;nuances&lt;/strong&gt; that can impact your billing significantly if overlooked.&lt;/p&gt;

&lt;h3&gt;
  
  
  2.1 Core Pricing Dimensions
&lt;/h3&gt;

&lt;p&gt;Lambda charges you based on two key factors:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1. Number of Invocations&lt;/strong&gt;&lt;br&gt;
You are charged for every invocation of your Lambda function, regardless of how long it runs or whether it returns an error.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;$0.20 per 1 million requests (after the free tier)&lt;/li&gt;
&lt;li&gt;First 1 million requests per month are free&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;2. Duration of Execution&lt;/strong&gt;&lt;br&gt;
Duration is calculated from the time your code begins executing until it returns or otherwise terminates. It is rounded up to the nearest millisecond and based on the memory size you allocate.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Charged at $0.0000166667 per GB-second&lt;/li&gt;
&lt;li&gt;This means both memory allocation and runtime duration directly 
impact cost&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For example:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;A function that uses 512MB of memory and runs for 1 second = 0.5 GB x 1 second = 0.5 GB-seconds&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;strong&gt;2.2 Memory and CPU Relationship&lt;/strong&gt;&lt;br&gt;
When you set the memory for a Lambda function (from 128MB to 10,240MB), AWS proportionally allocates CPU power, network bandwidth, and disk I/O. This means higher memory allocations may reduce runtime, resulting in a trade-off between performance and cost.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Tip&lt;/strong&gt;: More memory might make your function run faster, which can reduce the overall cost.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;strong&gt;2.3 Free Tier&lt;/strong&gt;&lt;br&gt;
Each AWS account receives the following free usage per month:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;1 million requests&lt;/li&gt;
&lt;li&gt;400,000 GB-seconds of compute time.
This is ideal for low-traffic or testing environments. However, it resets monthly and doesn’t carry over unused portions.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;**2.4 Additional Charges&lt;br&gt;
Lambda may also incur charges from the services it interacts with, such as:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;API Gateway: $3.50 per million requests for REST APIs.&lt;/li&gt;
&lt;li&gt;SQS and SNS: Depending on usage tiers.&lt;/li&gt;
&lt;li&gt;Step Functions: Per state transition.&lt;/li&gt;
&lt;li&gt;Data Transfer: Outbound traffic outside AWS region or to the internet.&lt;/li&gt;
&lt;li&gt;CloudWatch Logs: Storage and retrieval of logs.
You’ll also be charged extra for certain Lambda features:&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Provisioned Concurrency&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Keeps functions pre-initialized to avoid cold starts.&lt;/li&gt;
&lt;li&gt;Charged per GB-second of provisioned concurrency and invocation 
duration.
&lt;strong&gt;Lambda@Edge&lt;/strong&gt;

&lt;ul&gt;
&lt;li&gt;Functions associated with CloudFront distributions&lt;/li&gt;
&lt;li&gt;Charges vary by location (edge region execution pricing)
&lt;strong&gt;SnapStart (Java-only)&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;Cold start improvements for Java Lambdas.&lt;/li&gt;

&lt;li&gt;No extra cost currently.&lt;/li&gt;

&lt;/ul&gt;

&lt;p&gt;Now that you understand how AWS Lambda is priced, you're ready to explore actionable techniques to reduce costs, starting with function-level optimization.&lt;/p&gt;

&lt;h2&gt;
  
  
  Cost Optimization Strategies for AWS Lambda
&lt;/h2&gt;

&lt;p&gt;Now that you understand how AWS Lambda billing works, it's time to explore proven techniques to reduce and optimize costs. These strategies will help you save money at the function level, invocation level, and architectural level—without sacrificing performance or scalability.&lt;/p&gt;

&lt;h3&gt;
  
  
  3.1 Optimize Function Memory Allocation
&lt;/h3&gt;

&lt;p&gt;Lambda pricing depends heavily on the amount of memory allocated to your function. More memory means higher cost—but also more CPU power.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Why It Matters:&lt;/strong&gt;&lt;br&gt;
Under-allocating memory may lead to longer execution times, while over-allocating increases costs unnecessarily.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Solution: Use AWS Lambda Power Tuning&lt;/strong&gt;&lt;br&gt;
AWS provides a tool called &lt;a href="https://github.com/alexcasalboni/aws-lambda-power-tuning" rel="noopener noreferrer"&gt;Lambda Power Tuning&lt;/a&gt; that tests your function at different memory sizes and graphs the performance vs. cost.&lt;/p&gt;

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

&lt;ol&gt;
&lt;li&gt;- Clone the power tuning state machine from GitHub.&lt;/li&gt;
&lt;li&gt;- Deploy via AWS SAM or Serverless Framework.&lt;/li&gt;
&lt;li&gt;- Run your Lambda function at various memory settings.&lt;/li&gt;
&lt;li&gt;- Choose the best configuration with the lowest cost per execution.&lt;/li&gt;
&lt;/ol&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Tip:&lt;/strong&gt; Sometimes increasing memory (and hence CPU) can reduce duration, which may lower your total cost.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  3.2 Reduce Function Execution Time
&lt;/h3&gt;

&lt;p&gt;Execution time (duration) is the second major cost driver in Lambda billing. Even a few extra milliseconds across millions of invocations can significantly impact costs.&lt;/p&gt;

&lt;h3&gt;
  
  
  Optimization Tips:
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Use lighter programming languages&lt;/strong&gt; (e.g., Node.js, Go) over heavy ones like Java if possible.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Avoid large dependencies&lt;/strong&gt; or unnecessary libraries. Use tools like webpack or esbuild to bundle and tree-shake your code.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Minimize initialization logic&lt;/strong&gt; outside the handler function.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Use efficient algorithms and I/O operations&lt;/strong&gt; (e.g., async I/O, pagination).&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  3.3 Minimize Invocation Frequency
&lt;/h3&gt;

&lt;p&gt;Reducing how often your function is invoked can directly reduce costs.&lt;/p&gt;

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

&lt;ul&gt;
&lt;li&gt;Batch events: For example, process 10 messages from SQS in one invocation instead of 10 separate invocations.&lt;/li&gt;
&lt;li&gt;Use S3 event filtering to ignore irrelevant object uploads.&lt;/li&gt;
&lt;li&gt;Throttle event sources: For example, use EventBridge rules to limit invocations to specific hours.&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;Example: A DynamoDB stream with 1 record per invocation = 1000 invocations for 1000 records. By batching, you can process the same with just 100 invocations.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  3.4 Choose the Right Invocation Model
&lt;/h3&gt;

&lt;p&gt;Lambda functions can be triggered synchronously (waits for response) or asynchronously (queues and retries). Each has cost implications.&lt;/p&gt;

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

&lt;ul&gt;
&lt;li&gt;Use &lt;strong&gt;asynchronous invocations&lt;/strong&gt; for non-critical background tasks to reduce wait time and API Gateway costs.&lt;/li&gt;
&lt;li&gt;Limit max &lt;strong&gt;retry attempts and DLQs&lt;/strong&gt; (Dead Letter Queues) to avoid paying for redundant retries.&lt;/li&gt;
&lt;li&gt;Use &lt;strong&gt;Step Functions&lt;/strong&gt; to orchestrate complex flows efficiently.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  3.5 Use Provisioned Concurrency Strategically
&lt;/h3&gt;

&lt;p&gt;Provisioned Concurrency solves cold start problems by keeping your Lambda function initialized. But it's not free.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;When to Use:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;For high-traffic, latency-sensitive applications (e.g., login APIs, payments).&lt;/li&gt;
&lt;li&gt;During predictable spikes (e.g., flash sales, product launches).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Optimization Tips:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Enable auto-scaling for Provisioned Concurrency based on real-time traffic.&lt;/li&gt;
&lt;li&gt;Schedule concurrency with Application Auto Scaling using target tracking policies.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  3.6 Batch Processing with Event Sources
&lt;/h3&gt;

&lt;p&gt;Batching helps reduce both invocation count and total execution time.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Key Event Sources to Batch:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Amazon SQS: Set BatchSize up to 10&lt;/li&gt;
&lt;li&gt;Amazon Kinesis &amp;amp; DynamoDB Streams: Set BatchSize up to 10,000 (limited by 6MB payload)&lt;/li&gt;
&lt;/ul&gt;

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

&lt;ul&gt;
&lt;li&gt;Fewer invocations = lower cost&lt;/li&gt;
&lt;li&gt;Faster data processing with fewer context switches&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  3.7 Use SnapStart for Java Functions
&lt;/h3&gt;

&lt;p&gt;Java functions are notorious for cold start latency, which can also lead to higher duration-based costs.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Solution:&lt;/strong&gt;&lt;br&gt;
AWS Lambda SnapStart takes a snapshot of your function’s initialized state, reducing cold starts by up to 10x.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;No cost today, but always review latest AWS pricing.&lt;/li&gt;
&lt;li&gt;Great for APIs, authentication, and latency-sensitive applications using Java.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  3.8 Monitor Usage and Set Alarms
&lt;/h3&gt;

&lt;p&gt;You can’t optimize what you can’t see. Monitoring gives you insight into runtime behavior and cost patterns.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Tools to Use:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;CloudWatch Metrics: Track invocation count, duration, error rate&lt;/li&gt;
&lt;li&gt;CloudWatch Alarms: Alert when usage or duration spikes&lt;/li&gt;
&lt;li&gt;AWS Budgets: Set spending thresholds and receive alerts&lt;/li&gt;
&lt;li&gt;AWS Cost Explorer: Visualize and analyze Lambda usage patterns&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Tip:&lt;/strong&gt; Use anomaly detection in CloudWatch to spot unusual cost spikes early.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  3.9 Use AWS Compute Optimizer for Lambda
&lt;/h3&gt;

&lt;p&gt;AWS Compute Optimizer provides personalized memory recommendations for Lambda functions based on usage.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;How to Use:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Enable Compute Optimizer in your region.&lt;/li&gt;
&lt;li&gt;Wait for recommendations (based on historical data).&lt;/li&gt;
&lt;li&gt;Apply changes using the Lambda console or CLI.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;With these strategies, you're well-equipped to run &lt;strong&gt;Lambda&lt;/strong&gt; functions at minimal cost without sacrificing performance or reliability.&lt;br&gt;
Next, we’ll zoom out and look at &lt;strong&gt;architecture-level tips&lt;/strong&gt; for optimizing cost across your serverless applications.&lt;/p&gt;

&lt;h2&gt;
  
  
  Architecture-Level Cost Optimization Tips
&lt;/h2&gt;

&lt;p&gt;While tuning individual Lambda functions is important, architectural decisions often have a much bigger impact on long-term AWS costs. This section covers cost-conscious design principles for building scalable, efficient serverless applications.&lt;/p&gt;

&lt;h3&gt;
  
  
  4.1 Avoid Over-Architecting
&lt;/h3&gt;

&lt;p&gt;It is tempting to build sophisticated workflows with multiple Lambda functions, queues, and triggers. But complexity adds to your cloud cost.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Best Practices:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Minimize the number of Lambda layers. Combine related logic into a single function when it makes sense.&lt;/li&gt;
&lt;li&gt;Avoid turning simple flows into Step Function chains unless orchestration is absolutely needed.&lt;/li&gt;
&lt;li&gt;Don’t trigger Lambda when a native AWS integration (e.g., S3 + S3 event notifications + S3 lifecycle rules) could do the job without compute.&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;Example: Use Amazon S3’s event filtering to avoid unnecessary Lambda triggers when only a subset of files need processing.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  4.2 Use API Gateway Alternatives
&lt;/h3&gt;

&lt;p&gt;Amazon API Gateway is a powerful service, but it can be expensive, especially for high-volume REST APIs.&lt;/p&gt;

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

&lt;ul&gt;
&lt;li&gt;AWS Application Load Balancer (ALB):

&lt;ul&gt;
&lt;li&gt;Supports Lambda as a target (good for internal/private APIs).&lt;/li&gt;
&lt;li&gt;Lower per-request cost than API Gateway for large volumes.&lt;/li&gt;
&lt;li&gt;Ideal for use cases that don’t require advanced features (rate limiting, custom authorizers, etc.)&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;Direct integrations with services like S3, EventBridge, Step Functions, or AppSync can eliminate the need for Lambda altogether.&lt;/li&gt;

&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;Example: Instead of S3 → Lambda → DynamoDB, consider using S3 Event Notifications to write directly to DynamoDB via a stream processor or by batching in Glue or Step Functions.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  4.3 Filter Events at the Source
&lt;/h3&gt;

&lt;p&gt;If you don’t need every event, filter at the source to reduce Lambda invocations.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Use Cases:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;S3 Event Filtering: Only invoke Lambda on .jpg or .csv file uploads.&lt;/li&gt;
&lt;li&gt;DynamoDB Streams: Filter by operation type (e.g., INSERT only).&lt;/li&gt;
&lt;li&gt;SNS Message Filtering: Use message attributes to selectively route messages to subscribers.
This reduces the number of invocations, leading to lower costs and better throughput.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  4.4 Use CloudFront Functions Instead of Lambda@Edge
&lt;/h3&gt;

&lt;p&gt;Lambda@Edge brings computation closer to the user, but it’s more expensive than CloudFront Functions.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;For lightweight tasks (URL rewrites, redirects)&lt;/li&gt;
&lt;li&gt;Cheaper and faster than Lambda@Edge
Use Lambda@Edge only when necessary, such as:&lt;/li&gt;
&lt;li&gt;Custom authentication&lt;/li&gt;
&lt;li&gt;Advanced request manipulation&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  4.5 Right-Size Your Event Architecture
&lt;/h3&gt;

&lt;p&gt;Event-driven architectures are powerful, but excessive decoupling can lead to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Too many small Lambda functions&lt;/li&gt;
&lt;li&gt;Multiple intermediate queues&lt;/li&gt;
&lt;li&gt;Increased operational and financial overhead
&lt;strong&gt;Optimization Tip:&lt;/strong&gt;
Group related functionality into modular but cost-aware units. For example, combine several low-frequency SQS queues into one and filter events within a single consumer.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  4.6 Optimize Storage and Transfer
&lt;/h3&gt;

&lt;p&gt;Lambda is often part of a pipeline that interacts with S3, DynamoDB, or other services. Data transfer and storage pricing can sneak into your Lambda bill.&lt;br&gt;
&lt;strong&gt;Strategies:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Compress large payloads before transferring between services&lt;/li&gt;
&lt;li&gt;Use S3 Transfer Acceleration only when needed&lt;/li&gt;
&lt;li&gt;Clean up temporary storage in &lt;code&gt;/tmp&lt;/code&gt;  to avoid exceeding limits&lt;/li&gt;
&lt;li&gt;Use VPC endpoints to avoid NAT Gateway data charges when Lambda is inside a VPC&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  4.7 Prefer Async for Non-Critical Tasks
&lt;/h3&gt;

&lt;p&gt;Moving background tasks out of the synchronous request path can reduce load, improve user experience, and reduce Lambda duration costs.&lt;br&gt;
&lt;strong&gt;Services to Use:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;SQS or SNS for decoupled event queues&lt;/li&gt;
&lt;li&gt;Step Functions for structured workflows&lt;/li&gt;
&lt;li&gt;EventBridge for loosely-coupled pub/sub patterns&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  4.8 Review Serverless Alternatives
&lt;/h3&gt;

&lt;p&gt;Sometimes Lambda isn’t the best tool for the job.&lt;br&gt;
&lt;strong&gt;Alternatives to Consider:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;AWS Fargate: For long-running or resource-intensive workloads&lt;/li&gt;
&lt;li&gt;AppRunner: For containerized web apps with simple deployment&lt;/li&gt;
&lt;li&gt;EC2 Spot Instances: For batch workloads needing cost-efficiency&lt;/li&gt;
&lt;li&gt;Step Functions with service integrations: Run tasks without any compute (e.g., write to DynamoDB, send emails, etc.)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These architectural tips, combined with function-level optimization, create a solid foundation for a scalable, cost-effective serverless environment.&lt;br&gt;
Next up, we’ll explore the tools and resources you can use to monitor, analyze, and automate cost savings.&lt;/p&gt;

&lt;h2&gt;
  
  
  Cost Optimization Tools and Resources
&lt;/h2&gt;

&lt;p&gt;While cost optimization strategies are crucial, &lt;strong&gt;tools and services from AWS (and the broader ecosystem)&lt;/strong&gt; can help automate, monitor, and continuously improve your Lambda usage. In this section, we’ll highlight the most valuable tools for analyzing costs, optimizing performance, and staying on budget.&lt;/p&gt;

&lt;h3&gt;
  
  
  5.1 AWS Lambda Power Tuning
&lt;/h3&gt;

&lt;p&gt;A powerful, open-source tool created by AWS Hero &lt;strong&gt;Alex Casalboni&lt;/strong&gt;, this tool helps you find the best memory-size setting for your function by benchmarking it across multiple configurations.&lt;/p&gt;

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

&lt;ul&gt;
&lt;li&gt;Visualizes cost vs. execution time vs. performance&lt;/li&gt;
&lt;li&gt;Integrated with AWS Step Functions&lt;/li&gt;
&lt;li&gt;Supports real invocations and live profiling&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;How to Use:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Clone the &lt;a href="https://github.com/alexcasalboni/aws-lambda-power-tuning" rel="noopener noreferrer"&gt;GitHub repo&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Deploy via the AWS SAM CLI or Serverless Framework&lt;/li&gt;
&lt;li&gt;Run tests against your function&lt;/li&gt;
&lt;li&gt;Review the graph and pick the optimal memory configuration
&amp;gt; Ideal for fine-tuning performance while minimizing cost.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  5.2 AWS Compute Optimizer
&lt;/h3&gt;

&lt;p&gt;Compute Optimizer uses machine learning to recommend memory size adjustments for Lambda functions based on historical usage patterns.&lt;/p&gt;

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

&lt;ul&gt;
&lt;li&gt;Memory size recommendations&lt;/li&gt;
&lt;li&gt;Visibility into over- and under-provisioned functions&lt;/li&gt;
&lt;li&gt;Integrated into the AWS Console&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;How to Enable:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Go to AWS Compute Optimizer in your region&lt;/li&gt;
&lt;li&gt;Enable service for Lambda&lt;/li&gt;
&lt;li&gt;Wait 14+ days for sufficient data to generate insights
&amp;gt; Helps automate part of your memory tuning efforts over time.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  5.3 AWS CloudWatch
&lt;/h3&gt;

&lt;p&gt;CloudWatch provides deep observability for Lambda functions, including invocation count, duration, error rates, and logs.&lt;br&gt;
&lt;strong&gt;Useful for:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Creating alerts when invocation costs spike&lt;/li&gt;
&lt;li&gt;Tracking duration trends over time&lt;/li&gt;
&lt;li&gt;Analyzing cold starts via enhanced metrics&lt;/li&gt;
&lt;li&gt;Setting up dashboards and alarms
Use CloudWatch Insights to query logs and identify slow functions or bloated dependencies.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  5.4 AWS X-Ray
&lt;/h3&gt;

&lt;p&gt;X-Ray is an observability tool that helps visualize and trace Lambda executions, especially helpful for:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Identifying bottlenecks&lt;/li&gt;
&lt;li&gt;Viewing cold starts, retries, and service latencies&lt;/li&gt;
&lt;li&gt;Debugging distributed architectures&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;Turn on X-Ray tracing for each function via the Lambda console or CLI.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  5.5 AWS Cost Explorer
&lt;/h3&gt;

&lt;p&gt;The go-to service for tracking cloud spending across all AWS services—including Lambda.&lt;br&gt;
&lt;strong&gt;Features:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;View cost and usage reports&lt;/li&gt;
&lt;li&gt;Filter Lambda costs by function name, region, usage type&lt;/li&gt;
&lt;li&gt;Analyze spending trends over time&lt;/li&gt;
&lt;li&gt;Identify cost spikes
&amp;gt; Use it alongside Resource Tags to allocate Lambda costs to specific projects or teams.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  5.6 AWS Budgets &amp;amp; Alerts
&lt;/h3&gt;

&lt;p&gt;Set thresholds for your monthly spending and receive alerts if costs exceed limits.&lt;br&gt;
&lt;strong&gt;Best Practices:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Set a monthly budget for Lambda + API Gateway&lt;/li&gt;
&lt;li&gt;Create an alert for unexpected usage spikes&lt;/li&gt;
&lt;li&gt;Send notifications to Slack or email using Amazon SNS&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  5.7 Trusted Advisor (Business/Enterprise)
&lt;/h3&gt;

&lt;p&gt;Provides real-time recommendations across performance, security, and cost optimization.&lt;br&gt;
&lt;strong&gt;Lambda Cost Checks Include:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Underutilized functions&lt;/li&gt;
&lt;li&gt;Over-provisioned memory&lt;/li&gt;
&lt;li&gt;Expired or unused functions&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  5.8 Third-Party Tools
&lt;/h3&gt;

&lt;p&gt;Several external tools provide advanced features for monitoring and optimizing Lambda:&lt;/p&gt;

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

&lt;ul&gt;
&lt;li&gt;Dashbird – Real-time Lambda monitoring with cost estimation&lt;/li&gt;
&lt;li&gt;Lumigo – Tracing, cost analytics, and debugging tools&lt;/li&gt;
&lt;li&gt;Thundra – Observability with detailed breakdowns of duration and memory&lt;/li&gt;
&lt;li&gt;Datadog, New Relic, Dynatrace – Enterprise-level APM for serverless apps&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;By leveraging these tools, you can take a data-driven approach to Lambda cost optimization, automating decisions and catching inefficiencies early before they spiral into high cloud bills.&lt;/p&gt;

&lt;h3&gt;
  
  
  Final Thoughts
&lt;/h3&gt;

&lt;p&gt;AWS Lambda is a game-changing service that enables developers to build scalable, event-driven applications without managing servers. However, costs can quickly add up if functions are poorly configured, inefficiently invoked, or architected without optimization in mind.&lt;/p&gt;

&lt;p&gt;Cost optimization is not a one-time effort—it’s an ongoing practice. As your usage patterns evolve, regularly monitor your Lambda metrics, keep your architecture lean, and leverage the tools AWS offers to stay informed and in control.&lt;br&gt;
By adopting a cost-aware mindset from day one, you’ll not only prevent cloud bill surprises but also build faster, more efficient, and maintainable applications.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Written by &lt;a href="https://www.linkedin.com/in/umar-adam-b938501b1/" rel="noopener noreferrer"&gt;Adamu Umar&lt;/a&gt; a Cloud Engineer &amp;amp; Technical Writer focused on serverless architecture, cost optimization, and building impactful cloud-native applications.&lt;/em&gt;&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Comprehensive Breakdown of a Serverless Resume Uploader Project on AWS</title>
      <dc:creator>Faruq2991</dc:creator>
      <pubDate>Sun, 13 Apr 2025 16:47:49 +0000</pubDate>
      <link>https://forem.com/faruq2991/comprehensive-breakdown-of-a-serverless-resume-uploader-project-on-aws-4bf</link>
      <guid>https://forem.com/faruq2991/comprehensive-breakdown-of-a-serverless-resume-uploader-project-on-aws-4bf</guid>
      <description>&lt;p&gt;This project demonstrates a serverless architecture for uploading and processing resumes using AWS S3, Lambda, DynamoDB, CloudFormation, and SAM. Before we go into the technical aspect, lets understand what event-driven architectures (EDAs) and what a Serverless system is.&lt;/p&gt;

&lt;p&gt;Serverless and EDA are two architectural patterns that complement each other beautifully.&lt;/p&gt;

&lt;p&gt;Serverless doesn’t mean "no servers" — it means you don’t manage the servers. The cloud provider handles provisioning, scaling, and maintenance. You just focus on writing and deploying your business logic that differentiate you from the rest.&lt;br&gt;
In AWS, the most popular serverless compute service is AWS Lambda.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Event-Driven Architecture (EDA)&lt;/strong&gt;&lt;br&gt;
EDA is a system design where events (changes in state or updates) trigger actions. Events are typically emitted, captured, and reacted to using components like event producers, event routers (brokers), and event consumers.&lt;/p&gt;

&lt;p&gt;Think of it like this:&lt;br&gt;
Producer: "Hey! A new user signed up!"&lt;br&gt;
Router: "Got it! Who needs to know about this?"&lt;br&gt;
Consumers: (e.g., send welcome email, add to CRM, log signup)&lt;/p&gt;

&lt;p&gt;Now that we have that out of the way, below is a detailed, step-by-step explanation of the project architecture, covering infrastructure setup, deployment, automation, and best practices.&lt;/p&gt;
&lt;h2&gt;
  
  
  1. Project Overview
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Objective&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Build a &lt;strong&gt;serverless system&lt;/strong&gt; that:

&lt;ol&gt;
&lt;li&gt;Accepts resume uploads via &lt;strong&gt;S3.&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Triggers a &lt;strong&gt;Lambda function&lt;/strong&gt; on file upload.&lt;/li&gt;
&lt;li&gt;Stores metadata (filename,timestamp,size) in &lt;strong&gt;DynamoDB.&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Uses &lt;strong&gt;Infrastructure as Code (IaC)&lt;/strong&gt; for reproducibility.&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;
  
  
  Key AWS Services Used
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;AWS S3&lt;/strong&gt;              Stores uploaded resumes&lt;br&gt;
 &lt;strong&gt;AWS Lambda&lt;/strong&gt;          Processes files and updates metadata&lt;br&gt;
 &lt;strong&gt;IAM&lt;/strong&gt;                 Security permissions &lt;br&gt;
 &lt;strong&gt;AWS CloudFormation&lt;/strong&gt;  Infrastructure as Code (IaC)&lt;br&gt;
 &lt;strong&gt;AWS SAM&lt;/strong&gt;             Simplifies serverless deployments&lt;br&gt;
 &lt;strong&gt;DynamoDB&lt;/strong&gt;            Stores file metatdata (NoSQL)&lt;/p&gt;
&lt;h2&gt;
  
  
  2. Step-by-Step Execution Breakdown
&lt;/h2&gt;
&lt;h3&gt;
  
  
  Phase 1: Infrastructure Deployment (Core AWS Resources)
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Goal: Deploy S3 bucket + DynamoDB table independently to avoid circular dependencies.&lt;/strong&gt;&lt;br&gt;
&lt;strong&gt;What Happened?&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;CloudFormation Template &lt;code&gt;(infrastructure.yaml)&lt;/code&gt; defined:&lt;/strong&gt;

&lt;ul&gt;
&lt;li&gt;S3 Bucket &lt;code&gt;(UploadBucket)&lt;/code&gt; for storing resumes.&lt;/li&gt;
&lt;li&gt;DynamoDB Table &lt;code&gt;(FileMetadataTable)&lt;/code&gt; for tracking metadata.&lt;/li&gt;
&lt;li&gt;IAM Roles for least-privilege access.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Deployed via CLI:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;pre class="highlight plaintext"&gt;&lt;code&gt;    aws cloudformation deploy \
        --template-file infrastructure.yaml \
        --stack-name ServerlessResumeUploader-Infra \
        --capabilities CAPABILITY_IAM
&lt;/code&gt;&lt;/pre&gt;




&lt;/li&gt;

&lt;/ol&gt;

&lt;ul&gt;
&lt;li&gt;CloudFormation &lt;strong&gt;provisioned resources sequentially&lt;/strong&gt; (IAM → S3 → DynamoDB).&lt;/li&gt;
&lt;li&gt;Outputs &lt;code&gt;(BucketName, TableName)&lt;/code&gt; were stored for cross-stack reference.&lt;/li&gt;
&lt;/ul&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Verification:&lt;/strong&gt;
&lt;code&gt;aws cloudformation describe-stacks --stack-name ServerlessResumeUploader-Infra&lt;/code&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Phase 2: Lambda Function Deployment (Processing Logic)
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Goal: Deploy Lambda function that processes uploads and updates DynamoDB.&lt;/strong&gt;&lt;br&gt;
&lt;strong&gt;What Happened?&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;AWS SAM Template&lt;/strong&gt; &lt;code&gt;(lambda.yaml)&lt;/code&gt; defined:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Lambda Function&lt;/strong&gt; &lt;code&gt;(FileMetadataFunction)&lt;/code&gt; in Python.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;IAM Policies&lt;/strong&gt; (auto-generated by SAM for S3 + DynamoDB access).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Environment Variables&lt;/strong&gt; (DynamoDB table name, bucket name).&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Deployed via SAM CLI:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;pre class="highlight plaintext"&gt;&lt;code&gt;   sam deploy \
        --template-file lambda.yaml \
        --stack-name ServerlessResumeUploader-Lambda \
        --parameter-overrides BucketName=... TableName=... \
        --capabilities CAPABILITY_IAM 
&lt;/code&gt;&lt;/pre&gt;




&lt;/li&gt;

&lt;/ol&gt;

&lt;ul&gt;
&lt;li&gt;SAM automatically:

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Packaged&lt;/strong&gt; Lambda code into a .zip.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Uploaded&lt;/strong&gt; to S3.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Generated expanded CloudFormation template&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;Deployed using CloudFormation.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Behind the Scenes:&lt;/strong&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;SAM simplified Lambda definition&lt;/strong&gt; (vs raw CloudFormation).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Auto-generated IAM policies&lt;/strong&gt; (no manual JSON needed).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Managed cross-stack references&lt;/strong&gt; (bucket + table names).&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Phase 3: Permission &amp;amp; Event Configuration
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Goal: Allow S3 to trigger Lambda when a file is uploaded.&lt;/strong&gt;&lt;br&gt;
&lt;strong&gt;What Happened?&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Granted S3 Permission to Invoke Lambda&lt;/strong&gt;:

&lt;ul&gt;
&lt;li&gt;Ensures &lt;strong&gt;only the S3 bucket&lt;/strong&gt; can call this Lambda function.
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;       aws lambda add-permission \
            --function-name FileMetadataFunction \
            --principal s3.amazonaws.com \
            --action lambda:InvokeFunction \
            --source-arn arn:aws:s3:::upload-bucket-name
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Configured S3 Event Notification:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;pre class="highlight plaintext"&gt;&lt;code&gt;    aws s3api put-bucket-notification-configuration \
        --bucket upload-bucket-name \
        --notification-configuration '{
          "LambdaFunctionConfigurations": [{
            "LambdaFunctionArn": "arn:aws:lambda:...",
            "Events": ["s3:ObjectCreated:*"]
          }]
       }'
&lt;/code&gt;&lt;/pre&gt;




&lt;/li&gt;

&lt;/ol&gt;

&lt;h2&gt;
  
  
  Phase 4: System Verification (Testing)
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Goal: Ensure end-to-end workflow works.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1. Uploaded a Test File&lt;/strong&gt;:&lt;br&gt;
    &lt;code&gt;aws s3 cp resume.pdf s3://upload-bucket-name/test-resume.pdf&lt;/code&gt;&lt;br&gt;
  &lt;strong&gt;2. Lambda Execution&lt;/strong&gt;:&lt;br&gt;
      - S3 event triggered Lambda.&lt;br&gt;
      - Lambda processed the file (extracted metadata).&lt;br&gt;
      - Stored data in DynamoDB:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;   ```
     {
       "fileId": "123",
       "fileName": "test-resume.pdf",
       "uploadTime": "2024-04-09T12:00:00Z",
       "fileSize": "250KB"
     }
   ```
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;3. Verified Logs &amp;amp; DynamoDB&lt;/strong&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;       # Check Lambda logs
       aws logs tail /aws/lambda/FileMetadataFunction

       # Scan DynamoDB
       aws dynamodb scan --table-name FileMetadataTable
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  3. Key Technical Takeaways
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;1. CloudFormation’s Role&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Infrastructure as Code (IaC): Defined all resources in YAML.&lt;/li&gt;
&lt;li&gt;Dependency Management: Handled IAM → Lambda → S3 → DynamoDB order.&lt;/li&gt;
&lt;li&gt;Cross-Stack References: Used outputs/parameters to link stacks.&lt;/li&gt;
&lt;li&gt;Rollback Safety: If Lambda deployment failed, CloudFormation rolledback.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;2. AWS SAM’s Advantages&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Simplified Serverless Deployments:

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;AWS::Serverless::Function&lt;/code&gt; vs &lt;code&gt;AWS::Lambda::Function&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Auto-packaging &lt;code&gt;sam package&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Built-in IAM policies (&lt;code&gt;S3CrudPolicy&lt;/code&gt;, &lt;code&gt;DynamoDBCrudPolicy&lt;/code&gt;).&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;Local Testing &lt;code&gt;sam local invoke&lt;/code&gt;
&lt;/li&gt;

&lt;li&gt;Guided Deployments &lt;code&gt;sam deploy --guided&lt;/code&gt;
&lt;/li&gt;

&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;3. Event-Driven Architecture&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;S3 → Lambda → DynamoDB flow.&lt;/li&gt;
&lt;li&gt;Fully automated (no servers to manage).&lt;/li&gt;
&lt;li&gt;Scalable (handles 1 or 1,000 uploads seamlessly).&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  4. Best Practices Followed
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Least Privilege IAM&lt;/strong&gt;       SAM auto-generated minimal policies.&lt;br&gt;
&lt;strong&gt;Separation of Concerns&lt;/strong&gt;    Split infra (S3/DynamoDB) and app (Lambda) stacks.&lt;br&gt;
&lt;strong&gt;Idempotent Deployments&lt;/strong&gt;    CloudFormation ensures consistency.&lt;br&gt;
&lt;strong&gt;Automated Testing&lt;/strong&gt;         sam local invoke before deployment.&lt;br&gt;
&lt;strong&gt;Infrastructure Versioning&lt;/strong&gt; Templates stored in Git.&lt;/p&gt;

&lt;p&gt;The separation into two stacks makes sense because:&lt;br&gt;
Separation of Concerns - Each stack handles a distinct functional area (resume uploads vs general S3 metadata processing)&lt;br&gt;
Resource Isolation - Keeps resources for different purposes logically separated&lt;br&gt;
Independent Scaling - Each stack can be updated and scaled independently&lt;br&gt;
Security Boundaries - Different IAM permissions can be applied to each stack&lt;br&gt;
Maintainability - Smaller, focused stacks are easier to manage than one monolithic stack.&lt;/p&gt;

</description>
      <category>devops</category>
      <category>aws</category>
      <category>architecture</category>
      <category>microservices</category>
    </item>
    <item>
      <title>Automating User and Group Management with a Bash Script</title>
      <dc:creator>Faruq2991</dc:creator>
      <pubDate>Wed, 03 Jul 2024 14:17:31 +0000</pubDate>
      <link>https://forem.com/faruq2991/automating-user-and-group-management-with-a-bash-script-33fj</link>
      <guid>https://forem.com/faruq2991/automating-user-and-group-management-with-a-bash-script-33fj</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;I recently got accepted into the famous(&lt;a href="https://hng.tech/hire"&gt;https://hng.tech/hire&lt;/a&gt;). It is a very intense hands-on 8 week program where your skills will be tested and legends are made. As a requirement for proceeding to the next stage, interns on every track are given tasks they are expected to execute, document and write an article to pass. this blog post is such.&lt;br&gt;
I would recommend anyone willing to upskill and gain employable skill to enroll into the program. (&lt;a href="https://hng.tech/premium"&gt;https://hng.tech/premium&lt;/a&gt;) &lt;a href="https://hng.tech/internship"&gt;https://hng.tech/internship&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Hey there, fellow Sysadmin! We can all agree that managing users and groups is a bit difficult and time consuming. Trust me, I've been there. Picture this: it's 2 AM, you're knee-deep in energy drink cans, trying to add the 50th user to your system. Your eyes are crossing, and you're pretty sure you just gave someone access to critical codes by mistake. We've all been there, right? Well, chin up, because I'm about to introduce you to your new best friend: a Bash script that'll make user management a breeze!&lt;/p&gt;

&lt;h4&gt;
  
  
  Script Breakdown
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;   declare -a users
   declare -a groups
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The script starts with a shebang (&lt;code&gt;#!/bin/bash&lt;/code&gt;) to specify the interpreter. It then declares two arrays, &lt;code&gt;users&lt;/code&gt; and &lt;code&gt;groups&lt;/code&gt;, to hold user and group data.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Argument Check&lt;/strong&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;   &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;[[&lt;/span&gt; &lt;span class="nv"&gt;$# &lt;/span&gt;&lt;span class="nt"&gt;-ne&lt;/span&gt; 1 &lt;span class="o"&gt;]]&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then
     &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"Usage: &lt;/span&gt;&lt;span class="nv"&gt;$0&lt;/span&gt;&lt;span class="s2"&gt; &amp;lt;input_file&amp;gt;"&lt;/span&gt;
     &lt;span class="nb"&gt;exit &lt;/span&gt;1
   &lt;span class="k"&gt;fi

   &lt;/span&gt;&lt;span class="nv"&gt;input_file&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$1&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
   &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"Reading input file: &lt;/span&gt;&lt;span class="nv"&gt;$input_file&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The script checks and confirm that the script is run is run with exactly one argument (the input file). Otherwise, the exit code 1 is triggered which which indicates failure. The input file is then assigned to the variable &lt;code&gt;input_file&lt;/code&gt;.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Reading the Input File&lt;/strong&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;   &lt;span class="k"&gt;function &lt;/span&gt;read_input&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
     &lt;span class="nb"&gt;local &lt;/span&gt;&lt;span class="nv"&gt;file&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$1&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;

     &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;[[&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt; &lt;span class="nt"&gt;-f&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$file&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="o"&gt;]]&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then
       &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"File not found!"&lt;/span&gt;
       &lt;span class="k"&gt;return &lt;/span&gt;1
     &lt;span class="k"&gt;fi

     while &lt;/span&gt;&lt;span class="nv"&gt;IFS&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;read&lt;/span&gt; &lt;span class="nt"&gt;-r&lt;/span&gt; line&lt;span class="p"&gt;;&lt;/span&gt; 
     &lt;span class="k"&gt;do
       &lt;/span&gt;&lt;span class="nv"&gt;user&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$line&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; | &lt;span class="nb"&gt;cut&lt;/span&gt; &lt;span class="nt"&gt;-d&lt;/span&gt;&lt;span class="s1"&gt;';'&lt;/span&gt; &lt;span class="nt"&gt;-f1&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;
       &lt;span class="nv"&gt;groups_list&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$line&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; | &lt;span class="nb"&gt;cut&lt;/span&gt; &lt;span class="nt"&gt;-d&lt;/span&gt;&lt;span class="s1"&gt;';'&lt;/span&gt; &lt;span class="nt"&gt;-f2&lt;/span&gt; | &lt;span class="nb"&gt;tr&lt;/span&gt; &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="s1"&gt;'[:space:]'&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;
       &lt;span class="nb"&gt;users&lt;/span&gt;+&lt;span class="o"&gt;=(&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$user&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
       &lt;span class="nb"&gt;groups&lt;/span&gt;+&lt;span class="o"&gt;=(&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$groups_list&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
     &lt;span class="k"&gt;done&lt;/span&gt; &amp;lt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$file&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
   &lt;span class="o"&gt;}&lt;/span&gt;

   read_input &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$input_file&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;read_input&lt;/code&gt; function reads the input file line by line. Each line read is expected to contain a username and a comma-separated(delimiter) list of groups, separated by a semicolon. The function splits each line into a user and their groups, then adds these to the respective arrays.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Verification of Data&lt;/strong&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;   &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"Users: &lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;users&lt;/span&gt;&lt;span class="p"&gt;[@]&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
   &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"Groups: &lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;groups&lt;/span&gt;&lt;span class="p"&gt;[@]&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The script prints the &lt;code&gt;users&lt;/code&gt; and &lt;code&gt;groups&lt;/code&gt; arrays to verify the data read from the input file.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Log and Password Files Setup&lt;/strong&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;   &lt;span class="nv"&gt;log_file&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"/var/log/user_management.log"&lt;/span&gt;
   &lt;span class="nv"&gt;password_file&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"/var/secure/user_passwords.txt"&lt;/span&gt;

   &lt;span class="nb"&gt;touch&lt;/span&gt; &lt;span class="nv"&gt;$log_file&lt;/span&gt;
   &lt;span class="nb"&gt;mkdir&lt;/span&gt; &lt;span class="nt"&gt;-p&lt;/span&gt; &lt;span class="si"&gt;$(&lt;/span&gt;&lt;span class="nb"&gt;dirname&lt;/span&gt; &lt;span class="nv"&gt;$password_file&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;
   &lt;span class="nb"&gt;touch&lt;/span&gt; &lt;span class="nv"&gt;$password_file&lt;/span&gt;

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

&lt;/div&gt;



&lt;p&gt;The script sets up paths for a log file and a password file. It creates these files and their parent directories if they do not exist.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;User and Group Management&lt;/strong&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;   &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="o"&gt;((&lt;/span&gt; i &lt;span class="o"&gt;=&lt;/span&gt; 0&lt;span class="p"&gt;;&lt;/span&gt; i &amp;lt; &lt;span class="k"&gt;${#&lt;/span&gt;&lt;span class="nv"&gt;users&lt;/span&gt;&lt;span class="p"&gt;[@]&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; i++ &lt;span class="o"&gt;))&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;do
     &lt;/span&gt;&lt;span class="nv"&gt;user&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;users&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;$i&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
     &lt;span class="nv"&gt;user_groups&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;groups&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;$i&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
     &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="nb"&gt;id&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$user&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &amp;amp;&amp;gt;/dev/null&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then
       &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"User &lt;/span&gt;&lt;span class="nv"&gt;$user&lt;/span&gt;&lt;span class="s2"&gt; already exists, Skipped"&lt;/span&gt; | &lt;span class="nb"&gt;tee&lt;/span&gt; &lt;span class="nt"&gt;-a&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$log_file&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
     &lt;span class="k"&gt;else&lt;/span&gt;
       &lt;span class="c"&gt;# Create user&lt;/span&gt;
       useradd &lt;span class="nt"&gt;-m&lt;/span&gt; &lt;span class="nt"&gt;-s&lt;/span&gt; /bin/bash &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$user&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
       &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;[[&lt;/span&gt; &lt;span class="nv"&gt;$?&lt;/span&gt; &lt;span class="nt"&gt;-ne&lt;/span&gt; 0 &lt;span class="o"&gt;]]&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then
         &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"Failed to create user &lt;/span&gt;&lt;span class="nv"&gt;$user&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; | &lt;span class="nb"&gt;tee&lt;/span&gt; &lt;span class="nt"&gt;-a&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$log_file&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
         &lt;span class="nb"&gt;exit &lt;/span&gt;1
       &lt;span class="k"&gt;fi
       &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"User &lt;/span&gt;&lt;span class="nv"&gt;$user&lt;/span&gt;&lt;span class="s2"&gt; created"&lt;/span&gt; | &lt;span class="nb"&gt;tee&lt;/span&gt; &lt;span class="nt"&gt;-a&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$log_file&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;

       &lt;span class="nv"&gt;password&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;openssl rand &lt;span class="nt"&gt;-base64&lt;/span&gt; 50 | &lt;span class="nb"&gt;tr&lt;/span&gt; &lt;span class="nt"&gt;-dc&lt;/span&gt; &lt;span class="s1"&gt;'A-Za-z0-9!?%='&lt;/span&gt; | &lt;span class="nb"&gt;head&lt;/span&gt; &lt;span class="nt"&gt;-c&lt;/span&gt; 10&lt;span class="si"&gt;)&lt;/span&gt;
       &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$user&lt;/span&gt;&lt;span class="s2"&gt;:&lt;/span&gt;&lt;span class="nv"&gt;$password&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; | chpasswd
       &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;[[&lt;/span&gt; &lt;span class="nv"&gt;$?&lt;/span&gt; &lt;span class="nt"&gt;-ne&lt;/span&gt; 0 &lt;span class="o"&gt;]]&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then
         &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"Failed to set password for &lt;/span&gt;&lt;span class="nv"&gt;$user&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; | &lt;span class="nb"&gt;tee&lt;/span&gt; &lt;span class="nt"&gt;-a&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$log_file&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
         &lt;span class="nb"&gt;exit &lt;/span&gt;1
       &lt;span class="k"&gt;fi
       &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"Password for &lt;/span&gt;&lt;span class="nv"&gt;$user&lt;/span&gt;&lt;span class="s2"&gt; set"&lt;/span&gt; | &lt;span class="nb"&gt;tee&lt;/span&gt; &lt;span class="nt"&gt;-a&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$log_file&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
       &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$user&lt;/span&gt;&lt;span class="s2"&gt;:&lt;/span&gt;&lt;span class="nv"&gt;$password&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$password_file&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;

       &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="nb"&gt;grep&lt;/span&gt; &lt;span class="nt"&gt;-q&lt;/span&gt; &lt;span class="s2"&gt;"^&lt;/span&gt;&lt;span class="nv"&gt;$user&lt;/span&gt;&lt;span class="s2"&gt;:"&lt;/span&gt; /etc/group&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then
         &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"Personal group &lt;/span&gt;&lt;span class="nv"&gt;$user&lt;/span&gt;&lt;span class="s2"&gt; already exists"&lt;/span&gt; | &lt;span class="nb"&gt;tee&lt;/span&gt; &lt;span class="nt"&gt;-a&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$log_file&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
       &lt;span class="k"&gt;else
         &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"Personal group &lt;/span&gt;&lt;span class="nv"&gt;$user&lt;/span&gt;&lt;span class="s2"&gt; does not exist, creating &lt;/span&gt;&lt;span class="nv"&gt;$user&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; | &lt;span class="nb"&gt;tee&lt;/span&gt; &lt;span class="nt"&gt;-a&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$log_file&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
         groupadd &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$user&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
         &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;[[&lt;/span&gt; &lt;span class="nv"&gt;$?&lt;/span&gt; &lt;span class="nt"&gt;-ne&lt;/span&gt; 0 &lt;span class="o"&gt;]]&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then
           &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"Failed to create personal group &lt;/span&gt;&lt;span class="nv"&gt;$user&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; | &lt;span class="nb"&gt;tee&lt;/span&gt; &lt;span class="nt"&gt;-a&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$log_file&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
           &lt;span class="nb"&gt;exit &lt;/span&gt;1
         &lt;span class="k"&gt;fi
       fi

       &lt;/span&gt;usermod &lt;span class="nt"&gt;-aG&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$user&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$user&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
       &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;[[&lt;/span&gt; &lt;span class="nv"&gt;$?&lt;/span&gt; &lt;span class="nt"&gt;-ne&lt;/span&gt; 0 &lt;span class="o"&gt;]]&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then
         &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"Failed to add &lt;/span&gt;&lt;span class="nv"&gt;$user&lt;/span&gt;&lt;span class="s2"&gt; to &lt;/span&gt;&lt;span class="nv"&gt;$user&lt;/span&gt;&lt;span class="s2"&gt; group"&lt;/span&gt; | &lt;span class="nb"&gt;tee&lt;/span&gt; &lt;span class="nt"&gt;-a&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$log_file&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
         &lt;span class="nb"&gt;exit &lt;/span&gt;1
       &lt;span class="k"&gt;fi
       &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"Added &lt;/span&gt;&lt;span class="nv"&gt;$user&lt;/span&gt;&lt;span class="s2"&gt; to &lt;/span&gt;&lt;span class="nv"&gt;$user&lt;/span&gt;&lt;span class="s2"&gt; group"&lt;/span&gt; | &lt;span class="nb"&gt;tee&lt;/span&gt; &lt;span class="nt"&gt;-a&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$log_file&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;

       &lt;span class="k"&gt;for &lt;/span&gt;group &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="si"&gt;$(&lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$user_groups&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; | &lt;span class="nb"&gt;tr&lt;/span&gt; &lt;span class="s1"&gt;','&lt;/span&gt; &lt;span class="s1"&gt;'\n'&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;do
         if &lt;/span&gt;&lt;span class="nb"&gt;grep&lt;/span&gt; &lt;span class="nt"&gt;-q&lt;/span&gt; &lt;span class="s2"&gt;"^&lt;/span&gt;&lt;span class="nv"&gt;$group&lt;/span&gt;&lt;span class="s2"&gt;:"&lt;/span&gt; /etc/group&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then
           &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"Group &lt;/span&gt;&lt;span class="nv"&gt;$group&lt;/span&gt;&lt;span class="s2"&gt; already exists"&lt;/span&gt; | &lt;span class="nb"&gt;tee&lt;/span&gt; &lt;span class="nt"&gt;-a&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$log_file&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
         &lt;span class="k"&gt;else
           &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"Group &lt;/span&gt;&lt;span class="nv"&gt;$group&lt;/span&gt;&lt;span class="s2"&gt; does not exist, creating &lt;/span&gt;&lt;span class="nv"&gt;$group&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; | &lt;span class="nb"&gt;tee&lt;/span&gt; &lt;span class="nt"&gt;-a&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$log_file&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
           groupadd &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$group&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
           &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;[[&lt;/span&gt; &lt;span class="nv"&gt;$?&lt;/span&gt; &lt;span class="nt"&gt;-ne&lt;/span&gt; 0 &lt;span class="o"&gt;]]&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then
             &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"Failed to create group &lt;/span&gt;&lt;span class="nv"&gt;$group&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; | &lt;span class="nb"&gt;tee&lt;/span&gt; &lt;span class="nt"&gt;-a&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$log_file&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
             &lt;span class="nb"&gt;exit &lt;/span&gt;1
           &lt;span class="k"&gt;fi
         fi

         &lt;/span&gt;usermod &lt;span class="nt"&gt;-aG&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$group&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$user&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
         &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;[[&lt;/span&gt; &lt;span class="nv"&gt;$?&lt;/span&gt; &lt;span class="nt"&gt;-ne&lt;/span&gt; 0 &lt;span class="o"&gt;]]&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then
           &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"Failed to add &lt;/span&gt;&lt;span class="nv"&gt;$user&lt;/span&gt;&lt;span class="s2"&gt; to &lt;/span&gt;&lt;span class="nv"&gt;$group&lt;/span&gt;&lt;span class="s2"&gt; group"&lt;/span&gt; | &lt;span class="nb"&gt;tee&lt;/span&gt; &lt;span class="nt"&gt;-a&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$log_file&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
           &lt;span class="nb"&gt;exit &lt;/span&gt;1
         &lt;span class="k"&gt;fi
         &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"Added &lt;/span&gt;&lt;span class="nv"&gt;$user&lt;/span&gt;&lt;span class="s2"&gt; to &lt;/span&gt;&lt;span class="nv"&gt;$group&lt;/span&gt;&lt;span class="s2"&gt; group"&lt;/span&gt; | &lt;span class="nb"&gt;tee&lt;/span&gt; &lt;span class="nt"&gt;-a&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$log_file&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
       &lt;span class="k"&gt;done
     fi
   done&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The main loop iterates over the &lt;code&gt;users&lt;/code&gt; and &lt;code&gt;groups&lt;/code&gt; arrays. For each user:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;If the user already exists, it logs and skips to the next user.&lt;/li&gt;
&lt;li&gt;If the user does not exist, it creates the user, sets a password, logs the details, and creates a personal group if it does not exist.&lt;/li&gt;
&lt;li&gt;The user is added to their personal group and any additional groups specified.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This script provides a comprehensive solution for automating the management of users and groups, ensuring consistent and secure setups based on predefined input data.&lt;/p&gt;

</description>
      <category>devops</category>
      <category>linux</category>
      <category>cloud</category>
      <category>automation</category>
    </item>
    <item>
      <title>Understanding Ansible Roles: A Comprehensive Guide</title>
      <dc:creator>Faruq2991</dc:creator>
      <pubDate>Sun, 23 Jun 2024 03:41:43 +0000</pubDate>
      <link>https://forem.com/faruq2991/understanding-ansible-roles-a-comprehensive-guide-2bbj</link>
      <guid>https://forem.com/faruq2991/understanding-ansible-roles-a-comprehensive-guide-2bbj</guid>
      <description>&lt;p&gt;In IT automation, Ansible is a powerful and an easy to use tool. Among its various features, Ansible Roles stand out as a critical component for managing complex configurations and deployments. This article explains why Ansible Roles are essential, their usage scenarios, appropriate times to leverage on them, and a simple guide to implementing them.&lt;/p&gt;

&lt;h4&gt;
  
  
  Why Ansible Roles are Needed
&lt;/h4&gt;

&lt;p&gt;Ansible Roles provide a structured way of organizing playbooks, making complex playbooks more manageable, reusable, and scalable. Here are why Ansible Roles are indispensable:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Modularity&lt;/strong&gt;: Roles allow breaking down playbooks into reusable components. Each role can manage a particular aspect of the system, such as installing a web server or configuring a database.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Reusability&lt;/strong&gt;: Once created, roles can be reused across different projects and environments, reducing effort.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Maintainability&lt;/strong&gt;: By organizing tasks, variables, handlers, and other components into separate directories, roles make the codebase easier to navigate and maintain.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Scalability&lt;/strong&gt;: As infrastructure grows, roles help manage complexity by providing a clear structure, making it easier to scale configurations.&lt;/li&gt;
&lt;/ol&gt;

&lt;h4&gt;
  
  
  Where Ansible Roles are Used
&lt;/h4&gt;

&lt;p&gt;Ansible Roles are used in a variety of contexts, including:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Infrastructure as Code (IaC)&lt;/strong&gt;: Managing and provisioning infrastructure in a consistent and repeatable manner.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Application Deployment&lt;/strong&gt;: Deploying applications with all necessary dependencies and configurations.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Configuration Management&lt;/strong&gt;: Ensuring systems are configured correctly and consistently across environments.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Continuous Integration/Continuous Deployment (CI/CD)&lt;/strong&gt;: Integrating with CI/CD pipelines to automate the deployment process.&lt;/li&gt;
&lt;/ol&gt;

&lt;h4&gt;
  
  
  When to Use Ansible Roles
&lt;/h4&gt;

&lt;p&gt;Ansible Roles should be used when:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Managing Large Codebases&lt;/strong&gt;: For projects with large and complex playbooks, roles help in organizing and simplifying the code.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Promoting Code Reusability&lt;/strong&gt;: When there is a need to use the same configuration across multiple projects or environments.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Improving Collaboration&lt;/strong&gt;: In teams where multiple developers or operators are working on the same codebase, roles enhance collaboration by providing a clear structure.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Automating Repetitive Tasks&lt;/strong&gt;: For tasks that are repetitive and consistent across different environments, roles ensure standardization and efficiency.&lt;/li&gt;
&lt;/ol&gt;

&lt;h4&gt;
  
  
  How to Implement Ansible Roles
&lt;/h4&gt;

&lt;p&gt;Implementing Ansible Roles involves several steps, which are outlined below:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Create the Role Directory Structure&lt;/strong&gt;: Ansible provides a command to create a role's directory structure.&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;ansible-galaxy init &amp;lt;role_name&amp;gt;
&lt;/code&gt;&lt;/pre&gt;


&lt;p&gt;This command creates a directory structure with subdirectories for tasks, handlers, files, templates, vars, defaults, and meta.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Define Tasks&lt;/strong&gt;: The main logic of the role is defined in the &lt;code&gt;tasks&lt;/code&gt; directory. Create a &lt;code&gt;main.yml&lt;/code&gt; file within this directory to list all tasks.&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="c1"&gt;# roles/&amp;lt;role_name&amp;gt;/tasks/main.yml&lt;/span&gt;
&lt;span class="nn"&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;/code&gt;&lt;/pre&gt;

&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Add Handlers&lt;/strong&gt;: If there are services that need to be restarted or actions triggered by changes, define them in the &lt;code&gt;handlers&lt;/code&gt; directory.&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="c1"&gt;# roles/&amp;lt;role_name&amp;gt;/handlers/main.yml&lt;/span&gt;
&lt;span class="nn"&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 Nginx&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;restarted&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Provide Default and Variable Values&lt;/strong&gt;: Use the &lt;code&gt;defaults&lt;/code&gt; and &lt;code&gt;vars&lt;/code&gt; directories to set default values and other variables required by the role.&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="c1"&gt;# roles/&amp;lt;role_name&amp;gt;/defaults/main.yml&lt;/span&gt;
&lt;span class="nn"&gt;---&lt;/span&gt;
&lt;span class="na"&gt;nginx_version&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;latest&lt;/span&gt;

&lt;span class="c1"&gt;# roles/&amp;lt;role_name&amp;gt;/vars/main.yml&lt;/span&gt;
&lt;span class="nn"&gt;---&lt;/span&gt;
&lt;span class="na"&gt;some_variable&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;value&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Templates and Files&lt;/strong&gt;: Place configuration templates and static files in the &lt;code&gt;templates&lt;/code&gt; and &lt;code&gt;files&lt;/code&gt; directories, respectively.&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight jinja"&gt;&lt;code&gt;# roles/&lt;span class="nt"&gt;&amp;lt;role_name&amp;gt;&lt;/span&gt;/templates/nginx.conf.j2
server {
    listen 80;
    server_name &lt;span class="cp"&gt;{{&lt;/span&gt; &lt;span class="nv"&gt;server_name&lt;/span&gt; &lt;span class="cp"&gt;}}&lt;/span&gt;;
    ...
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Metadata and Dependencies&lt;/strong&gt;: Define any role dependencies in the &lt;code&gt;meta&lt;/code&gt; directory.&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="c1"&gt;# roles/&amp;lt;role_name&amp;gt;/meta/main.yml&lt;/span&gt;
&lt;span class="nn"&gt;---&lt;/span&gt;
&lt;span class="na"&gt;dependencies&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="pi"&gt;{&lt;/span&gt; &lt;span class="nv"&gt;role&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="nv"&gt;another_role&lt;/span&gt; &lt;span class="pi"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Include Roles in Playbooks&lt;/strong&gt;: Finally, include the role in your playbook.&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="c1"&gt;# playbook.yml&lt;/span&gt;
&lt;span class="nn"&gt;---&lt;/span&gt;
&lt;span class="pi"&gt;-&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;role_name&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

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

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

&lt;p&gt;Ansible Roles are a fundamental feature that enhances your automation scripts. By organizing your playbooks into discrete, reusable components, roles simplify complex configurations and make your automation tasks more efficient and manageable. Implementing roles is straightforward, and once set up, they can significantly streamline your IT operations, ensuring idempotency and reducing overhead. Whether you're managing infrastructure, deploying applications, or integrating with CI/CD pipelines, Ansible Roles are an invaluable tool in your automation arsenal.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fj8lncl0ierrrx7xc0lxn.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fj8lncl0ierrrx7xc0lxn.png" alt="Ansible Logo" width="200" height="200"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>devops</category>
      <category>cloud</category>
      <category>automation</category>
      <category>tooling</category>
    </item>
    <item>
      <title>Troubleshooting Apache2 and Nginx Configuration on Ubuntu with Ansible</title>
      <dc:creator>Faruq2991</dc:creator>
      <pubDate>Fri, 21 Jun 2024 14:23:20 +0000</pubDate>
      <link>https://forem.com/faruq2991/troubleshooting-apache2-and-nginx-configuration-on-ubuntu-with-ansible-hd</link>
      <guid>https://forem.com/faruq2991/troubleshooting-apache2-and-nginx-configuration-on-ubuntu-with-ansible-hd</guid>
      <description>&lt;p&gt;In the early hours of today, I found myself deep in the trenches of an Ansible playbook problem while configuring &lt;code&gt;nginx&lt;/code&gt; and &lt;code&gt;apache2&lt;/code&gt; on some remote Ubuntu hosts. This journey was challenging but ultimately rewarding. Here’s a guide based on my experience to help you navigate similar issues.&lt;/p&gt;

&lt;h2&gt;
  
  
  Initial Problem: Ansible and Missing Python Dependencies
&lt;/h2&gt;

&lt;p&gt;When running an Ansible playbook to configure &lt;code&gt;nginx&lt;/code&gt; and &lt;code&gt;apache2&lt;/code&gt;, one of the hosts refused to execute the playbook commands. Despite being able to SSH into the host, the commands wouldn't run. After some research, I discovered that the issue was due to missing Python dependencies, which Ansible relies on to function correctly. So, I installed all dependencies including Ansible again, just to make sure everything is up to date.&lt;/p&gt;

&lt;h3&gt;
  
  
  Solution:
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Install Python Dependencies Ansible&lt;/strong&gt;:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;  &lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;apt update
  &lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;apt &lt;span class="nb"&gt;install &lt;/span&gt;software-properties-common
  &lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;add-apt-repository &lt;span class="nt"&gt;--yes&lt;/span&gt; &lt;span class="nt"&gt;--update&lt;/span&gt; ppa:ansible/ansible
  &lt;span class="nv"&gt;$ &lt;/span&gt;&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;h2&gt;
  
  
  Subsequent Issue: Apache2 Fails to Start
&lt;/h2&gt;

&lt;p&gt;After resolving the initial problem, I encountered a new issue: while Apache2 installed successfully, it failed to start. The error message was:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Job for apache2.service failed because the control process exited with error code. See "systemctl status apache2.service" and "journalctl -xe" for details.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Check Service Status&lt;/strong&gt;:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;   systemctl status apache2.service
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Inspect Logs&lt;/strong&gt;:
&lt;/li&gt;
&lt;/ol&gt;

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

&lt;/div&gt;



&lt;h3&gt;
  
  
  Common Issues and Fixes:
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Missing &lt;code&gt;ServerName&lt;/code&gt; Directive&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Apache2 requires a &lt;code&gt;ServerName&lt;/code&gt; directive to avoid warnings.&lt;/li&gt;
&lt;li&gt;Add &lt;code&gt;ServerName 127.0.0.1&lt;/code&gt; to your Apache2 configuration file.
&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt; &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"ServerName 127.0.0.1"&lt;/span&gt; | &lt;span class="nb"&gt;sudo tee&lt;/span&gt; /etc/apache2/conf-available/servername.conf
 &lt;span class="nb"&gt;sudo &lt;/span&gt;a2enconf servername
 &lt;span class="nb"&gt;sudo &lt;/span&gt;apache2ctl configtest
&lt;/code&gt;&lt;/pre&gt;

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

&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;If the configuration test passes, restart Apache2:&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt; &lt;span class="nb"&gt;sudo &lt;/span&gt;systemctl restart apache2
&lt;/code&gt;&lt;/pre&gt;

&lt;/li&gt;
&lt;/ul&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Port Conflict with Nginx&lt;/strong&gt;:

&lt;ul&gt;
&lt;li&gt;Both &lt;code&gt;nginx&lt;/code&gt; and &lt;code&gt;apache2&lt;/code&gt; were attempting to start on port 80, causing a conflict.&lt;/li&gt;
&lt;li&gt;Ensure they are configured to use different ports or that only one of them is running at a time.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Resolving the Port Conflict:
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Change Apache2 Port&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Edit the Apache2 ports configuration file:
&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt; &lt;span class="nb"&gt;sudo &lt;/span&gt;nano /etc/apache2/ports.conf
&lt;/code&gt;&lt;/pre&gt;

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

&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Change the &lt;code&gt;Listen&lt;/code&gt; directive to a different port, e.g., &lt;code&gt;8080&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight apache"&gt;&lt;code&gt; &lt;span class="nc"&gt;Listen&lt;/span&gt; 8080
&lt;/code&gt;&lt;/pre&gt;

&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Update your virtual host configuration to match the new port.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Restart Services&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Restart Apache2:
&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt; &lt;span class="nb"&gt;sudo &lt;/span&gt;systemctl restart apache2
&lt;/code&gt;&lt;/pre&gt;

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

&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Restart Nginx:&lt;br&gt;
&lt;/p&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;/li&gt;
&lt;/ul&gt;

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

&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Persistence Pays Off&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Troubleshooting can be frustrating and time-consuming, but persistence and determination are key. Even when the solution seems elusive, continue researching and testing.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Attention to Detail&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Small configuration errors can cause significant issues. Always double-check configuration files and ensure all directives are correct.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Comprehensive Logging&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Utilize system logs and status commands to gather detailed information about errors. These logs are invaluable for diagnosing problems.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;System Knowledge&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Understanding how services interact on your system (e.g., port usage) can prevent conflicts and help in resolving issues faster.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;

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

&lt;p&gt;Troubleshooting server configuration issues can be a daunting task, especially when using automation tools like Ansible. However, each challenge is an opportunity to learn and improve your skills. By documenting and sharing these experiences, we can help others navigate similar challenges more efficiently.&lt;/p&gt;

&lt;p&gt;Happy coding!&lt;/p&gt;

</description>
      <category>devops</category>
      <category>learning</category>
      <category>cloud</category>
      <category>automation</category>
    </item>
    <item>
      <title>My Ansible Learning Journey: Exploring Essential Modules</title>
      <dc:creator>Faruq2991</dc:creator>
      <pubDate>Thu, 20 Jun 2024 23:10:20 +0000</pubDate>
      <link>https://forem.com/faruq2991/my-ansible-learning-journey-exploring-essential-modules-2e6c</link>
      <guid>https://forem.com/faruq2991/my-ansible-learning-journey-exploring-essential-modules-2e6c</guid>
      <description>&lt;p&gt;&lt;strong&gt;Introduction to Ansible&lt;/strong&gt;&lt;br&gt;
Ansible is an open-source automation tool that simplifies tasks like configuration management, application deployment, and task automation. It uses a simple, human-readable language called YAML (Yet Another Markup Language) to describe automation jobs, making it accessible for beginners and powerful for experts.&lt;/p&gt;
&lt;h3&gt;
  
  
  Why Use Ansible Modules?
&lt;/h3&gt;

&lt;p&gt;Ansible modules are the building blocks for creating tasks in Ansible. Each module is a standalone script that Ansible runs on your behalf, performing specific tasks like managing files, installing packages, or configuring services. Modules help you automate tasks efficiently and consistently, reducing the risk of manual errors.&lt;/p&gt;
&lt;h3&gt;
  
  
  Important Ansible Modules for Beginners
&lt;/h3&gt;

&lt;p&gt;Here are some essential Ansible modules that every beginner should know:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;ping&lt;/strong&gt;: Checks connectivity with the target hosts.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;shell&lt;/strong&gt;: Executes shell commands on remote hosts.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;file&lt;/strong&gt;: Manages files and directories.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;copy&lt;/strong&gt;: Copies files to remote locations.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;apt&lt;/strong&gt;: Manages packages on Debian-based systems.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;yum&lt;/strong&gt;: Manages packages on Red Hat-based systems.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;service&lt;/strong&gt;: Manages services on remote hosts.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;user&lt;/strong&gt;: Manages user accounts.&lt;/li&gt;
&lt;/ol&gt;
&lt;h3&gt;
  
  
  Using Ansible Modules: Code Examples
&lt;/h3&gt;
&lt;h4&gt;
  
  
  1. &lt;strong&gt;ping&lt;/strong&gt; Module
&lt;/h4&gt;

&lt;p&gt;The &lt;code&gt;ping&lt;/code&gt; module checks for connectivity to your host machines.&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;Check connectivity&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;all&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;Ping all hosts&lt;/span&gt;
      &lt;span class="na"&gt;ansible.builtin.ping&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  2. &lt;strong&gt;shell&lt;/strong&gt; Module
&lt;/h4&gt;

&lt;p&gt;The &lt;code&gt;shell&lt;/code&gt; module allows you to run shell commands on remote hosts.&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;Run a shell command&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;all&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;Print date on remote hosts&lt;/span&gt;
      &lt;span class="na"&gt;ansible.builtin.shell&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;date&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  3. &lt;strong&gt;file&lt;/strong&gt; Module
&lt;/h4&gt;

&lt;p&gt;The &lt;code&gt;file&lt;/code&gt; module manages file and directory properties.&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;Create a directory&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;all&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;Ensure /tmp/mydir exists&lt;/span&gt;
      &lt;span class="na"&gt;ansible.builtin.file&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="na"&gt;path&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;/tmp/mydir&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;directory&lt;/span&gt;
        &lt;span class="na"&gt;mode&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;0755'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  4. &lt;strong&gt;copy&lt;/strong&gt; Module
&lt;/h4&gt;

&lt;p&gt;The &lt;code&gt;copy&lt;/code&gt; module copies files from the local machine to remote hosts.&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;Copy a file&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;all&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;Copy file to remote hosts&lt;/span&gt;
      &lt;span class="na"&gt;ansible.builtin.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;/path/to/local/file&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;/path/to/remote/file&lt;/span&gt;
        &lt;span class="na"&gt;mode&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;0644'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  5. &lt;strong&gt;apt&lt;/strong&gt; Module
&lt;/h4&gt;

&lt;p&gt;The &lt;code&gt;apt&lt;/code&gt; module manages packages on Debian-based systems.&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 a package on Debian/Ubuntu&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;all&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 htop&lt;/span&gt;
      &lt;span class="na"&gt;ansible.builtin.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;htop&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  6. &lt;strong&gt;yum&lt;/strong&gt; Module
&lt;/h4&gt;

&lt;p&gt;The &lt;code&gt;yum&lt;/code&gt; module manages packages on Red Hat-based systems.&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 a package on CentOS/RHEL&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;all&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 htop&lt;/span&gt;
      &lt;span class="na"&gt;ansible.builtin.yum&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;htop&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  7. &lt;strong&gt;service&lt;/strong&gt; Module
&lt;/h4&gt;

&lt;p&gt;The &lt;code&gt;service&lt;/code&gt; module manages services on remote hosts.&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;Start and enable a service&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;all&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;Ensure nginx is running and enabled&lt;/span&gt;
      &lt;span class="na"&gt;ansible.builtin.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;span class="na"&gt;enabled&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;yes&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  8. &lt;strong&gt;user&lt;/strong&gt; Module
&lt;/h4&gt;

&lt;p&gt;The &lt;code&gt;user&lt;/code&gt; module manages user accounts on remote hosts.&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;Create a user account&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;all&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;Ensure user 'john' exists&lt;/span&gt;
      &lt;span class="na"&gt;ansible.builtin.user&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;john&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;groups&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;wheel'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;p&gt;Learning Ansible modules is a fundamental step in mastering automation with Ansible. These essential modules will help me automate repetitive tasks within my workflow, making it more efficient and reliable. As I continue on my Ansible journey, I believe I will discover many more modules that will cater to some specific needs, but starting with the basics gives me a solid foundation.&lt;/p&gt;

&lt;p&gt;I love automating!&lt;br&gt;
I love Ansible!!&lt;/p&gt;

</description>
      <category>devops</category>
      <category>learning</category>
      <category>automation</category>
      <category>tooling</category>
    </item>
  </channel>
</rss>
