<?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: damilola lawal</title>
    <description>The latest articles on DEV Community by damilola lawal (@damilola_lawal_b415434987).</description>
    <link>https://dev.to/damilola_lawal_b415434987</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%2F1723484%2F65c7f5ee-d700-4dfd-bc83-d88056c0041f.png</url>
      <title>DEV Community: damilola lawal</title>
      <link>https://dev.to/damilola_lawal_b415434987</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/damilola_lawal_b415434987"/>
    <language>en</language>
    <item>
      <title>A Multi-Tier web Application Stack using; Nginx, Tomcat, Memcached, RabbitMQ on AWS EC2 instance</title>
      <dc:creator>damilola lawal</dc:creator>
      <pubDate>Mon, 15 Jul 2024 15:02:38 +0000</pubDate>
      <link>https://dev.to/damilola_lawal_b415434987/a-multi-tier-web-application-stack-using-nginx-tomcat-memcached-rabbitmq-on-aws-ec2-instance-16ne</link>
      <guid>https://dev.to/damilola_lawal_b415434987/a-multi-tier-web-application-stack-using-nginx-tomcat-memcached-rabbitmq-on-aws-ec2-instance-16ne</guid>
      <description>&lt;p&gt;Welcome, this project will show how to create a simple multi-tier web application application hosted ec2-instance.&lt;/p&gt;

&lt;p&gt;These stack consist of the web layer, application layer and database layer.&lt;br&gt;
Each of these services have its functionality which include;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Nginx:&lt;/strong&gt; Nginx is a high-performance web server and reverse proxy server that efficiently handles HTTP and other web traffic, known for its stability, rich feature set, and low resource consumption.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Tomcat:&lt;/strong&gt;Apache Tomcat is an open-source Java Servlet container. It is a web server and servlet container that serves as a platform for running Java applications.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;MySQL:&lt;/strong&gt; MySQL is a widely-used open-source relational database management system (RDBMS) that allows for the efficient storage, retrieval, and management of data using SQL (Structured Query Language).&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Memcached&lt;/strong&gt;: Mem-cached is a distributed memory caching system designed to speed up dynamic web applications by reducing database load through caching data and objects in RAM.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;RabbitMQ&lt;/strong&gt;: RabbitMQ is a robust, open-source message broker that facilitates the efficient handling of message queuing for distributed systems and microservices, supporting multiple messaging protocols.&lt;/p&gt;

&lt;p&gt;In web development, &lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;STACKS are collection of services working together to create an experience&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Example MERN, LAMP etc.&lt;/p&gt;

&lt;p&gt;The image below shows the workflow of these project.&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%2Flrngojkwth2f37wsx960.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%2Flrngojkwth2f37wsx960.png" alt="web-stack flow" width="686" height="519"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;User enters the URL of the website (ip-address will be used for this project).&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The request goes to Nginx (act as a load balancer which route request to the Apache Tomcat service- a JAVA web application service).&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The web application is hosted on the tomcat server.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The user information will be logged into the MYSQL database.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;RabbitMQ serves as a broker/queuing agent, enabling seamless communication and message queuing between distributed systems&lt;a href="https://www.cloudamqp.com/blog/part1-rabbitmq-for-beginners-what-is-rabbitmq.html" rel="noopener noreferrer"&gt;Read more&lt;/a&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Memcached service is a database caching agent connected to MySQL and previously accessed information from the database is cached to it reducing database hit and increase performance.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;PREREQUISITE&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Two EC2 instance ( one centos and one ubuntu).&lt;/li&gt;
&lt;li&gt;Gitbash or an IDE.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Create two medium EC2 instance &lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;The centos which will host the Tomcat service, memcache, Mysql and RabbitMQ.&lt;/li&gt;
&lt;li&gt;The ubuntu will be hosting Nginx.&lt;/li&gt;
&lt;/ol&gt;

&lt;ul&gt;
&lt;li&gt;MySQL (Database SVC)&lt;/li&gt;
&lt;li&gt;Memcache (DB Caching SVC)&lt;/li&gt;
&lt;li&gt;RabbitMQ (Broker/Queue SVC)&lt;/li&gt;
&lt;li&gt;Tomcat (Application SVC)&lt;/li&gt;
&lt;li&gt;Nginx (Web SVC)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;We are going to start the configuration from the database to the web layer as its custom to do so.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Setting up MYSQL service&lt;/strong&gt;:&lt;br&gt;
SSH into the Centos EC2 instance &amp;amp; update OS&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;sudo yum update -y
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Set Repository
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;sudo yum install epel-release -y
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Install MariaDB package
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;yum install git mariadb-server -y
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;start MariaDB service and enable to start automatically at boot time.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt; systemctl start mariadb
 systemctl enable mariadb
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Run the **mysql secure installation **script, to enable us secure our database.&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;



&lt;p&gt;Also, I will be using &lt;strong&gt;admin123&lt;/strong&gt; as root password but you can use any password but ensure its strong ( containing alphabet, numeric and characters).&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%2Fcpowhv5uarocy03qtv0x.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%2Fcpowhv5uarocy03qtv0x.png" alt="mysql secure installation" width="555" height="698"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Next, set the database name, create user and grant all remote privilege.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt; mysql -u root -padmin123
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;where user is root and password is admin123&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;mysql&amp;gt; create database accounts;
mysql&amp;gt; grant all privileges on accounts.* TO 'admin'@'%' identified by 'admin123';
mysql&amp;gt; FLUSH PRIVILEGES;
mysql&amp;gt; exit;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In the above code, we grant all privilege ( SELECT, DELETE, INSERT, UPDATE e.t.c ) on database name "accounts" to a user "admin" who can connect from any host ( % ).&lt;/p&gt;

&lt;p&gt;Next, we will clone the Repo that has the source code for our application and initialize database.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;git clone -b main https://github.com/lasdapharm/vprofile-project.git
cd vprofile-project
mysql -u root -padmin123 accounts &amp;lt; src/main/resources/db_backup.sql
mysql -u root -padmin123 accounts

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

&lt;/div&gt;



&lt;p&gt;db_backup.sql script create all necessary schema and table on the database.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;mysql&amp;gt; show tables;
mysql&amp;gt; exit;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&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%2Fm17qiolw9fdpunygzye9.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%2Fm17qiolw9fdpunygzye9.png" alt="Image description" width="556" height="322"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Restart mariadb,&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;systemctl restart mariadb
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Check the mariadb status&lt;br&gt;
&lt;/p&gt;

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

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

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;SET UP MEMCACHE SERVICE&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Install, start &amp;amp; enable memcache&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;sudo dnf install epel-release -y
sudo dnf install memcached -y
sudo systemctl start memcached
sudo systemctl enable memcached
sudo systemctl status memcached
sudo systemctl restart memcached
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;SET UP RABBITMQ&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;update OS to latest patches.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt; yum update -y
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Install dependencies,&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;sudo yum install wget -y
cd /tmp/
dnf -y install centos-release-rabbitmq-38
dnf --enablerepo=centos-rabbitmq-38 -y install rabbitmq-server
systemctl enable --now rabbitmq-server

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

&lt;/div&gt;



&lt;p&gt;Setup access to user "test" and make it "admin"&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;sudo sh -c 'echo "[{rabbit, [{loopback_users, []}]}]." &amp;gt;  /etc/rabbitmq/rabbitmq.config'
sudo rabbitmqctl add_user test test
sudo rabbitmqctl set_user_tags test administrator
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;em&gt;sh -c '...'&lt;/em&gt;: Invokes the shell to execute the command within the single quotes.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;[{rabbit, [{loopback_users, []}]}]&lt;/em&gt;. is the content being written to the RabbitMQ configuration file. This configuration tells RabbitMQ not to restrict the guest user to only loopback (localhost) connections.&lt;/p&gt;

&lt;p&gt;By default, RabbitMQ restricts the guest user to only connect from localhost (loopback). &lt;br&gt;
Setting loopback_users to an empty list ([]) removes this restriction, allowing the guest user to connect from any IP address.&lt;/p&gt;

&lt;p&gt;Restart RabbitMQ&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;sudo systemctl restart rabbitmq-server
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;*&lt;em&gt;SET UP TOMCAT SERVICE&lt;br&gt;
*&lt;/em&gt;&lt;br&gt;
When we install other services, we use the package managers (yum and dnf) and this way, we automatically get the systemctl command to manage the service ( start, stop, enable service ) and place the configuration, binaries e.t.c in the rigt directory but for tomcat we are going download the package and configure the systemctl ourselves.&lt;/p&gt;

&lt;p&gt;Tomcat service need JDK (openjdk11 : to develop our application) as dependencies so we going install that as well.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;dnf -y install java-11-openjdk java-11-openjdk-devel
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Install maven ( to build our application from source code) and also install git&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt; dnf install git maven wget -y
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Change directory to /tmp&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;



&lt;p&gt;Download and install tomcat package&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;wget https://archive.apache.org/dist/tomcat/tomcat-9/v9.0.75/bin/apache-tomcat-9.0.75.tar.gz
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Extract package&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;tar xzvf apache-tomcat-9.0.75.tar.gz
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Add tomcat user to run tomcat services and add user to a home directory.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;useradd --home-dir /usr/local/tomcat --shell /sbin/nologin tomcat
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The tomcat user created will be used by tomcat process so we don't need login (--shell /sbin/nologin).&lt;/p&gt;

&lt;p&gt;Copy all file in apache-tomcat-9.0.75 to /usr/local/tomcat/&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;cp -r /tmp/apache-tomcat-9.0.75/* /usr/local/tomcat/
&lt;/code&gt;&lt;/pre&gt;

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

&lt;p&gt;When we do this, the copy command will copy the folder and file as root user and all files and folder will automatically be owned by root.&lt;br&gt;
We need to change the ownership of the files and folder to tomcat user and tomcat group.&lt;br&gt;
This changes is required for systemctl otherwise using systemctl to start, stop or enable tomcat service will fail.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;chown -R tomcat.tomcat /usr/local/tomcat
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&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%2Fe6rdrds14kwr05st61n3.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%2Fe6rdrds14kwr05st61n3.png" alt="tomcat" width="669" height="241"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Setup systemctl command for tomcat&lt;/p&gt;

&lt;p&gt;Create tomcat service file&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;vi /etc/systemd/system/tomcat.service
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Update the tomcat.srvice with this configuration&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;[Unit]
Description=Tomcat
After=network.target
[Service]
User=tomcat
WorkingDirectory=/usr/local/tomcat
Environment=JRE_HOME=/usr/lib/jvm/jre
Environment=JAVA_HOME=/usr/lib/jvm/jre
Environment=CATALINA_HOME=/usr/local/tomcat
Environment=CATALINE_BASE=/usr/local/tomcat
ExecStart=/usr/local/tomcat/bin/catalina.sh run
ExecStop=/usr/local/tomcat/bin/shutdown.sh
SyslogIdentifier=tomcat-%i
[Install]
WantedBy=multi-user.target
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;When we say systemctl start, &lt;em&gt;"ExecStart=/usr/local/tomcat/bin/catalina.sh run" _get executed and for systemctl stop _"ExecStop=/usr/local/tomcat/bin/shutdown.sh"&lt;/em&gt; get executed.&lt;/p&gt;

&lt;p&gt;Reload the configuration&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;systemctl daemon-reload
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Start and Enable service&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;systemctl start tomcat
systemctl enable tomcat
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Build code and Deploy&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Update configuration,&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;cd vprofile-project
&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;vim src/main/resources/application.properties
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Update file with backend server details.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;#JDBC Configutation for Database Connection
jdbc.driverClassName=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://&amp;lt;pubilc_IP_address&amp;gt;:3306/accounts?useUnicode=true&amp;amp;characterEncoding=UTF-8&amp;amp;zeroDateTimeBehavior=convertToNull
jdbc.username=admin # database username
jdbc.password=admin123 # databse password

#Memcached Configuration For Active and StandBy Host
#For Active Host
memcached.active.host=&amp;lt;pubilc_IP_address&amp;gt;
memcached.active.port=11211
#For StandBy Host
memcached.standBy.host=127.0.0.2
memcached.standBy.port=11211

#RabbitMq Configuration
rabbitmq.address=&amp;lt;pubilc_IP_address&amp;gt;
rabbitmq.port=5672
rabbitmq.username=test
rabbitmq.password=test
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Build code&lt;br&gt;
Run below command inside the repository&lt;br&gt;
Make sure you are in the vprofile directory &amp;amp; run the mvn install&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;



&lt;p&gt;The command will read the source code and build the artifact ( A deployable product ) &lt;/p&gt;

&lt;p&gt;Artifact is basically an archive ( in java, archive format is var, jar , war )&lt;/p&gt;

&lt;p&gt;Deploy artifact, first stop the tomcat service&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;systemctl stop tomcat
&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;rm -rf /usr/local/tomcat/webapps/ROOT*
cp target/vprofile-v2.war /usr/local/tomcat/webapps/ROOT.war
systemctl start tomcat
chown tomcat.tomcat /usr/local/tomcat/webapps -R
systemctl restart tomcat
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;what we did was to remove the default app in java (ROOT) and replace it with our artifact (target/vprofile-v2.war )&lt;br&gt;
We restart tomcat and when tomcat find a war file its will extract it to ROOT.&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%2Fc2ky73mb7cvr8tdl2azc.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%2Fc2ky73mb7cvr8tdl2azc.png" alt="tomcat" width="649" height="394"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Finally,&lt;br&gt;
&lt;strong&gt;SET UP NGINX&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;For our nginx which route request to our tomcat service.&lt;/p&gt;

&lt;p&gt;We are going to host it on our Ubuntu EC2 instance,&lt;/p&gt;

&lt;p&gt;So SSH into the instance,&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;



&lt;p&gt;Install nginx&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;



&lt;p&gt;Create Nginx conf file&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;vi /etc/nginx/sites-available/vproapp
&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;upstream vproapp {
    server &amp;lt;public_IP_of_Centos_instance&amp;gt;:8080;
}

server {
    listen 80;
    location / {
        proxy_pass http://vproapp;
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Remove default nginx conf&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt; rm -rf /etc/nginx/sites-enabled/default
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Create link to activate website and make our website default&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;ln -s /etc/nginx/sites-available/vproapp /etc/nginx/sites-enabled/vproapp
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Restart Nginx&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt; systemctl restart nginx
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Security&lt;/strong&gt;.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Allow inbound rule for our EC2 instance&lt;/li&gt;
&lt;li&gt;For the Centos, allow inbound traffic on port 3306 (Mysql), 11211 (memcached), 5672 ( RabbitMQ) from Ubuntu. &lt;/li&gt;
&lt;li&gt;Allow inbound traffic from 0.0.0.0 on port 80 on the Ubuntu instance since its public-facing.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Validation&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Access the website from web browser by :80&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%2Fuvi9xgk69j7fbr4tc5ux.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%2Fuvi9xgk69j7fbr4tc5ux.png" alt="Login page" width="800" height="394"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Login using &lt;strong&gt;admin_vp as user admin-vp as password&lt;/strong&gt;&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%2Fgdijdlkzhzb26zqob10x.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%2Fgdijdlkzhzb26zqob10x.png" alt="Website page" width="800" height="394"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Click on RabbitMQ &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%2Fakwsgb0k319epvyoz2aw.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%2Fakwsgb0k319epvyoz2aw.png" alt="RabbitMQ" width="800" height="407"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Click on All_user and this will fetch all user on databse&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%2Fxu9sgo7b4uuz4fkbfsen.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%2Fxu9sgo7b4uuz4fkbfsen.png" alt="Users" width="800" height="407"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Thank you for reading...&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Automated User Management Script for Linux Systems</title>
      <dc:creator>damilola lawal</dc:creator>
      <pubDate>Wed, 03 Jul 2024 20:46:32 +0000</pubDate>
      <link>https://dev.to/damilola_lawal_b415434987/automated-user-management-script-for-linux-systems-2olo</link>
      <guid>https://dev.to/damilola_lawal_b415434987/automated-user-management-script-for-linux-systems-2olo</guid>
      <description>&lt;p&gt;Nowadays managing user accounts properly is extremely important for SysOps professionals working in dynamic IT setups. &lt;br&gt;
The pro of user provisioning is that it saves time, ensures consistency , security across systems  and improve efficiency since much of the process can be automated.&lt;/p&gt;

&lt;p&gt;In this article, we will discuss about bash script and how to create a bash script that can be used for creating and managing accounts of users on Linux servers.&lt;/p&gt;

&lt;p&gt;In this article we will be writing a script which that reads a text file containing the employee’s usernames and group names, where each line is formatted as "user;groups".&lt;/p&gt;

&lt;p&gt;This script will create users and groups as specified, set up home directories with appropriate permissions and ownership, generate random passwords for the users, and log all actions to &lt;em&gt;var/log/user_management.log&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Additionally, it will store the generated passwords securely in &lt;em&gt;/var/secure/user_passwords.txt&lt;/em&gt;.&lt;br&gt;
we will ensure error handling for scenarios like existing users by the script.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Each User will have a personal group with the same group name as the username, this group name will not be written in the text file&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;A user can have multiple groups, each group delimited by comma ","&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Usernames and user groups are separated by semicolon ";"&lt;br&gt;
For example;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;ol&gt;
&lt;li&gt;light; sudo,dev,www-data&lt;/li&gt;
&lt;li&gt;idimma; sudo&lt;/li&gt;
&lt;li&gt;mayowa; dev,www-data&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Where light is username and groups are sudo, dev, www-data&lt;br&gt;
Firstly,&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
# Check if script is run as root
if [ "$EUID" -ne 0 ]; then
  echo "Please run as root"
  exit 1
fi
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The #!/bin/bash line at the beginning of a script is known as the shebang. This shebang line tells the operating system which interpreter to use to execute the script. In this case, it specifies the Bash shell as the interpreter.&lt;/p&gt;

&lt;p&gt;The line if [ "$EUID" -ne 0 ]; checks if the script is being run as root. The EUID (Effective User ID) is used to determine the privileges of the executing process. The -ne operator means "not equal." Since the root user has an ID of 0, this condition checks if the current user is not root. If true, it prompts to run the script as root and exits.&lt;/p&gt;

&lt;p&gt;Next;&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 input file is provided
if [ -z "$1" ]; then
  echo "Usage: bash create_users.sh &amp;lt;name-of-text-file&amp;gt;"
  exit 1
fi
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The script checks if a positional argument is provided. If not, it exits with a status of 1 and displays the message: "Usage: bash create_user.sh ," prompting the user to provide the correct argument.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;The -z is a string value which means value has a length of zero&lt;/em&gt; and &lt;em&gt;"$1" indicate the first parameter after the script name($0)&lt;/em&gt; which is assigned a variable name INPUT_FILE. So it checks if the first positional parameter is empty.&lt;/p&gt;

&lt;p&gt;Next;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;INPUT_FILE="$1"
LOG_FILE="/var/log/user_management.log"
PASSWORD_FILE="/var/secure/user_passwords.txt"

# Ensure log and password files exist and have the correct permissions
touch $LOG_FILE
chmod 644 $LOG_FILE

mkdir -p /var/secure
touch $PASSWORD_FILE
chmod 600 $PASSWORD_FILE
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We will create the directory /var/secure and the file user_password.txt in it to securely store user passwords with permissions set to "600" (read and write only for the owner). Additionally, we will create the file management.log in the /var/log directory to log all events.&lt;/p&gt;

&lt;p&gt;The first positional parameter($1) is assigned INPUT_FILE as variable&lt;/p&gt;

&lt;p&gt;Next;&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;



&lt;p&gt;The OpenSSL rand command will be used to generate a cryptographic password that is base64 encoded (strong and resistant as it contains letters, numbers, and characters). This function will generate the password, which will be called in the script.&lt;/p&gt;

&lt;p&gt;Next;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# Process the input file
while IFS=';' read -r username groups; do
  # Create personal group for the user
  if ! getent group "$username" &amp;amp;&amp;gt;/dev/null; then
    groupadd "$username"
    echo "Created group $username" | tee -a $LOG_FILE
  fi
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Let's process the input file;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;IFS means Internal Field Separator; this is an environment variable which define a list of characters the Bash shell uses as field separators. These include space, tab, newline.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Use the while condition to read the username and group taking note of the separators by the IFS.&lt;/p&gt;

&lt;p&gt;We will create a personal group for the user but before then we will check the system group database (/etc/group) using the &lt;em&gt;getent&lt;/em&gt; command to ensure the group is not present.&lt;/p&gt;

&lt;p&gt;The negate operator (!) is used to reverse the outcome of an expression. In this case, if the $group does not exist, the expression with ! will evaluate to true. This condition triggers the groupadd command to create the group if it doesn't already exist.&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 user already exists
  if id "$username" &amp;amp;&amp;gt;/dev/null; then
    echo "User $username already exists. Skipping..." | tee -a $LOG_FILE
    continue
  fi
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If user already exist then our shell script will throw an error message indicating that user exist but we want to redirect such output( standard error or output) to the &lt;em&gt;/dev/null&lt;/em&gt; and the tee reads the output and save it silently in the $LOG_FILE.&lt;/p&gt;

&lt;p&gt;We then use the continue to create user if user does not exist.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# Create user and personal group
  useradd -m -s /bin/bash -g "$username" "$username"
  if [ $? -eq 0 ]; then
    echo "Created user $username with a personal group $username" | tee -a $LOG_FILE
  else
    echo "Failed to create user $username" | tee -a $LOG_FILE
    continue
  fi
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Let's add create user and add to the personal group using the popular command &lt;em&gt;useradd&lt;/em&gt; and use the -m(to add a home directory for the user, -s (to set the shell to /bin/bash).&lt;/p&gt;

&lt;p&gt;If the user is created and added to the personal group successfully this make the exit status ($?) equal zero (0) and it print the success message "Created user $username with a personal group $username" to the $LOG_FILE and if not it execute the else statement.&lt;/p&gt;

&lt;p&gt;Next;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt; # Generate password and set it for the user
  password=$(generate_password)
  echo "$username:$password" | chpasswd
  if [ $? -eq 0 ]; then
    echo "$username,$password" &amp;gt;&amp;gt; $PASSWORD_FILE
    echo "Set password for $username" | tee -a $LOG_FILE
  else
    echo "Failed to set password for $username" | tee -a $LOG_FILE
  fi
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Let's call the function to generate the password and set password for the user using chpasswd (change password) , write the username,password into the $PASSWORD_FILE and log it.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;chpasswd is designed to process multiple username and password pairs from standard input (usually via a pipe | or a redirection &amp;lt;)&lt;br&gt;
.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Next,&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# Create additional groups if specified
  if [ -n "$groups" ]; then
    IFS=',' read -ra group_array &amp;lt;&amp;lt;&amp;lt; "$groups"
    for group in "${group_array[@]}"; do
      # Create group if it doesn't exist
      if ! getent group "$group" &amp;amp;&amp;gt;/dev/null; then
        groupadd "$group"
        echo "Created group $group" | tee -a $LOG_FILE
      fi
  fi
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;we will be creating other group which user will be by passing the $groups as an array and iterate  over it by "${group_array[@]}" where "@" insinuate every character.&lt;/p&gt;

&lt;p&gt;The character -n is also similar to the -z only that it describe value which length is greater than zero&lt;/p&gt;

&lt;p&gt;We will check the system group database (/etc/group) using the getent command but will add a negate operator (!) which will negate the expression and makes it True, if the $group does not exist thereby causing it to create the group if it doesn't exist using the groupadd command as previously discussed.&lt;/p&gt;

&lt;p&gt;Next;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;usermod -aG "$group" "$username"
      if [ $? -eq 0 ]; then
        echo "Added $username to group $group" | tee -a $LOG_FILE
      else
        echo "Failed to add $username to group $group" | tee -a $LOG_FILE
      fi
    done
  fi
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;we then add the user to group using the usermod -aG command&lt;br&gt;
Finally,&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;done &amp;lt; "$INPUT_FILE"
echo "User creation process completed." | tee -a $LOG_FILE
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;we will close our while  loop condition and pass the $INPUT_FILE to read lines from it.&lt;br&gt;
Create a directory, touch a file named create.sh (shell script) in the directory and make the file executable;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;sudo mkdir -p ~/bash-script
sudo chmod +x ~/bash-script/create_users.sh
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;open the create and paste this 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
#check if script is run as root
if [ "$EUID" -ne 0 ]; then
  echo "Please run as root"
  exit 1
fi

# Check if the input file is provided
if [ -z "$1" ]; then
  echo "Usage: bash create_users.sh &amp;lt;name-of-text-file&amp;gt;"
  exit 1
fi

INPUT_FILE="$1"
LOG_FILE="/var/log/user_management.log"
PASSWORD_FILE="/var/secure/user_passwords.txt"

# Ensure log and password files exist and have the correct permissions
touch $LOG_FILE
chmod 644 $LOG_FILE

mkdir -p /var/secure
touch $PASSWORD_FILE
chmod 600 $PASSWORD_FILE

# Function to generate random password
generate_password() {
  openssl rand -base64 12
}

# Process the input file
while IFS=';' read -r username groups; do
  # Create personal group for the user
  if ! getent group "$username" &amp;amp;&amp;gt;/dev/null; then
    groupadd "$username"
    echo "Created group $username" | tee -a $LOG_FILE
  fi

  # Check if user already exists
  if id "$username" &amp;amp;&amp;gt;/dev/null; then
    echo "User $username already exists. Skipping..." | tee -a $LOG_FILE
    continue
  fi

  # Create user and personal group
  useradd -m -s /bin/bash -g "$username" "$username"
  if [ $? -eq 0 ]; then
    echo "Created user $username with a personal group $username" | tee -a $LOG_FILE
  else
    echo "Failed to create user $username" | tee -a $LOG_FILE
    continue
  fi

  # Generate password and set it for the user
  password=$(generate_password)
  echo "$username:$password" | chpasswd
  if [ $? -eq 0 ]; then
    echo "$username,$password" &amp;gt;&amp;gt; $PASSWORD_FILE
    echo "Set password for $username" | tee -a $LOG_FILE
  else
    echo "Failed to set password for $username" | tee -a $LOG_FILE
  fi

  # Create additional groups if specified
  if [ -n "$groups" ]; then
    IFS=',' read -ra group_array &amp;lt;&amp;lt;&amp;lt; "$groups"
    for group in "${group_array[@]}"; do
      # Create group if it doesn't exist
      if ! getent group "$group" &amp;amp;&amp;gt;/dev/null; then
        groupadd "$group"
        echo "Created group $group" | tee -a $LOG_FILE
      fi

      usermod -aG "$group" "$username"
      if [ $? -eq 0 ]; then
        echo "Added $username to group $group" | tee -a $LOG_FILE
      else
        echo "Failed to add $username to group $group" | tee -a $LOG_FILE
      fi
    done
  fi
done &amp;lt; "$INPUT_FILE"

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

&lt;/div&gt;



&lt;p&gt;Create a file (input_file.txt) containing username;groups&lt;br&gt;
&lt;/p&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;p&gt;Run the script and pass the input_file.txt as argument.&lt;/p&gt;

&lt;p&gt;Thank you for reading, to learn more kindly join the HNG internship programme to get your tech skill upgraded and land you dream job.&lt;br&gt;
Follow this link&lt;br&gt;
&lt;a href="https://hng.tech/internship"&gt;https://hng.tech/internship&lt;/a&gt;, &lt;br&gt;
&lt;a href="https://hng.tech/hire"&gt;https://hng.tech/hire&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;hsh&lt;/p&gt;

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