<?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: Lanky-23</title>
    <description>The latest articles on DEV Community by Lanky-23 (@lanky23).</description>
    <link>https://dev.to/lanky23</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%2F1720043%2F43eafec5-57e3-4984-a6c7-aa01533ddf53.png</url>
      <title>DEV Community: Lanky-23</title>
      <link>https://dev.to/lanky23</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/lanky23"/>
    <language>en</language>
    <item>
      <title>Documentation for Deploying "HNG Boilerplate", A Next.js Application using GitHub Actions</title>
      <dc:creator>Lanky-23</dc:creator>
      <pubDate>Sat, 24 Aug 2024 21:29:18 +0000</pubDate>
      <link>https://dev.to/lanky23/documentation-for-deploying-hng-boilerplate-a-nextjs-application-using-github-actions-4g5c</link>
      <guid>https://dev.to/lanky23/documentation-for-deploying-hng-boilerplate-a-nextjs-application-using-github-actions-4g5c</guid>
      <description>&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;This guide provides a step-by-step explanation of deploying the "HNG Boilerplate" Next.js application using a CI/CD pipeline powered by GitHub Actions. The deployment process includes building the application, uploading artifacts, and deploying them on a server with Nginx configured to route traffic to the application.&lt;/p&gt;

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

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

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;A GitHub repository with your "HNG Boilerplate" Next.js application.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;A server (e.g., Ubuntu) with SSH access.&lt;br&gt;
Nginx installed on your server.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;A domain name pointing to your server's IP address.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Dependencies
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Node.js &amp;amp; pnpm: Required for building the "HNG Boilerplate."&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Nginx: Used as a reverse proxy to direct traffic from your domain to the "HNG Boilerplate."&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;PM2: Manages and keeps your Node.js application running.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  GitHub Actions Workflows
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Build and Upload Workflow
&lt;/h3&gt;

&lt;p&gt;This workflow is responsible for building the "HNG Boilerplate" application and uploading the production artifacts.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;name: Build and Upload

on:
  push:
    branches:
      - dev

jobs:
  build:
    runs-on: ubuntu-latest
    if: github.event.repository.fork == false

    steps:
    - uses: actions/checkout@v4

    - name: Set up Node.js
      uses: actions/setup-node@v3
      with:
        node-version: "20"

    - name: Cache pnpm modules
      uses: actions/cache@v3
      with:
        path: ~/.pnpm-store
        key: ${{ runner.os }}-pnpm-${{ hashFiles('**/pnpm-lock.yaml') }}
        restore-keys: |
          ${{ runner.os }}-pnpm-

    - name: Install pnpm
      uses: pnpm/action-setup@v4
      with:
        version: 9

    - name: Install dependencies
      run: pnpm install

    - name: Build Next.js application
      run: pnpm build

    - name: Archive production artifacts
      run: tar -czf boilerplate.tar.gz .next public

    - name: Upload production artifacts
      uses: actions/upload-artifact@v3
      with:
        name: boilerplate-build
        path: boilerplate.tar.gz

    - name: Delete zip file
      run: rm -f boilerplate.tar.gz
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Node.js Setup: Ensures the correct Node.js version is used.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Caching: Speeds up workflow by caching pnpm modules.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Build Process: Builds the "HNG Boilerplate" and archives the production files.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Artifact Upload: Uploads the build as an artifact for the deployment process.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Deployment Workflow
&lt;/h3&gt;

&lt;p&gt;This workflow is triggered upon the successful completion of the "Build and Upload" workflow and handles the deployment of the "HNG Boilerplate."&lt;br&gt;
&lt;/p&gt;

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

on:
  workflow_run:
    workflows: ["Build and Upload"]
    types:
      - completed

jobs:   
  deploy:
    if: ${{ github.event.workflow_run.conclusion == 'success' }}
    runs-on: ubuntu-latest

    environment:
      name: "panther-expressjs"
      url: ${{ vars.URL }}

    steps:
      - name: Download build artifact
        uses: actions/download-artifact@v4
        with:
          github-token: ${{ secrets.GITHUB_TOKEN }}
          run-id: ${{ github.event.workflow_run.id }}
          name: boilerplate-build
          path: .

      - name: Decode ENV secret
        run: |
         echo "${{ secrets.ENV }}" &amp;gt; encoded_env.txt
         base64 -d encoded_env.txt &amp;gt; .env.expressjs

      - name: Copy Artifacts to server
        uses: appleboy/scp-action@v0.1.7
        with:
          host: ${{ secrets.HOST }}
          username: ${{ secrets.USERNAME }}
          password: ${{ secrets.PASSWORD }}
          source: ".env.expressjs,boilerplate.tar.gz"
          target: "/tmp/expressjs"

      - name: Deploy on server
        uses: appleboy/ssh-action@master
        with:
          host: ${{ secrets.HOST }}
          username: ${{ secrets.USERNAME }}
          password: ${{ secrets.PASSWORD }}
          script: |
             sudo npm install -g pm2
            mkdir -p hng_boilerplate_nextjs
            cd hng_boilerplate_nextjs
            tar -xzf /tmp/expressjs/boilerplate.tar.gz
            mv /tmp/expressjs/.env.expressjs .env
            rm -f /tmp/expressjs/boilerplate.tar.gz
            cp -r .next/standalone/* .
            pm2 restart nextjs_boilerplate --update-env
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Artifact Download: Retrieves the build artifacts from the "Build and Upload" workflow.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Environment Setup: Decodes and applies environment variables for the deployment.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Server Deployment: Transfers the necessary files to the server and restarts the application using PM2.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Nginx Configuration
&lt;/h2&gt;

&lt;p&gt;To route your domain to the "HNG Boilerplate" application running on the &lt;br&gt;
server, configure Nginx as follows:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Install Nginx on your server:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;sudo apt update
sudo apt install nginx

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

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Configure Nginx by editing the default site configuration or creating a new one
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;server {
    listen 80;
    server_name yourdomain.com www.yourdomain.com;

    location / {
        proxy_pass http://localhost:port;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection 'upgrade';
        proxy_set_header Host $host;
        proxy_cache_bypass $http_upgrade;
    }

    error_page 404 /404.html;
    location = /404.html {
        internal;
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Enable the configuration and restart Nginx
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;sudo ln -s /etc/nginx/path to 'URL' /etc/nginx/sites-enabled/
sudo nginx -t
sudo systemctl restart nginx
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Set up SSL with Certbot:
Use Certbot to automatically obtain and install an SSL certificate for your domain:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;sudo certbot --nginx -d 'URL'
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;p&gt;This guide provides a comprehensive overview of deploying the "HNG Boilerplate" using GitHub Actions and Nginx. The combination of automated CI/CD pipelines and a robust web server setup ensures a smooth and efficient deployment process.&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Automating the Management of Users and Groups Using a Bash Script in Linux.</title>
      <dc:creator>Lanky-23</dc:creator>
      <pubDate>Wed, 03 Jul 2024 20:33:59 +0000</pubDate>
      <link>https://dev.to/lanky23/automating-the-management-of-users-and-groups-using-a-bash-script-in-linux-12bh</link>
      <guid>https://dev.to/lanky23/automating-the-management-of-users-and-groups-using-a-bash-script-in-linux-12bh</guid>
      <description>&lt;p&gt;As a SysOps engineer in a company, there is the occasional necessity to manage the creation of users and groups, maximum efficiency can be attained by automating this process. To address this, I have developed a Bash script to create users and groups, set up home directories with appropriate permissions and ownership, generate random passwords, and log all actions.&lt;br&gt;
This article details the functionality and structure of the script, ensuring error handling for scenarios such as existing users, and providing comprehensive documentation and comments within the script.&lt;/p&gt;
&lt;h2&gt;
  
  
  Script Overview
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;The creation of Bash script that reads a text file containing users and groups.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Creation of users and groups as specified.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Setting up home directories with appropriate permissions, generating random passwords, and  logging all actions to file.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Securely storing generated passwords.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;
  
  
  Let's dive into the script
&lt;/h2&gt;

&lt;p&gt;Every Bash script begins with the shebang line.&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
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This indicates that the script should be run using the Bash shell.&lt;/p&gt;

&lt;h2&gt;
  
  
  Directory and File Setup
&lt;/h2&gt;



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

chmod 600 /var/secure/user_passwords.txt
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This ensures that the directories &lt;code&gt;/var/log&lt;/code&gt; and &lt;code&gt;/var/secure&lt;/code&gt; exist. The &lt;code&gt;-p&lt;/code&gt; flag allows the command to create parent directories as needed without raising an error if the directory already exists, and creates the log file user_management.log in &lt;code&gt;/var/log&lt;/code&gt; and the password file user_passwords.txt in &lt;code&gt;/var/secure&lt;/code&gt;. &lt;br&gt;
Having created the &lt;code&gt;/var/secure&lt;/code&gt; directory. Using &lt;code&gt;chmod 600&lt;/code&gt; I set the permissions for user_passwords.txt to be readable and writable only by the file's owner.&lt;/p&gt;
&lt;h2&gt;
  
  
  Action Logging Function
&lt;/h2&gt;

&lt;p&gt;This defines a function &lt;code&gt;log_action&lt;/code&gt; that appends a timestamped log entry to the user_management.log file.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;log_action() {
    echo "$(date) - $1" &amp;gt;&amp;gt; "/var/log/user_management.log"
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  User Creation Function
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;I declared the &lt;code&gt;create_user()&lt;/code&gt; function, defining three variables: user (username), groups (additional groups), and password (which will be generated).
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;create_user() {
   user, groups, and password
    local user="$1"
    local groups="$2"
    local password
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I proceeded to check if the user already exists using the 'id' command. If the user exists, log "$user already exists" and exit the function.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt; if id "$user" &amp;amp;&amp;gt;/dev/null; then
        log_action "User $user already exists."
        return
    fi
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Next, I created a personal group for the user with the same name as the username using &lt;code&gt;groupadd "$user"&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

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

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

&lt;/div&gt;



&lt;h2&gt;
  
  
  Group Handling and Creation
&lt;/h2&gt;

&lt;p&gt;The script takes the list of additional groups and splits them into separate items in a &lt;code&gt;group_array&lt;/code&gt;. Logs a message that lists all the groups the user will be added to. The script then goes through each group in the array, removes any extra spaces from the group name, and checks if the group already exists. If the group doesn't exist, it creates the group.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt; IFS=' ' read -ra group_array &amp;lt;&amp;lt;&amp;lt; "$groups"

    # Log the group array
    log_action "User $user will be added to groups: ${group_array[*]}"
    for group in "${group_array[@]}"; do
        group=$(echo "$group" | xargs)  # Trim whitespace
        if ! getent group "$group" &amp;amp;&amp;gt;/dev/null; then
            groupadd "$group"
            log_action "Group $group created."
        fi
    done
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I created the user with a home directory &lt;code&gt;(-m)&lt;/code&gt;, a default shell &lt;code&gt;(-s /bin/bash)&lt;/code&gt;, and set the primary group to the personal group &lt;code&gt;(-g "$user")&lt;/code&gt;. Logging the success or failure of the user creation.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt; useradd -m -s /bin/bash -g "$user" "$user"
    if [ $? -eq 0 ]; then
        log_action "User $user created with primary group: $user"
    else
        log_action "Failed to create user $user."
        return
    fi
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Followed by, adding the user to the additional groups using usermod &lt;code&gt;-aG&lt;/code&gt; and logging the action. This splits the additional groups into an array, logs them, trims whitespace, checks if each group exists, and creates any missing groups.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;for group in "${group_array[@]}"; do
        usermod -aG "$group" "$user"
    done
    log_action "User $user added to groups: ${group_array[*]}"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Random Password Generation &amp;amp; Granting Home Directory Permissions&lt;/strong&gt;&lt;br&gt;
I generated a 12-character random password using &lt;code&gt;/dev/urandom&lt;/code&gt;, formatted it, and set it for the user using &lt;code&gt;chpasswd&lt;/code&gt;. Appended the username and password to &lt;code&gt;user_passwords.txt&lt;/code&gt; and stored them in the secure file. Setting the permissions for the user's home directory to be accessible only by the user changing ownership to the user.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt; password=$(&amp;lt;/dev/urandom tr -dc A-Za-z0-9 | head -c 12)
    echo "$user:$password" | chpasswd

    echo "$user,$password" &amp;gt;&amp;gt; "/var/secure/user_passwords.txt"

chmod 700 "/home/$user"
    chown "$user:$user" "/home/$user"

  log_action "Password for user $user set and stored securely."
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Main Script Execution
&lt;/h2&gt;

&lt;p&gt;This begins by checking if exactly one argument &lt;code&gt;&amp;lt;user_list_file&amp;gt;&lt;/code&gt; is provided. If not, it prints usage instructions and exits. Then it checks if the provided 'User list file' exists. If not, it prints an error message and exits. For each line, it reads the username and groups, trims whitespace, replaces commas with spaces, and calls the &lt;code&gt;create_user()&lt;/code&gt; function with the parsed values. Finally, it prints a message indicating that user creation is complete and where to find more information.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;if [ $# -ne 1 ]; then
    echo "Usage: $0 &amp;lt;user_list_file&amp;gt;"
    exit 1
fi
filename="$1"

if [ ! -f "$filename" ]; then
    echo "Users list file $filename not found."
    exit 1
fi

while IFS=';' read -r user groups; do
    user=$(echo "$user" | xargs)
    groups=$(echo "$groups" | xargs | tr -d ' ')


    groups=$(echo "$groups" | tr ',' ' ')
    create_user "$user" "$groups"
done &amp;lt; "$filename"
echo "User created. Type cat /var/log/user_management.log for more information."
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is the combined script.⬇️&lt;br&gt;
&lt;/p&gt;

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

# Create directory for user logs and passwords
mkdir -p /var/log /var/secure

# Create logs file and passwords file
touch /var/log/user_management.log
touch /var/secure/user_passwords.txt

# Grant read and write permissions for file owner only
chmod 600 /var/secure/user_passwords.txt

# Action Logging function
log_action() {
    echo "$(date) - $1" &amp;gt;&amp;gt; "/var/log/user_management.log"
}


create_user() {
    # Define three variables passed to the function: user, groups, and password
    local user="$1"
    local groups="$2"
    local password

    # Check if user already exists
    if id "$user" &amp;amp;&amp;gt;/dev/null; then
        log_action "User $user already exists."
        return
    fi

    # Create personal group for the user
    groupadd "$user"

    # Create additional groups if they do not exist
    IFS=' ' read -ra group_array &amp;lt;&amp;lt;&amp;lt; "$groups"

    # Log the group array
    log_action "User $user will be added to groups: ${group_array[*]}"
    for group in "${group_array[@]}"; do
        group=$(echo "$group" | xargs)  # Trim whitespace
     if ! getent group "$group" &amp;amp;&amp;gt;/dev/null; then
            groupadd "$group"
            log_action "Group $group created."
        fi
    done

    # Create user with home directory and shell, primary group set to the personal group
    useradd -m -s /bin/bash -g "$user" "$user"
    if [ $? -eq 0 ]; then
        log_action "User $user created with primary group: $user"
    else
        log_action "Failed to create user $user."
        return
    fi

    # Add the user to additional groups
    for group in "${group_array[@]}"; do
        usermod -aG "$group" "$user"
    done
    log_action "User $user added to groups: ${group_array[*]}"

    # Generate password and store it securely in a file
    password=$(&amp;lt;/dev/urandom tr -dc A-Za-z0-9 | head -c 12)
    echo "$user:$password" | chpasswd

    # Store user and password securely in a file
    echo "$user,$password" &amp;gt;&amp;gt; "/var/secure/user_passwords.txt"

    # Set permissions and ownership for user home directory
    chmod 700 "/home/$user"
    chown "$user:$user" "/home/$user"

    log_action "Password for user $user set and stored securely."
}

# Check if user list file is provided
if [ $# -ne 1 ]; then
    echo "Usage: $0 &amp;lt;user_list_file&amp;gt;"
    exit 1
fi

filename="$1"

if [ ! -f "$filename" ]; then
    echo "Users list file $filename not found."
    exit 1
fi

# Read user list file and create users
while IFS=';' read -r user groups; do
    user=$(echo "$user" | xargs)
    groups=$(echo "$groups" | xargs | tr -d ' ')

    # Replace commas with spaces for usermod group format
    groups=$(echo "$groups" | tr ',' ' ')
    create_user "$user" "$groups"
done &amp;lt; "$filename"

echo "User created. Type cat /var/log/user_management.log for more information."


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

&lt;/div&gt;



&lt;h2&gt;
  
  
  Testing The Script
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;To use this script, provide a user list file as an argument. Each line in the file should contain a username and a comma-separated list of groups (optional), separated by a semicolon. For example:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;light; sudo,dev,www-data
idimma; sudo
mayowa; dev,www-data
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;To run the script, use this command.
&lt;code&gt;./script_name.sh user_list_file.txt&lt;/code&gt;.
For a non-root user, use &lt;code&gt;sudo ./create_users.sh user_list_file.txt&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

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

&lt;p&gt;The Bash script automates user management by creating users, managing groups, generating secure passwords, and logging actions. It ensures the secure handling of passwords and provides detailed logs for auditing purposes. This automation is critical for efficiently onboarding new users and maintaining system security and organization.&lt;/p&gt;

&lt;p&gt;To rapidly upskill and advance your tech career, visit &lt;a href="https://hng.tech/internship"&gt;https://hng.tech/internship&lt;/a&gt; or &lt;a href="https://hng.tech/premium"&gt;https://hng.tech/premium&lt;/a&gt; for more information.&lt;/p&gt;

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