<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Ayomide</title>
    <description>The latest articles on DEV Community by Ayomide (@ayocloud247).</description>
    <link>https://dev.to/ayocloud247</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.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F1237181%2F595f805d-ff76-4ee1-a83f-0dc9072de8f8.png</url>
      <title>DEV Community: Ayomide</title>
      <link>https://dev.to/ayocloud247</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/ayocloud247"/>
    <language>en</language>
    <item>
      <title>Building Your First Server "Bouncer": A Beginner's Guide to Anomaly Detection</title>
      <dc:creator>Ayomide</dc:creator>
      <pubDate>Wed, 29 Apr 2026 22:54:53 +0000</pubDate>
      <link>https://dev.to/ayocloud247/building-your-first-server-bouncer-a-beginners-guide-to-anomaly-detection-1ajc</link>
      <guid>https://dev.to/ayocloud247/building-your-first-server-bouncer-a-beginners-guide-to-anomaly-detection-1ajc</guid>
      <description>&lt;p&gt;When I first started in DevSecOps, this felt overwhelming. How do you stop attacks when you are asleep? &lt;/p&gt;

&lt;p&gt;The answer is &lt;strong&gt;Automated Anomaly Detection&lt;/strong&gt;. I recently built a Python-based security engine that watches server traffic, learns what "normal" looks like, and automatically bans malicious bots. &lt;/p&gt;

&lt;p&gt;If you have never worked on security tooling before, don't worry! I am going to break down exactly how this project works, piece by piece, without the dense jargon.&lt;/p&gt;




&lt;h3&gt;
  
  
  What This Project Does (And Why It Matters)
&lt;/h3&gt;

&lt;p&gt;Imagine your web server is an exclusive nightclub, and the Nginx log file is the guest list. Every time someone visits your site, Nginx writes their IP address in the log. &lt;/p&gt;

&lt;p&gt;This project acts as an invisible bouncer standing next to the list. It reads the logs in real-time. If someone is walking in and out a normal amount of times, the bouncer ignores them. But if one person tries to enter the club 500 times in ten seconds, the bouncer grabs them, throws them out, and locks the door.&lt;/p&gt;

&lt;p&gt;This matters because manual security doesn't scale. You cannot sit at your computer 24/7 watching logs. By automating this, your server protects itself.&lt;/p&gt;




&lt;h3&gt;
  
  
  1. The Sliding Window: The Short-Term Memory
&lt;/h3&gt;

&lt;p&gt;To know if someone is attacking us &lt;em&gt;right now&lt;/em&gt;, the engine needs short-term memory. We use a concept called a &lt;strong&gt;Sliding Window&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Imagine a 60-second timer. Every time an IP address makes a request, we record the exact timestamp. As time ticks forward, we continuously "drop" any timestamps that are older than 60 seconds.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;[  Time: 10:00:00  ] -&amp;gt; Request comes in. Add to window.
[  Time: 10:00:30  ] -&amp;gt; More requests come in.
[  Time: 10:01:05  ] -&amp;gt; The request from 10:00:00 is now too old. We drop it!

This ensures we are always looking at the current rate of traffic. In Python, we do this using a deque (a double-ended queue), which makes it incredibly fast to add new requests to the right side and pop old requests off the left side.

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

&lt;/div&gt;



&lt;p&gt;from collections import deque&lt;br&gt;
import time&lt;/p&gt;

&lt;p&gt;class RateTracker:&lt;br&gt;
    def &lt;strong&gt;init&lt;/strong&gt;(self):&lt;br&gt;
        # Keeps memory of timestamps&lt;br&gt;
        self.requests = deque() &lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;def add_request(self):
    self.requests.append(time.time())

def get_rate(self):
    current_time = time.time()
    # Remove anything older than 60 seconds
    while self.requests and self.requests[0] &amp;lt; current_time - 60:
        self.requests.popleft()

    # The remaining length is our current Requests-Per-Second!
    return len(self.requests) / 60.0
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;2. The Baseline: How the Engine "Learns"
A static rule like "Ban anyone who makes 50 requests" is actually a terrible idea. What if your site goes viral? Suddenly, your engine will ban all your real customers!

Instead, the engine needs to learn what "normal" is. We call this the Baseline.

Every minute, our engine takes a snapshot of the global traffic rate and saves it. Over time, it calculates two things:

The Mean (Average): The normal amount of traffic we expect to see.

The Standard Deviation: How much traffic naturally "wiggles" up and down on a normal day.

If normal traffic is 10 requests per second (the Mean), and it usually fluctuates by about 2 requests (the Standard Deviation), the engine learns that anything between 8 and 12 is perfectly safe.

3. The Detection Logic: The Judge
Now we have our short-term memory (Sliding Window) and our long-term learning (Baseline). How do we make a decision to ban someone?

We use a mathematical concept called a Z-Score. Don't let the math term scare you! A Z-Score simply answers the question: "How weird is this right now compared to what we normally see?"

Here is the logic:

We look at a specific IP address's current request rate.

We subtract the "normal" Baseline Mean.

We divide by the Standard Deviation.

If the Z-Score is 1, it means traffic is slightly elevated, but fine. If the Z-Score hits 5, it means that IP is behaving so aggressively that there is practically a 0% chance it is a normal user.

When the logic sees a high Z-Score, it pulls the alarm.

4. iptables: The Muscle
Once the engine decides an IP is an attacker, it needs to physically block them from the server. It does this using iptables.

iptables is the built-in firewall for Linux systems. Think of it as a brick wall surrounding your server. When our Python script catches a bad IP, it executes this exact terminal command:

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

&lt;/div&gt;



&lt;p&gt;sudo iptables -A INPUT -s 192.168.1.100 -j DROP&lt;/p&gt;



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

Let's break down what this command actually means:

sudo: Run this with absolute administrator power.

iptables: Wake up the firewall program.

-A INPUT: Append (add) a new rule to the INPUT door (incoming traffic).

-s 192.168.1.100: Look for this specific source IP address.

-j DROP: Jump to the DROP action. Do not send an error message, do not say hello, just silently drop their connection into a black hole.

Once this command runs, that attacker can no longer touch our Nginx server, view our website, or waste our CPU resources. They are completely locked out!

Wrapping Up
By combining Nginx logs, a sliding window, statistical math, and Linux firewalls, we built an engine that thinks, learns, and defends entirely on its own. DevSecOps isn't just about reading logs—it is about building automated systems that do the hard work for you.

Have you ever built a security tool or worked with iptables? Let me know in the comments below!
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

</description>
    </item>
    <item>
      <title>HNG STAGE 1 TASK: Linux User Creation Bash Script Task</title>
      <dc:creator>Ayomide</dc:creator>
      <pubDate>Sat, 06 Jul 2024 11:19:24 +0000</pubDate>
      <link>https://dev.to/ayocloud247/hng-stage-1-task-linux-user-creation-bash-script-task-61a</link>
      <guid>https://dev.to/ayocloud247/hng-stage-1-task-linux-user-creation-bash-script-task-61a</guid>
      <description>&lt;p&gt;&lt;strong&gt;Introduction&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Managing user accounts and groups efficiently is a critical task for any SysOps engineer. It is essential to automate this process to ensure consistency, security, and ease of management. In this article, we will explore a bash script that automates the creation of users and groups based on a provided text file. This script sets up home directories, generates random passwords, and logs all actions performed.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Script Overview&lt;/strong&gt;&lt;br&gt;
Our bash script, create_users.sh, reads a text file where each line is formatted as username;groups, creates users, assigns them to groups, and logs the actions. The script also handles error scenarios for existing users and sets appropriate permissions for home directories and password files.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Initialization and Variable Declaration&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;

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

log_message_file="/var/log/user_management.log"
passwords_file="/var/secure/user_passwords.txt"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I defined the log and password files, ensuring they exist.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Fucntion to Verify User and Group&lt;/em&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 if a user exists
user_exists() {
    local username=$1
    if getent passwd "$username" &amp;gt; /dev/null 2&amp;gt;&amp;amp;1; then
        return 0  # User exists
    else
        return 1  # User does not exist
    fi
}

# Check if a group exists
group_exists() {
    local group_name=$1
    if getent group "$group_name" &amp;gt; /dev/null 2&amp;gt;&amp;amp;1; then
        return 0  # Group exists
    else
        return 1  # Group does not exist
    fi
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I declare functions to check if the users and groups exists. They will be called in later&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Function for Password Generation and Logging&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# Generate a random password
generate_password() {
    openssl rand -base64 12
}

# Log actions to /var/log/user_management.log
log() {
    local MESSAGE="$1"
    echo "$(date +'%Y-%m-%d %H:%M:%S') - $MESSAGE" | sudo tee -a $log_message_file &amp;gt; /dev/null
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The first function generates a random password and the second function sends a log of all actions to the specified file&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# Assign the file name from the command line argument
user_group=$1

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

&lt;/div&gt;



&lt;p&gt;Here, a variable is assigned to the command line argument as a stand in for the filename&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Log and Password File Creation&lt;/em&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 if the log file exist

if [ ! -f "$log_messsage_file" ]; then
    # Create the log file
    sudo touch "$log_message_file"
    log "$log_message_file has been created."
else
    log "$log_message_file exists already"
fi

# Check and create the passwords_file

if [ ! -f "$passwords_file" ]; then
    # Create the file and set permissions
    sudo mkdir -p /var/secure/
    sudo touch "$passwords_file"
    log "$passwords_file has been created."
    # Set ownership permissions for passwords_file
    sudo chmod 600 "$passwords_file"
    log "Updated passwords_file permission to file owner"
else
    log "$passwords_file exists already"
fi
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here, the log file and password file are checked for any sign of existence and created if none is found&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Looping Through Users and Groups&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;



&lt;p&gt;Using IFS, I separate the value in our text file using the ";" as the delimiter and extract the username and groups&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Checking for Users and Password Creation&lt;/em&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 if the user exists
    if user_exists "$username"; then
        log "$username exists already"
        continue
    else
        # Generate a random password for the user
        password=$(generate_password)

        # Create the user with home directory and set password
        sudo useradd -m -s /bin/bash "$username"
        echo "$username:$password" | sudo chpasswd

        log "Successfully Created User: $username"
    fi

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

&lt;/div&gt;



&lt;p&gt;This code checks if the user already exists; otherwise, it creates the user and gives it a randomized password.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Checking for User Group&lt;/em&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 that the user has its own group
    if ! group_exists "$username"; then
        sudo groupadd "$username"
        log "Successfully created group: $username"
        sudo usermod -aG "$username" "$username"
        log "User: $username added to Group: $username"
    else
        log "User: $username added to Group: $username"
    fi
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It checks if the user created has its own group and adds it to its group if it does not.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Extracting The Groups&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;    # Extract the groups and remove any spaces
    groups=$(echo "$groups" | tr -d ' ')

    # Split the groups by comma
    IFS=',' read -r -a group_count &amp;lt;&amp;lt;&amp;lt; "$groups"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;From the text file, we extract the groups, spilt the values by the comma "," delimiter and append the values into the _group_count _array.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Creation of Groups and Attachment of Users&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;    # Create the groups and add the user to each group
    for group in "${group_count[@]}"; do
        # Check if the group already exists
        if ! group_exists "$group"; then
            # Create the group if it does not exist
            sudo groupadd "$group"
            log "Successfully created Group: $group"
        else
            log "Group: $group already exists"
        fi
        # Add the user to the group
        sudo usermod -aG "$group" "$username"
    done
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;By looping through the array, we check if the group exists, create it if it does not and add the users to their respective groups&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Setting Appropriate Permission&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;    # Set permissions for home directory
    sudo chmod 700 "/home/$username"
    sudo chown "$username:$username" "/home/$username"
    log "Updated permissions for home directory: '/home/$username' of User: $username to '$username:$username'"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here, we set the permission and ownership for the home directory of the created user(s)&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Storing Username and Password in Password file&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;    # Store username and password in secure file
    echo "$username,$password" | sudo tee -a "$passwords_file" &amp;gt; /dev/null
    log "Stored username and password in $passwords_file"
done &amp;lt; "$user_group"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here, we store the user and password in the specified file&lt;/p&gt;

&lt;p&gt;To learn more about the HNG internship and what they do, check out &lt;a href="https://hng.tech/internship" rel="noopener noreferrer"&gt;HNG Internship&lt;/a&gt;. You can also visit &lt;a href="https://hng.tech/hire" rel="noopener noreferrer"&gt;HNG Hire&lt;/a&gt; to scout the best talents.&lt;/p&gt;

&lt;p&gt;Thank You.&lt;/p&gt;

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