<?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: John Doe</title>
    <description>The latest articles on DEV Community by John Doe (@gideonisbuilding).</description>
    <link>https://dev.to/gideonisbuilding</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%2F1724925%2Fd78aebdf-c912-46c8-9a7f-e4b8a38d9ec8.jpeg</url>
      <title>DEV Community: John Doe</title>
      <link>https://dev.to/gideonisbuilding</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/gideonisbuilding"/>
    <language>en</language>
    <item>
      <title>Automating Full-Stack Cloud Deployments Using Terraform and Ansible</title>
      <dc:creator>John Doe</dc:creator>
      <pubDate>Tue, 03 Dec 2024 22:15:17 +0000</pubDate>
      <link>https://dev.to/gideonisbuilding/automating-cloud-infrastructure-deployment-with-terraform-and-ansible-a-comprehensive-guide-2bf2</link>
      <guid>https://dev.to/gideonisbuilding/automating-cloud-infrastructure-deployment-with-terraform-and-ansible-a-comprehensive-guide-2bf2</guid>
      <description>&lt;p&gt;Infrastructure as Code (IaC) is the cornerstone of automation. With the right tools, it’s possible to manage cloud resources, deploy applications, and configure servers without needing to manually perform these tasks each time. &lt;/p&gt;

&lt;p&gt;In this article, we will walk you through an end-to-end project involving &lt;strong&gt;Terraform&lt;/strong&gt; and &lt;strong&gt;Ansible&lt;/strong&gt; to provision cloud infrastructure, deploy application and monitoring stacks, and configure everything automatically. This project will provide a deep dive into &lt;strong&gt;Docker&lt;/strong&gt;, &lt;strong&gt;Terraform&lt;/strong&gt;, and &lt;strong&gt;Ansible&lt;/strong&gt;, as well as how they work together to automate your infrastructure setup and deployment pipeline.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Overview of the Project&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;This project involves:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Building Docker images for a frontend and backend application.&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Designing and provisioning cloud infrastructure using Terraform.&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Using Terraform to trigger Ansible playbooks for deploying the application stack and setting up the monitoring stack.&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Creating a reverse proxy using Traefik or Nginx for routing between services.&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Configuring monitoring using Prometheus, Grafana, cAdvisor, and Loki.&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The ultimate goal is to run a single Terraform command that provisions the infrastructure, deploys all services, and configures routing automatically.&lt;/p&gt;




&lt;h2&gt;
  
  
  &lt;strong&gt;Step 1: Building and Pushing Docker Images&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Before we can deploy anything, we need Docker images for our frontend and backend applications. This step ensures that we have prebuilt images ready for deployment on any cloud instance.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Frontend Application&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;For the frontend, we use &lt;strong&gt;React&lt;/strong&gt; to build a single-page application. The Dockerfile for the frontend might look like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight docker"&gt;&lt;code&gt;&lt;span class="c"&gt;#-----------------&lt;/span&gt;
&lt;span class="c"&gt;# Building the app&lt;/span&gt;
&lt;span class="c"&gt;#-----------------&lt;/span&gt;
&lt;span class="k"&gt;FROM&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;node:17-alpine&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;AS&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;build&lt;/span&gt;

&lt;span class="k"&gt;WORKDIR&lt;/span&gt;&lt;span class="s"&gt; /app/frontend&lt;/span&gt;

&lt;span class="k"&gt;COPY&lt;/span&gt;&lt;span class="s"&gt; package*.json ./&lt;/span&gt;

&lt;span class="k"&gt;RUN &lt;/span&gt;npm &lt;span class="nb"&gt;install&lt;/span&gt;

&lt;span class="k"&gt;COPY&lt;/span&gt;&lt;span class="s"&gt; . .&lt;/span&gt;

&lt;span class="k"&gt;ARG&lt;/span&gt;&lt;span class="s"&gt; VITE_API_URL&lt;/span&gt;

&lt;span class="k"&gt;ENV&lt;/span&gt;&lt;span class="s"&gt; VITE_API_URL=$VITE_API_URL&lt;/span&gt;

&lt;span class="k"&gt;RUN &lt;/span&gt;npm run build

&lt;span class="c"&gt;#----------------&lt;/span&gt;
&lt;span class="c"&gt;# Serving the app&lt;/span&gt;
&lt;span class="c"&gt;#----------------&lt;/span&gt;
&lt;span class="k"&gt;FROM&lt;/span&gt;&lt;span class="s"&gt; nginx:alpine&lt;/span&gt;

&lt;span class="k"&gt;COPY&lt;/span&gt;&lt;span class="s"&gt; --from=build /app/frontend/dist /usr/share/nginx/html&lt;/span&gt;

&lt;span class="k"&gt;COPY&lt;/span&gt;&lt;span class="s"&gt; nginx.conf /etc/nginx/conf.d/default.conf&lt;/span&gt;

&lt;span class="k"&gt;EXPOSE&lt;/span&gt;&lt;span class="s"&gt; 80&lt;/span&gt;

&lt;span class="k"&gt;CMD&lt;/span&gt;&lt;span class="s"&gt; [ "nginx", "-g", "daemon off;" ]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  &lt;strong&gt;Backend Application&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;The backend is built using &lt;strong&gt;FastAPI&lt;/strong&gt;, which is a modern, fast web framework for building APIs with Python. The Dockerfile for the backend would look something like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight docker"&gt;&lt;code&gt;&lt;span class="k"&gt;FROM&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;python:3.11&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;AS&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;build&lt;/span&gt;

&lt;span class="k"&gt;WORKDIR&lt;/span&gt;&lt;span class="s"&gt; /app/backend&lt;/span&gt;

&lt;span class="k"&gt;COPY&lt;/span&gt;&lt;span class="s"&gt; pyproject.toml poetry.lock ./&lt;/span&gt;

&lt;span class="k"&gt;RUN &lt;/span&gt;pip &lt;span class="nb"&gt;install &lt;/span&gt;poetry

&lt;span class="k"&gt;RUN &lt;/span&gt;poetry config virtualenvs.create &lt;span class="nb"&gt;false&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="se"&gt;\
&lt;/span&gt;    poetry &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;--no-root&lt;/span&gt;

&lt;span class="k"&gt;COPY&lt;/span&gt;&lt;span class="s"&gt; . .&lt;/span&gt;

&lt;span class="k"&gt;RUN &lt;/span&gt;pip &lt;span class="nb"&gt;install &lt;/span&gt;sqlalchemy sqlmodel alembic

&lt;span class="k"&gt;ENV&lt;/span&gt;&lt;span class="s"&gt; PYTHONPATH=/app/backend&lt;/span&gt;

&lt;span class="k"&gt;RUN &lt;/span&gt;&lt;span class="nb"&gt;chmod&lt;/span&gt; +x /app/backend/prestart.sh

&lt;span class="k"&gt;EXPOSE&lt;/span&gt;&lt;span class="s"&gt; 8000&lt;/span&gt;

&lt;span class="k"&gt;CMD&lt;/span&gt;&lt;span class="s"&gt; ["sh", "-c", "./prestart.sh &amp;amp;&amp;amp; uvicorn app.main:app --host 0.0.0.0 --port 8000"]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Once the Dockerfiles are in place, you build and push the images to &lt;strong&gt;Docker Hub&lt;/strong&gt; (or any other container registry of your choice):&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;# Build the frontend image&lt;/span&gt;
docker build &lt;span class="nt"&gt;-t&lt;/span&gt; &amp;lt;your-username&amp;gt;/frontend:latest &lt;span class="nb"&gt;.&lt;/span&gt;

&lt;span class="c"&gt;# Build the backend image&lt;/span&gt;
docker build &lt;span class="nt"&gt;-t&lt;/span&gt; &amp;lt;your-username&amp;gt;/backend:latest &lt;span class="nb"&gt;.&lt;/span&gt;

&lt;span class="c"&gt;# Push the images to Docker Hub&lt;/span&gt;
docker push &amp;lt;your-username&amp;gt;/frontend:latest
docker push &amp;lt;your-username&amp;gt;/backend:latest
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This will make the Docker images available for deployment later on when using &lt;strong&gt;Terraform&lt;/strong&gt; and &lt;strong&gt;Ansible&lt;/strong&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  &lt;strong&gt;Step 2: Designing the Infrastructure&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Before provisioning resources, it’s essential to define the architecture. In this project, the architecture involves:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A &lt;strong&gt;virtual machine (VM)&lt;/strong&gt; that hosts the application stack (frontend, backend, and reverse proxy).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Networking&lt;/strong&gt; to ensure the components can communicate with each other.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;A reverse proxy&lt;/strong&gt; (either &lt;strong&gt;Traefik&lt;/strong&gt; or &lt;strong&gt;Nginx&lt;/strong&gt;) to route traffic between services.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Prometheus&lt;/strong&gt;, &lt;strong&gt;Grafana&lt;/strong&gt;, &lt;strong&gt;cAdvisor&lt;/strong&gt;, &lt;strong&gt;Loki&lt;/strong&gt;, and &lt;strong&gt;Promtail&lt;/strong&gt; to monitor the applications and collect logs.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Architecture Diagram&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Here’s a simple architecture diagram to help visualize the components:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ft5ddnniupma8vz55cmm0.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ft5ddnniupma8vz55cmm0.png" alt="Deployment Architechture" width="800" height="961"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  &lt;strong&gt;Step 3: Writing Terraform Configuration&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Terraform is used to provision the infrastructure, such as the cloud instance (VM), and to trigger the execution of the Ansible playbook. The &lt;strong&gt;main.tf&lt;/strong&gt; file will define the infrastructure, and it will include:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The creation of an &lt;strong&gt;AWS EC2 instance&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;An &lt;strong&gt;Elastic IP&lt;/strong&gt; (EIP) to give the instance a static public IP.&lt;/li&gt;
&lt;li&gt;A &lt;strong&gt;security group&lt;/strong&gt; that allows SSH access.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Outputs&lt;/strong&gt; to show important information such as the public IP of the instance.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Here is a simple Terraform configuration for provisioning an AWS EC2 instance:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight hcl"&gt;&lt;code&gt;&lt;span class="nx"&gt;provider&lt;/span&gt; &lt;span class="s2"&gt;"aws"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;region&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"us-east-1"&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nx"&gt;resource&lt;/span&gt; &lt;span class="s2"&gt;"aws_instance"&lt;/span&gt; &lt;span class="s2"&gt;"app"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;ami&lt;/span&gt;           &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"ami-12345678"&lt;/span&gt;  &lt;span class="c1"&gt;# Replace with an appropriate AMI ID&lt;/span&gt;
  &lt;span class="nx"&gt;instance_type&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"t2.micro"&lt;/span&gt;
  &lt;span class="nx"&gt;key_name&lt;/span&gt;      &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"your-key-pair"&lt;/span&gt;

  &lt;span class="nx"&gt;tags&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;Name&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"App Instance"&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="nx"&gt;associate_public_ip_address&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nx"&gt;resource&lt;/span&gt; &lt;span class="s2"&gt;"aws_eip"&lt;/span&gt; &lt;span class="s2"&gt;"dojo-eip"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;instance&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;aws_instance&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nx"&gt;output&lt;/span&gt; &lt;span class="s2"&gt;"public_ip"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;value&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;aws_instance&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;public_ip&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  &lt;strong&gt;Terraform and Ansible Integration&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Terraform will use &lt;strong&gt;Ansible&lt;/strong&gt; to configure the application after the EC2 instance is created. The &lt;strong&gt;null_resource&lt;/strong&gt; and &lt;strong&gt;remote-exec provisioner&lt;/strong&gt; are used to execute commands on the instance via SSH.&lt;/p&gt;

&lt;p&gt;Here is the relevant Terraform configuration that integrates Ansible with Terraform:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight hcl"&gt;&lt;code&gt;&lt;span class="nx"&gt;resource&lt;/span&gt; &lt;span class="s2"&gt;"null_resource"&lt;/span&gt; &lt;span class="s2"&gt;"ansible"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;provisioner&lt;/span&gt; &lt;span class="s2"&gt;"remote-exec"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;connection&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;host&lt;/span&gt;        &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;aws_instance&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;public_ip&lt;/span&gt;
      &lt;span class="nx"&gt;user&lt;/span&gt;        &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"ubuntu"&lt;/span&gt;
      &lt;span class="nx"&gt;private_key&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;file&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"/path/to/your/private-key.pem"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="nx"&gt;inline&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"echo 'connected!'"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="nx"&gt;provisioner&lt;/span&gt; &lt;span class="s2"&gt;"local-exec"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;command&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"ansible-playbook -vvv -T 180 -i /path/to/inventory /path/to/ansible/playbook.yml --extra-vars '@/path/to/ansible/vars/docker_hub.yml'"&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="nx"&gt;depends_on&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;aws_instance&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  &lt;strong&gt;Step 4: Writing Ansible Playbooks&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Ansible is used for configuring the application and monitoring stacks. The &lt;strong&gt;playbook.yml&lt;/strong&gt; file will define the steps to set up the system.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Server Setup&lt;/strong&gt;: Install necessary dependencies and configure the environment.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Application Setup&lt;/strong&gt;: Pull Docker images from Docker Hub and run the frontend and backend services.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Monitoring Setup&lt;/strong&gt;: Install Prometheus, Grafana, and other monitoring tools.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Reverse Proxy Setup&lt;/strong&gt;: Configure Traefik or Nginx to route traffic.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Here’s an example of the playbook:&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="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;Configure app server&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;become&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;yes&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 Docker&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;docker.io&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="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 shared Docker network&lt;/span&gt;
      &lt;span class="na"&gt;command&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;docker network create app-network&lt;/span&gt;

    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Pull frontend Docker image&lt;/span&gt;
      &lt;span class="na"&gt;docker_image&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="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;{{&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;docker_hub.frontend_image&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;}}"&lt;/span&gt;
        &lt;span class="na"&gt;source&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;pull&lt;/span&gt;

    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Pull backend Docker image&lt;/span&gt;
      &lt;span class="na"&gt;docker_image&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="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;{{&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;docker_hub.backend_image&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;}}"&lt;/span&gt;
        &lt;span class="na"&gt;source&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;pull&lt;/span&gt;

    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Run frontend container&lt;/span&gt;
      &lt;span class="na"&gt;docker_container&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;frontend&lt;/span&gt;
        &lt;span class="na"&gt;image&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;{{&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;docker_hub.frontend_image&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;}}"&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;restart_policy&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;always&lt;/span&gt;
        &lt;span class="na"&gt;networks&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;app-network&lt;/span&gt;

    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Run backend container&lt;/span&gt;
      &lt;span class="na"&gt;docker_container&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;backend&lt;/span&gt;
        &lt;span class="na"&gt;image&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;{{&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;docker_hub.backend_image&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;}}"&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;restart_policy&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;always&lt;/span&gt;
        &lt;span class="na"&gt;networks&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;app-network&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 Traefik for routing&lt;/span&gt;
      &lt;span class="na"&gt;docker_container&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;traefik&lt;/span&gt;
        &lt;span class="na"&gt;image&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;traefik:v2.5&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;restart_policy&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;always&lt;/span&gt;
        &lt;span class="na"&gt;ports&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;80:80"&lt;/span&gt;
          &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;443:443"&lt;/span&gt;
        &lt;span class="na"&gt;command&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;--api.insecure=true&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;--providers.docker"&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 Prometheus&lt;/span&gt;
      &lt;span class="na"&gt;docker_container&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;prometheus&lt;/span&gt;
        &lt;span class="na"&gt;image&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;prom/prometheus&lt;/span&gt;
        &lt;span class="na"&gt;state&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;

&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="s"&gt;started&lt;/span&gt;
        &lt;span class="s"&gt;restart_policy&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt; &lt;span class="s"&gt;always&lt;/span&gt;
        &lt;span class="s"&gt;ports&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt;
          &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;9090:9090"&lt;/span&gt;
&lt;span class="err"&gt;        &lt;/span&gt;&lt;span class="na"&gt;volumes&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;/prometheus.yml:/etc/prometheus/prometheus.yml&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  &lt;strong&gt;Step 5: Finalizing the Deployment&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Once the &lt;strong&gt;Terraform configuration&lt;/strong&gt; and &lt;strong&gt;Ansible playbooks&lt;/strong&gt; are set up:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Run &lt;code&gt;terraform apply&lt;/code&gt; to provision the infrastructure.&lt;/li&gt;
&lt;li&gt;Terraform will automatically trigger Ansible, which will configure the server and deploy the application.&lt;/li&gt;
&lt;li&gt;After execution, you can access the application via the public IP provided by Terraform, and the monitoring stack (Grafana, Prometheus, etc.) will be up and running.&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Testing the Setup&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;You can test the entire setup by visiting the public IP address in your browser. Ensure that:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The frontend and backend applications are accessible.&lt;/li&gt;
&lt;li&gt;The monitoring dashboard in Grafana is functioning.&lt;/li&gt;
&lt;li&gt;Logs are being collected by Loki.&lt;/li&gt;
&lt;/ul&gt;




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

&lt;p&gt;This project demonstrated how to automate cloud infrastructure provisioning and application deployment using Terraform and Ansible. By combining &lt;strong&gt;IaC&lt;/strong&gt; and &lt;strong&gt;CM&lt;/strong&gt;, you can ensure repeatable, consistent, and scalable deployments. In this case, we also integrated monitoring into the workflow, which is an essential part of maintaining cloud-based systems.&lt;/p&gt;

&lt;p&gt;Through this guide, you learned how to:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Build and push Docker images for your applications.&lt;/li&gt;
&lt;li&gt;Write Terraform configurations to provision cloud resources.&lt;/li&gt;
&lt;li&gt;Use Ansible to configure servers and deploy applications.&lt;/li&gt;
&lt;li&gt;Set up monitoring using Prometheus, Grafana, and other tools.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;This approach can be adapted to suit more complex applications and environments, making it an invaluable skill for any DevOps engineer or cloud automation specialist. Happy automating!&lt;/p&gt;

</description>
      <category>ansible</category>
      <category>terraform</category>
      <category>devops</category>
      <category>docker</category>
    </item>
    <item>
      <title>Connecting Jenkins to Slack: A Beginner's Guide</title>
      <dc:creator>John Doe</dc:creator>
      <pubDate>Fri, 29 Nov 2024 13:04:08 +0000</pubDate>
      <link>https://dev.to/gideonisbuilding/connecting-jenkins-to-slack-a-beginners-guide-2c7a</link>
      <guid>https://dev.to/gideonisbuilding/connecting-jenkins-to-slack-a-beginners-guide-2c7a</guid>
      <description>&lt;p&gt;Integrating &lt;strong&gt;Jenkins&lt;/strong&gt; with &lt;strong&gt;Slack&lt;/strong&gt; allows your development team to receive real-time notifications about build statuses, deployments, and other important events directly in Slack channels. This seamless communication enhances collaboration, accelerates issue resolution, and keeps everyone informed throughout the development lifecycle.&lt;/p&gt;

&lt;p&gt;This guide provides a step-by-step walkthrough on how to connect Jenkins to Slack, ensuring that your team stays updated on your CI/CD pipeline activities&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Benefits of Integrating Jenkins with Slack&lt;/strong&gt;
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Immediate Feedback&lt;/strong&gt;: Slack notifications provide instant updates on build processes, enabling faster troubleshooting.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Improved Team Collaboration&lt;/strong&gt;: Real-time alerts keep all team members on the same page, enhancing communication and efficiency.&lt;/li&gt;
&lt;/ul&gt;




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

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

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Jenkins&lt;/strong&gt; installed and running on your local Windows machine. (Refer to previous documentation on installing Jenkins using Docker if needed.)&lt;/li&gt;
&lt;li&gt;Administrative access to your Jenkins instance.&lt;/li&gt;
&lt;li&gt;A &lt;strong&gt;Slack workspace&lt;/strong&gt; where you can install apps and integrations.&lt;/li&gt;
&lt;li&gt;Working understanding of Jenkins and Slack.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Table of Contents
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Installing the Slack Notification Plugin in Jenkins&lt;/li&gt;
&lt;li&gt;Creating a Slack App and Obtaining Credentials&lt;/li&gt;
&lt;li&gt;Configuring Jenkins Global Settings for Slack&lt;/li&gt;
&lt;li&gt;Setting Up a Jenkins Job to Send Slack Notifications&lt;/li&gt;
&lt;li&gt;Testing the Integration&lt;/li&gt;
&lt;li&gt;Conclusion&lt;/li&gt;
&lt;/ol&gt;




&lt;p&gt;&lt;a&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  1. Installing the Slack Notification Plugin in Jenkins
&lt;/h2&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Why This Step?&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;To enable Jenkins to communicate with Slack, you need to install the Slack Notification Plugin, which provides the necessary functionality for sending messages to Slack channels.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Step-by-Step Guide&lt;/strong&gt;
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Access Jenkins Dashboard&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Open your web browser and go to your Jenkins instance (e.g., &lt;code&gt;http://localhost:8080&lt;/code&gt; or whatever port you have configured your Jenkins server to listen on).&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Navigate to Plugin Manager&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Click on &lt;strong&gt;"Manage Jenkins"&lt;/strong&gt; on the left sidebar.&lt;/li&gt;
&lt;li&gt;Select &lt;strong&gt;"Manage Plugins"&lt;/strong&gt;.
&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fa22vruykzksq6jh3kccr.png" alt="Jenkins Dashboard" width="800" height="784"&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fzjvebxzlwftrgl78g6ei.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fzjvebxzlwftrgl78g6ei.png" alt="Plugin Manager" width="800" height="804"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Install the Slack Notification Plugin&lt;/strong&gt;:

&lt;ul&gt;
&lt;li&gt;Go to the &lt;strong&gt;"Available"&lt;/strong&gt; tab.&lt;/li&gt;
&lt;li&gt;In the &lt;strong&gt;"Filter"&lt;/strong&gt; search box, type &lt;strong&gt;"Slack Notification"&lt;/strong&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2i7bu52iomwyt641veu9.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2i7bu52iomwyt641veu9.png" alt="Slack Notif" width="800" height="784"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Check the box next to &lt;strong&gt;"Slack Notification Plugin"&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;Click &lt;strong&gt;"Install without restart"&lt;/strong&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Wait for Installation&lt;/strong&gt;:

&lt;ul&gt;
&lt;li&gt;The plugin will download and install. Wait until you see a confirmation message.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;




&lt;p&gt;&lt;a&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  2. Creating a Slack App and Obtaining Credentials
&lt;/h2&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Why This Step?&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Creating a Slack App and obtaining an OAuth token allows Jenkins to authenticate with Slack and send messages to your channels.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Step-by-Step Guide&lt;/strong&gt;
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Go to Your Slack Workspace&lt;/strong&gt;:

&lt;ul&gt;
&lt;li&gt;Click on the dropdown arrow besides your Slack workspace name and select &lt;strong&gt;"Tool &amp;amp; Settings"&lt;/strong&gt; and then &lt;strong&gt;"Manage Apps"&lt;/strong&gt; next.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fo97ez4rru2g7edlo21gn.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fo97ez4rru2g7edlo21gn.png" alt="Manage Apps" width="800" height="409"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Add Jenkins App&lt;/strong&gt;:

&lt;ul&gt;
&lt;li&gt;On the &lt;strong&gt;"Instaled Apps"&lt;/strong&gt; window that follows, enter Jenkins CI in the &lt;strong&gt;"Search Slack Marketplace"&lt;/strong&gt; search bar.&lt;/li&gt;
&lt;li&gt;In the window that follows, click on the pill shaped green button &lt;strong&gt;"Add to Slack"&lt;/strong&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fssstvyjo5cx81omeqa06.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fssstvyjo5cx81omeqa06.png" alt="Slack Marketplace" width="800" height="430"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F1v60we1ig9p8d59owfzn.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F1v60we1ig9p8d59owfzn.png" alt="Add Jenkins" width="800" height="430"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fb4x26xdys2cb1ionqaf5.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fb4x26xdys2cb1ionqaf5.png" alt="Add Jenkins CI" width="800" height="430"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Set Up App Details&lt;/strong&gt;:

&lt;ul&gt;
&lt;li&gt;Follow the setup instructions in the edit configuration window. &lt;/li&gt;
&lt;li&gt;Go to "Manage Jenkins" again in the left navigation in your Jenkins server, then click on "System".&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  3. Configuring Jenkins Global Settings for Slack
&lt;/h2&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Why This Step?&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Configuring Jenkins with your Slack credentials allows it to send notifications to your Slack channels.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Step-by-Step Guide&lt;/strong&gt;
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Access Jenkins Configuration&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;From the Jenkins dashboard, click &lt;strong&gt;"Manage Jenkins"&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;Select &lt;strong&gt;"Configure System"&lt;/strong&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Find Slack Plugin Settings&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Scroll down until the &lt;strong&gt;"Slack"&lt;/strong&gt; settings section (typically at the end of the page).&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Flg8sdcpzmpgducn6077d.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Flg8sdcpzmpgducn6077d.png" alt="Slack Settings" width="800" height="640"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Fill in Slack Configuration&lt;/strong&gt;:

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Workspace&lt;/strong&gt;: Enter your Slack workspace domain (e.g., &lt;code&gt;myworkspace&lt;/code&gt; from &lt;code&gt;myworkspace.slack.com&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Credential&lt;/strong&gt;:

&lt;ul&gt;
&lt;li&gt;Click on the &lt;strong&gt;"+Add"&lt;/strong&gt; button, just beneath the credential field&lt;/li&gt;
&lt;li&gt;Choose &lt;strong&gt;"Global"&lt;/strong&gt; for scope.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Kind&lt;/strong&gt;: Select &lt;strong&gt;"Secret text"&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Secret&lt;/strong&gt;: Paste the &lt;strong&gt;Integration token credential ID&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;ID&lt;/strong&gt;: Name it (e.g., &lt;code&gt;slack-token&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;Click &lt;strong&gt;"Add"&lt;/strong&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fzzltqnemr920glkawgxi.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fzzltqnemr920glkawgxi.png" alt="Slack credentials" width="800" height="640"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Default Channel&lt;/strong&gt;: Enter the Slack channel (e.g., &lt;code&gt;#cicd&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Test Connection&lt;/strong&gt;:

&lt;ul&gt;
&lt;li&gt;Click &lt;strong&gt;"Test Connection"&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;Look for a success message.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F120h021wehx5lmw5ncv2.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F120h021wehx5lmw5ncv2.png" alt="Success Message" width="800" height="870"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Save Configuration&lt;/strong&gt;:

&lt;ul&gt;
&lt;li&gt;Click &lt;strong&gt;"Save"&lt;/strong&gt; at the bottom.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;




&lt;p&gt;&lt;a&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  4. Setting Up a Jenkins Job to Send Slack Notifications
&lt;/h2&gt;

&lt;p&gt;&lt;em&gt;Placeholder for Job Configuration Screenshot&lt;/em&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Why This Step?&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Configuring individual jobs to send notifications ensures that you receive updates for specific builds or projects.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Step-by-Step Guide&lt;/strong&gt;
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Open a Jenkins Job&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Go to the Jenkins dashboard.&lt;/li&gt;
&lt;li&gt;Click on an existing job or create a new one.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Configure the Job&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Click &lt;strong&gt;"Configure"&lt;/strong&gt; on the left.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Enable Slack Notifications&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Scroll to &lt;strong&gt;"Post-build Actions"&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;Click &lt;strong&gt;"Add post-build action"&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;Select &lt;strong&gt;"Slack Notifications"&lt;/strong&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;em&gt;Placeholder for Adding Slack Notifications Screenshot&lt;/em&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Set Notification Preferences&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Check the boxes for when you want notifications (e.g., &lt;strong&gt;"Notify Success"&lt;/strong&gt;, &lt;strong&gt;"Notify Failure"&lt;/strong&gt;).&lt;/li&gt;
&lt;li&gt;Optionally, click &lt;strong&gt;"Advanced..."&lt;/strong&gt; to specify a different channel.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;em&gt;Placeholder for Slack Notification Settings Screenshot&lt;/em&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Save the Job Configuration&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Click &lt;strong&gt;"Save"&lt;/strong&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;




&lt;p&gt;&lt;a&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  5. Testing the Integration
&lt;/h2&gt;

&lt;p&gt;&lt;em&gt;Placeholder for Build Now Screenshot&lt;/em&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Why This Step?&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Testing ensures that your setup works correctly and that notifications are received in Slack.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Step-by-Step Guide&lt;/strong&gt;
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Run the Jenkins Job&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Go to the job page.&lt;/li&gt;
&lt;li&gt;Click &lt;strong&gt;"Build Now"&lt;/strong&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Check Slack Channel&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Open Slack and navigate to your channel.&lt;/li&gt;
&lt;li&gt;Look for notifications about the build.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;em&gt;Placeholder for Slack Notification Screenshot&lt;/em&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Verify the Notification&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Ensure the notification shows the correct build status and details.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;




&lt;p&gt;&lt;a&gt;&lt;/a&gt;&lt;/p&gt;

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

&lt;p&gt;By connecting Jenkins to Slack, you've enhanced your development workflow. Installing Jenkins locally allows you to experiment and learn, while Slack integration keeps your team informed in real-time.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Key Benefits&lt;/strong&gt;
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Immediate Awareness&lt;/strong&gt;: Instant notifications about builds help quickly address issues.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Enhanced Collaboration&lt;/strong&gt;: Teams stay aligned and can discuss problems directly in Slack.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Improved Efficiency&lt;/strong&gt;: Automated updates reduce the need for manual checks.&lt;/li&gt;
&lt;/ul&gt;




&lt;p&gt;&lt;strong&gt;Happy Building and Collaborating!&lt;/strong&gt;&lt;/p&gt;




</description>
      <category>jenkins</category>
      <category>cicd</category>
      <category>devops</category>
      <category>productivity</category>
    </item>
    <item>
      <title>Deploying a Fullstack Application with Monitoring: A Comprehensive Guide</title>
      <dc:creator>John Doe</dc:creator>
      <pubDate>Thu, 28 Nov 2024 15:49:53 +0000</pubDate>
      <link>https://dev.to/gideonisbuilding/deploying-a-fullstack-application-with-monitoring-a-comprehensive-guide-38f4</link>
      <guid>https://dev.to/gideonisbuilding/deploying-a-fullstack-application-with-monitoring-a-comprehensive-guide-38f4</guid>
      <description>&lt;p&gt;In this article, we will walk through deploying a fullstack application (frontend, backend, and database) and setting up a monitoring stack using &lt;strong&gt;Prometheus&lt;/strong&gt;, &lt;strong&gt;Grafana&lt;/strong&gt;, and &lt;strong&gt;cAdvisor&lt;/strong&gt;. The goal is to simplify the process so even beginners can follow along and understand the purpose of each step.&lt;/p&gt;




&lt;h3&gt;
  
  
  &lt;strong&gt;Overview&lt;/strong&gt;
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Fullstack Application Deployment&lt;/strong&gt;: Deploy a frontend, backend, and database with Docker and Docker Compose.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Monitoring Stack Setup&lt;/strong&gt;: Integrate monitoring tools to track application and server performance.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;NGINX Proxy Manager&lt;/strong&gt;: Use it for routing traffic, enabling SSL, and managing domain redirections.&lt;/li&gt;
&lt;/ul&gt;




&lt;h3&gt;
  
  
  &lt;strong&gt;1. Prerequisites&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Before starting, ensure you have the following installed on your server or local machine:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Docker&lt;/strong&gt;: To containerize and run applications.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Docker Compose&lt;/strong&gt;: To manage multi-container setups.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;A Domain Name&lt;/strong&gt;: For accessing your application and monitoring stack (e.g., &lt;code&gt;example.com&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Basic Linux Skills&lt;/strong&gt;: Ability to use the terminal for commands.&lt;/li&gt;
&lt;/ol&gt;




&lt;h3&gt;
  
  
  &lt;strong&gt;2. Setting Up the File Structure&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Here’s how your project folder should look:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;project/
├── backend/          # Contains the backend application
├── frontend/         # Contains the frontend application
├── monitoring/       # Contains configurations for Prometheus, Promtail, and Loki
├── docker-compose.yml
└── README.md
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Backend&lt;/strong&gt;: API service logic (e.g., Node.js, Python).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Frontend&lt;/strong&gt;: UI served via NGINX.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Monitoring&lt;/strong&gt;: Monitoring tools (Prometheus, Grafana, etc.).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;docker-compose.yml&lt;/strong&gt;: Defines all services for deployment.&lt;/li&gt;
&lt;/ul&gt;




&lt;h3&gt;
  
  
  &lt;strong&gt;3. Writing the &lt;code&gt;docker-compose.yml&lt;/code&gt;&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;The &lt;code&gt;docker-compose.yml&lt;/code&gt; file combines all the services into one deployable stack.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;version&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;3.8'&lt;/span&gt;

&lt;span class="na"&gt;services&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;backend&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;build&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;context&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;./backend&lt;/span&gt;
      &lt;span class="na"&gt;dockerfile&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Dockerfile&lt;/span&gt;
    &lt;span class="na"&gt;container_name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;backend&lt;/span&gt;
    &lt;span class="na"&gt;ports&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;8000:8000"&lt;/span&gt;
    &lt;span class="na"&gt;networks&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;app-network&lt;/span&gt;
    &lt;span class="na"&gt;depends_on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;db&lt;/span&gt;

  &lt;span class="na"&gt;frontend&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;build&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;context&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;./frontend&lt;/span&gt;
      &lt;span class="na"&gt;dockerfile&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Dockerfile&lt;/span&gt;
    &lt;span class="na"&gt;container_name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;frontend&lt;/span&gt;
    &lt;span class="na"&gt;ports&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;5173:80"&lt;/span&gt;
    &lt;span class="na"&gt;networks&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;app-network&lt;/span&gt;

  &lt;span class="na"&gt;db&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;image&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;postgres:14&lt;/span&gt;
    &lt;span class="na"&gt;container_name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;db&lt;/span&gt;
    &lt;span class="na"&gt;volumes&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;db-data:/var/lib/postgresql/data&lt;/span&gt;
    &lt;span class="na"&gt;environment&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;POSTGRES_USER&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;appuser&lt;/span&gt;
      &lt;span class="na"&gt;POSTGRES_PASSWORD&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;password123&lt;/span&gt;
      &lt;span class="na"&gt;POSTGRES_DB&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;appdb&lt;/span&gt;
    &lt;span class="na"&gt;networks&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;app-network&lt;/span&gt;

  &lt;span class="na"&gt;prometheus&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;image&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;prom/prometheus&lt;/span&gt;
    &lt;span class="na"&gt;container_name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;prometheus&lt;/span&gt;
    &lt;span class="na"&gt;command&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;--config.file=/etc/prometheus/prometheus.yml'&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;--web.external-url=http://localhost/prometheus'&lt;/span&gt;
    &lt;span class="na"&gt;ports&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;9090:9090"&lt;/span&gt;
    &lt;span class="na"&gt;volumes&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;./monitoring/prometheus.yml:/etc/prometheus/prometheus.yml&lt;/span&gt;
    &lt;span class="na"&gt;networks&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;app-network&lt;/span&gt;

  &lt;span class="na"&gt;grafana&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;image&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;grafana/grafana&lt;/span&gt;
    &lt;span class="na"&gt;container_name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;grafana&lt;/span&gt;
    &lt;span class="na"&gt;environment&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;GF_SERVER_ROOT_URL=http://localhost/grafana&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;GF_SERVER_SERVE_FROM_SUB_PATH=true&lt;/span&gt;
    &lt;span class="na"&gt;ports&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;3000:3000"&lt;/span&gt;
    &lt;span class="na"&gt;volumes&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;grafana-data:/var/lib/grafana&lt;/span&gt;
    &lt;span class="na"&gt;networks&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;app-network&lt;/span&gt;

  &lt;span class="na"&gt;cadvisor&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;image&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;gcr.io/cadvisor/cadvisor:latest&lt;/span&gt;
    &lt;span class="na"&gt;container_name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;cadvisor&lt;/span&gt;
    &lt;span class="na"&gt;ports&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;8083:8080"&lt;/span&gt;
    &lt;span class="na"&gt;volumes&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;/:/rootfs:ro&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;/var/run:/var/run:rw&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;/sys:/sys:ro&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;/var/lib/docker/:/var/lib/docker:ro&lt;/span&gt;
    &lt;span class="na"&gt;networks&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;app-network&lt;/span&gt;

&lt;span class="na"&gt;volumes&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;db-data&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;grafana-data&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;

&lt;span class="na"&gt;networks&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;app-network&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;driver&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;bridge&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h3&gt;
  
  
  &lt;strong&gt;4. Configuring the Monitoring Tools&lt;/strong&gt;
&lt;/h3&gt;

&lt;h4&gt;
  
  
  &lt;strong&gt;4.1 Prometheus Configuration&lt;/strong&gt;
&lt;/h4&gt;

&lt;p&gt;Prometheus scrapes metrics from services like cAdvisor. Add a &lt;code&gt;prometheus.yml&lt;/code&gt; file in the &lt;code&gt;monitoring&lt;/code&gt; folder.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;global&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;scrape_interval&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;15s&lt;/span&gt;

&lt;span class="na"&gt;scrape_configs&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;job_name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;prometheus"&lt;/span&gt;
    &lt;span class="na"&gt;static_configs&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;targets&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;localhost:9090"&lt;/span&gt;&lt;span class="pi"&gt;]&lt;/span&gt;

  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;job_name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;cadvisor"&lt;/span&gt;
    &lt;span class="na"&gt;static_configs&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;targets&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;cadvisor:8080"&lt;/span&gt;&lt;span class="pi"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  &lt;strong&gt;4.2 Grafana Configuration&lt;/strong&gt;
&lt;/h4&gt;

&lt;p&gt;Grafana uses Prometheus as a data source. Configure dashboards by:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Starting Grafana (&lt;code&gt;http://localhost:3000&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;Logging in (default: admin/admin).&lt;/li&gt;
&lt;li&gt;Adding Prometheus as a data source (&lt;code&gt;http://prometheus:9090&lt;/code&gt;).&lt;/li&gt;
&lt;/ol&gt;




&lt;h3&gt;
  
  
  &lt;strong&gt;5. Deploying the Fullstack Application&lt;/strong&gt;
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Build and Start Services&lt;/strong&gt;:
Run the following command to start all services:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;   docker-compose up &lt;span class="nt"&gt;-d&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Access the Services&lt;/strong&gt;:

&lt;ul&gt;
&lt;li&gt;Backend: &lt;code&gt;http://localhost:8000&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Frontend: &lt;code&gt;http://localhost:5173&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Prometheus: &lt;code&gt;http://localhost:9090&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Grafana: &lt;code&gt;http://localhost:3000&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;cAdvisor: &lt;code&gt;http://localhost:8083&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;




&lt;h3&gt;
  
  
  &lt;strong&gt;6. Setting Up NGINX Proxy Manager&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;NGINX Proxy Manager provides routing, HTTPS, and domain management.&lt;/p&gt;

&lt;h4&gt;
  
  
  &lt;strong&gt;6.1 Installation&lt;/strong&gt;
&lt;/h4&gt;

&lt;p&gt;Install NGINX Proxy Manager as a Docker container:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;services&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;proxy&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;image&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;jc21/nginx-proxy-manager:latest'&lt;/span&gt;
    &lt;span class="na"&gt;ports&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;80:80"&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;443:443"&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;81:81"&lt;/span&gt;
    &lt;span class="na"&gt;volumes&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;./data:/data&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;./letsencrypt:/etc/letsencrypt&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Run &lt;code&gt;docker-compose up -d&lt;/code&gt; to start the proxy manager.&lt;/p&gt;

&lt;h4&gt;
  
  
  &lt;strong&gt;6.2 Configuring Proxy Hosts&lt;/strong&gt;
&lt;/h4&gt;

&lt;ol&gt;
&lt;li&gt;Log in to NGINX Proxy Manager (&lt;code&gt;http://&amp;lt;your-server-ip&amp;gt;:81&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Add a Proxy Host for each service:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Domain&lt;/strong&gt;: &lt;code&gt;example.com&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Forward Hostname&lt;/strong&gt;: Container name (e.g., &lt;code&gt;frontend&lt;/code&gt;, &lt;code&gt;backend&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Forward Port&lt;/strong&gt;: Port of the service (e.g., &lt;code&gt;8000&lt;/code&gt; for the backend).&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Enable &lt;strong&gt;Force SSL&lt;/strong&gt; and request a Let's Encrypt certificate.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;




&lt;h3&gt;
  
  
  &lt;strong&gt;7. Testing and Debugging&lt;/strong&gt;
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Logs&lt;/strong&gt;:
Check logs for errors:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;   docker logs &amp;lt;container-name&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Network&lt;/strong&gt;:&lt;br&gt;
Ensure containers can communicate via &lt;code&gt;docker network inspect app-network&lt;/code&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;DNS&lt;/strong&gt;:&lt;br&gt;
Verify domain resolves to the server IP using:&lt;br&gt;
&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;   nslookup example.com
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h3&gt;
  
  
  &lt;strong&gt;8. Enhancements&lt;/strong&gt;
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Add Alerting&lt;/strong&gt;:
Integrate Alertmanager with Prometheus for alert notifications.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Expand Monitoring&lt;/strong&gt;:
Use Node Exporter to monitor the host system.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Automate Deployment&lt;/strong&gt;:
Use CI/CD pipelines to deploy updates automatically.&lt;/li&gt;
&lt;/ul&gt;




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

&lt;p&gt;This guide covered deploying a fullstack application with a monitoring stack and routing traffic using NGINX Proxy Manager. With Docker Compose, the process is streamlined, and tools like Prometheus and Grafana ensure your application is monitored effectively. Let me know if you need further assistance! 😊&lt;/p&gt;

</description>
      <category>monitoring</category>
      <category>react</category>
      <category>fastapi</category>
      <category>docker</category>
    </item>
    <item>
      <title>How to Install Jenkins on a Local Windows Machine</title>
      <dc:creator>John Doe</dc:creator>
      <pubDate>Thu, 28 Nov 2024 15:46:01 +0000</pubDate>
      <link>https://dev.to/gideonisbuilding/how-to-jenkins-on-a-local-windows-machine-2iho</link>
      <guid>https://dev.to/gideonisbuilding/how-to-jenkins-on-a-local-windows-machine-2iho</guid>
      <description>&lt;p&gt;Jenkins is an open-source automation server that enables developers to build, test, and deploy their software reliably. It plays a pivotal role in the DevOps lifecycle by automating tasks, facilitating continuous integration and continuous delivery (CI/CD), and improving collaboration among development teams.&lt;/p&gt;

&lt;p&gt;Installing Jenkins on your local Windows machine allows you to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Experiment with Jenkins features without affecting a production environment.&lt;/li&gt;
&lt;li&gt;Develop and test CI/CD pipelines locally.&lt;/li&gt;
&lt;li&gt;Gain hands-on experience with DevOps practices.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This guide will walk you through two methods to install Jenkins on Windows:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Using Docker (Recommended)&lt;/li&gt;
&lt;li&gt;Using Windows Subsystem for Linux (WSL)&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;We'll compare both methods and explain why using Docker is the better choice.&lt;/p&gt;

&lt;h2&gt;
  
  
  Method 1: Installing Jenkins Using Docker
&lt;/h2&gt;

&lt;p&gt;&lt;em&gt;Placeholder for Docker and Jenkins Logos&lt;/em&gt;&lt;/p&gt;

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

&lt;ul&gt;
&lt;li&gt;Windows 10 or later&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Docker Desktop&lt;/strong&gt; installed on your machine&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Steps to Install Jenkins with Docker
&lt;/h3&gt;

&lt;h4&gt;
  
  
  Step 1: Install Docker Desktop
&lt;/h4&gt;

&lt;p&gt;If you haven't installed Docker Desktop:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Download Docker Desktop&lt;/strong&gt; from the &lt;a href="https://www.docker.com/products/docker-desktop/" rel="noopener noreferrer"&gt;official website&lt;/a&gt;. &lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fjpj6g7q0ulgirfyueazl.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fjpj6g7q0ulgirfyueazl.png" alt="Docker Desktop Download Page" width="800" height="615"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Check the architecture of your Windows machine (x86_64 or Arm). Here's a &lt;a href="https://medium.com/@kv2023/how-to-check-if-your-linux-is-arm64-or-x86-architecture-f0cd817fb266" rel="noopener noreferrer"&gt;medium article&lt;/a&gt; that helps.&lt;/li&gt;
&lt;li&gt;After a successful download, run the installer and follow the on-screen instructions.&lt;/li&gt;
&lt;li&gt;After installation, launch Docker Desktop and ensure it's running.&lt;/li&gt;
&lt;/ol&gt;

&lt;h4&gt;
  
  
  Step 2: Pull the Jenkins Docker Image
&lt;/h4&gt;

&lt;p&gt;Open &lt;strong&gt;Command Prompt&lt;/strong&gt; or &lt;strong&gt;PowerShell&lt;/strong&gt; and run:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker pull jenkins/jenkins:lts
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This command downloads the latest stable (LTS) Jenkins image.&lt;/p&gt;

&lt;h4&gt;
  
  
  Step 3: Run Jenkins Container
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker run &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-p&lt;/span&gt; 8080:8080 &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-p&lt;/span&gt; 50000:50000 &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-v&lt;/span&gt; jenkins_home:/var/jenkins_home &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-v&lt;/span&gt; /var/run/docker.sock:/var/run/docker.sock &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-v&lt;/span&gt; &lt;span class="si"&gt;$(&lt;/span&gt;which docker&lt;span class="si"&gt;)&lt;/span&gt;:/usr/bin/docker &lt;span class="se"&gt;\&lt;/span&gt;
  jenkins/jenkins:lts
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fq9yo1c7nqzcvjurhanvj.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fq9yo1c7nqzcvjurhanvj.png" alt="Docker Run Command Execution" width="800" height="298"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;docker run&lt;/code&gt;: This is the Docker command used to create and run a new container from a specified image.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;-p 8080:8080&lt;/code&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Purpose&lt;/strong&gt;: Maps port &lt;strong&gt;8080&lt;/strong&gt; of the &lt;strong&gt;host&lt;/strong&gt; machine to port &lt;strong&gt;8080&lt;/strong&gt; of the &lt;strong&gt;container&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Explanation&lt;/strong&gt;: Jenkins uses port 8080 as its default web interface port. This mapping allows you to access the Jenkins web UI via &lt;code&gt;http://localhost:8080&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

&lt;p&gt;&lt;code&gt;-p 50000:50000&lt;/code&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Purpose&lt;/strong&gt;: Maps port &lt;strong&gt;50000&lt;/strong&gt; of the &lt;strong&gt;host&lt;/strong&gt; to port &lt;strong&gt;50000&lt;/strong&gt; of the &lt;strong&gt;container&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Explanation&lt;/strong&gt;: Port 50000 is used by Jenkins for communication with build agents (JNLP agents). This mapping enables distributed builds and agent connections.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

&lt;p&gt;&lt;code&gt;-d&lt;/code&gt; :&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Purpose&lt;/strong&gt;: Runs the container in &lt;strong&gt;detached mode&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Explanation&lt;/strong&gt;: The container runs in the background, allowing you to continue using the terminal for other commands.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

&lt;p&gt;&lt;code&gt;-v jenkins_home:/var/jenkins_home&lt;/code&gt; :&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Purpose&lt;/strong&gt;: Mounts the Docker volume &lt;strong&gt;&lt;code&gt;jenkins_home&lt;/code&gt;&lt;/strong&gt; to the container's &lt;strong&gt;&lt;code&gt;/var/jenkins_home&lt;/code&gt;&lt;/strong&gt; directory.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Explanation&lt;/strong&gt;:

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Data Persistence&lt;/strong&gt;: Jenkins stores its configuration, plugins, and job data in &lt;code&gt;/var/jenkins_home&lt;/code&gt;. Mounting a volume ensures that this data persists across container restarts or recreations.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Named Volume&lt;/strong&gt;: Using &lt;code&gt;jenkins_home&lt;/code&gt; as a named volume allows Docker to manage the volume, and it can be reused or backed up easily.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;/li&gt;

&lt;li&gt;

&lt;p&gt;&lt;code&gt;-v /var/run/docker.sock:/var/run/docker.sock&lt;/code&gt; :&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Purpose&lt;/strong&gt;: Mounts the Docker daemon socket from the &lt;strong&gt;host&lt;/strong&gt; into the &lt;strong&gt;container&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Explanation&lt;/strong&gt;:

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Docker Control&lt;/strong&gt;: By mounting the Docker socket, Jenkins running inside the container can communicate with the Docker daemon on the host.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Use Case&lt;/strong&gt;: This is essential if you want Jenkins to build Docker images or manage Docker containers as part of your CI/CD pipelines.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;/li&gt;

&lt;li&gt;

&lt;p&gt;&lt;code&gt;-v $(which docker):/usr/bin/docker&lt;/code&gt; :&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Purpose&lt;/strong&gt;: Mounts the Docker executable from the &lt;strong&gt;host&lt;/strong&gt; into the &lt;strong&gt;container&lt;/strong&gt; at &lt;strong&gt;&lt;code&gt;/usr/bin/docker&lt;/code&gt;&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Explanation&lt;/strong&gt;:

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Docker CLI Access&lt;/strong&gt;: This makes the Docker command-line tool (&lt;code&gt;docker&lt;/code&gt;) available inside the Jenkins container.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Version Consistency&lt;/strong&gt;: Ensures that the Docker CLI inside the container matches the version installed on the host, avoiding compatibility issues.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;/li&gt;

&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Note&lt;/strong&gt;: &lt;code&gt;$(which docker)&lt;/code&gt; is a command substitution that returns the path of the Docker executable on the host system.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;jenkins/jenkins:lts&lt;/code&gt; :

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Purpose&lt;/strong&gt;: Specifies the Docker image to use, in this case, the &lt;strong&gt;Jenkins Long-Term Support (LTS)&lt;/strong&gt; version.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Explanation&lt;/strong&gt;:

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Stable Version&lt;/strong&gt;: Using the LTS version ensures you are running a stable and well-supported release of Jenkins.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Image Source&lt;/strong&gt;: The image &lt;code&gt;jenkins/jenkins:lts&lt;/code&gt; is maintained by the Jenkins project on Docker Hub.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;/li&gt;

&lt;/ul&gt;




&lt;h3&gt;
  
  
  &lt;strong&gt;Summary of the Command's Purpose&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;This Docker command sets up a Jenkins server in a container with the capability to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Persist data through the &lt;code&gt;jenkins_home&lt;/code&gt; volume.&lt;/li&gt;
&lt;li&gt;Be accessible via the web interface on &lt;code&gt;localhost:8080&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Communicate with build agents through port 50000.&lt;/li&gt;
&lt;li&gt;Interact with Docker on the host machine to build images and manage containers from within Jenkins jobs.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Why Mount Docker Socket and Executable?&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;By mounting both the Docker socket and executable:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Docker Socket (&lt;code&gt;/var/run/docker.sock&lt;/code&gt;)&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Grants the container access to the Docker daemon running on the host.&lt;/li&gt;
&lt;li&gt;Allows Jenkins to execute Docker commands that affect the host's Docker environment.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

&lt;p&gt;&lt;strong&gt;Docker Executable (&lt;code&gt;/usr/bin/docker&lt;/code&gt;)&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Provides the &lt;code&gt;docker&lt;/code&gt; CLI inside the container.&lt;/li&gt;
&lt;li&gt;Ensures Jenkins can run Docker commands as if it were on the host.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;p&gt;This setup is commonly used when you need Jenkins to perform Docker-related tasks, such as:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Building Docker images.&lt;/li&gt;
&lt;li&gt;Running Docker containers.&lt;/li&gt;
&lt;li&gt;Managing Docker registries.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Security Considerations&lt;/strong&gt;
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Privileges&lt;/strong&gt;: Mounting the Docker socket and executable gives the Jenkins container elevated permissions over the host's Docker daemon.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Risk&lt;/strong&gt;: If the Jenkins server or any of its jobs are compromised, malicious commands could be executed on the host.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Mitigation&lt;/strong&gt;:

&lt;ul&gt;
&lt;li&gt;Limit access to the Jenkins server.&lt;/li&gt;
&lt;li&gt;Use proper authentication and authorization within Jenkins.&lt;/li&gt;
&lt;li&gt;Consider using Docker-in-Docker or Docker agents with limited permissions for additional isolation.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Alternative Approaches&lt;/strong&gt;
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Docker-in-Docker (&lt;code&gt;dind&lt;/code&gt;)&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Run a separate Docker daemon inside the container.&lt;/li&gt;
&lt;li&gt;Adds complexity and potential performance overhead.&lt;/li&gt;
&lt;li&gt;Provides better isolation from the host's Docker daemon.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

&lt;p&gt;&lt;strong&gt;Docker Agents&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Use separate Docker containers as build agents.&lt;/li&gt;
&lt;li&gt;Avoids giving the main Jenkins container direct access to the host's Docker daemon.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Example Usage in a Jenkins Pipeline&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;With this setup, you can create Jenkins pipelines that include steps like:&lt;br&gt;
&lt;/p&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="n"&gt;any&lt;/span&gt;
    &lt;span class="n"&gt;stages&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;stage&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'Build Docker Image'&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;steps&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
                &lt;span class="n"&gt;sh&lt;/span&gt; &lt;span class="s1"&gt;'sudo docker build -t my-image .'&lt;/span&gt;
            &lt;span class="o"&gt;}&lt;/span&gt;
        &lt;span class="o"&gt;}&lt;/span&gt;
        &lt;span class="n"&gt;stage&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'Run Docker Container'&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;steps&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
                &lt;span class="n"&gt;sh&lt;/span&gt; &lt;span class="s1"&gt;'sudo docker run -d --name my-container my-image'&lt;/span&gt;
            &lt;span class="o"&gt;}&lt;/span&gt;
        &lt;span class="o"&gt;}&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This pipeline builds a Docker image and runs a container using the Docker commands available inside the Jenkins container.&lt;/p&gt;

&lt;h4&gt;
  
  
  Step 4: Access Jenkins Web Interface
&lt;/h4&gt;

&lt;ol&gt;
&lt;li&gt;Open a web browser and navigate to &lt;code&gt;http://localhost:8080&lt;/code&gt;.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fe9325xxr70a1rpfm1tgu.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fe9325xxr70a1rpfm1tgu.png" alt="Jenkins Unlock Screen" width="800" height="841"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;You'll see the "Unlock Jenkins" screen. Retrieve the initial admin password by checking the Docker container logs or reading the &lt;code&gt;initialAdminPassword&lt;/code&gt; file:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;   docker &lt;span class="nb"&gt;exec&lt;/span&gt; &lt;span class="nt"&gt;-it&lt;/span&gt; &amp;lt;container_id&amp;gt; &lt;span class="nb"&gt;cat&lt;/span&gt; /var/jenkins_home/secrets/initialAdminPassword
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;em&gt;Placeholder for Screenshot of Command to Retrieve Password&lt;/em&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Copy the password, paste it into the web interface, and proceed with the setup.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Install suggested plugins or customize as needed.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Create your first admin user, and you're ready to use Jenkins!&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;




&lt;h4&gt;
  
  
  Advantages of Using Docker
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Portability&lt;/strong&gt;: Docker containers can run on any machine with Docker installed.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Isolation&lt;/strong&gt;: Each container is isolated, preventing conflicts with other applications.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Ease of Setup&lt;/strong&gt;: Simplifies the installation process with minimal configuration.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Consistency&lt;/strong&gt;: Ensures the environment is consistent across different setups.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Easy Cleanup&lt;/strong&gt;: Containers can be stopped and removed without leaving residual files.&lt;/li&gt;
&lt;/ul&gt;




&lt;p&gt;To allow the Jenkins user inside the Docker container to run Docker commands without needing to prefix them with &lt;code&gt;sudo&lt;/code&gt;. This involves adding the Jenkins user to the Docker group inside the container.&lt;/p&gt;

&lt;p&gt;Here's how you can do it:&lt;/p&gt;




&lt;h3&gt;
  
  
  &lt;strong&gt;Allowing Jenkins to Run Docker Commands Without &lt;code&gt;sudo&lt;/code&gt;&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;By default, Docker commands require root privileges. To enable the Jenkins user inside the container to execute Docker commands without &lt;code&gt;sudo&lt;/code&gt;, you need to add the Jenkins user to the Docker group. Here's how to do it:&lt;/p&gt;

&lt;h4&gt;
  
  
  &lt;strong&gt;Step 1: Access the Running Jenkins Container as Root&lt;/strong&gt;
&lt;/h4&gt;

&lt;p&gt;First, you'll need to access the running Jenkins container with root privileges. You can do this using the &lt;code&gt;docker exec&lt;/code&gt; command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker &lt;span class="nb"&gt;exec&lt;/span&gt; &lt;span class="nt"&gt;-u&lt;/span&gt; 0 &lt;span class="nt"&gt;-it&lt;/span&gt; &amp;lt;container-name&amp;gt; bash
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;docker exec&lt;/code&gt;: Runs a command in a running container.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;-u 0&lt;/code&gt;: Specifies the user ID to execute the command as. &lt;code&gt;0&lt;/code&gt; is the user ID for &lt;code&gt;root&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;-it&lt;/code&gt;: Allocates a pseudo-TTY and keeps STDIN open, allowing you to interact with the container's shell.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;&amp;lt;container-name&amp;gt;&lt;/code&gt;: Replace this with the actual name or ID of your Jenkins container.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;bash&lt;/code&gt;: The command to run, in this case, starting a Bash shell.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Example&lt;/strong&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker &lt;span class="nb"&gt;exec&lt;/span&gt; &lt;span class="nt"&gt;-u&lt;/span&gt; 0 &lt;span class="nt"&gt;-it&lt;/span&gt; jenkins-container bash
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;em&gt;Note: Replace &lt;code&gt;jenkins-container&lt;/code&gt; with your container's actual name or ID.&lt;/em&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  &lt;strong&gt;Step 2: Add Jenkins User to the Docker Group&lt;/strong&gt;
&lt;/h4&gt;

&lt;p&gt;Once inside the container as the root user, execute the following commands:&lt;/p&gt;

&lt;h5&gt;
  
  
  &lt;strong&gt;Check if the Docker Group Exists&lt;/strong&gt;
&lt;/h5&gt;

&lt;p&gt;First, verify whether the &lt;code&gt;docker&lt;/code&gt; group exists inside the container:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;grep&lt;/span&gt; &lt;span class="nt"&gt;-i&lt;/span&gt; docker /etc/group
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;If it doesn't exist, create it:
&lt;/li&gt;
&lt;/ul&gt;

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

&lt;/div&gt;



&lt;h5&gt;
  
  
  &lt;strong&gt;Add Jenkins User to the Docker Group&lt;/strong&gt;
&lt;/h5&gt;

&lt;p&gt;Now, add the &lt;code&gt;jenkins&lt;/code&gt; user to the &lt;code&gt;docker&lt;/code&gt; group:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;usermod &lt;span class="nt"&gt;-aG&lt;/span&gt; docker jenkins
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;usermod&lt;/code&gt;: A command to modify a user's settings.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;-aG docker&lt;/code&gt;: Appends the user to the &lt;code&gt;docker&lt;/code&gt; group.&lt;/li&gt;
&lt;/ul&gt;

&lt;h5&gt;
  
  
  &lt;strong&gt;Verify the User's Group Membership&lt;/strong&gt;
&lt;/h5&gt;

&lt;p&gt;You can verify that the &lt;code&gt;jenkins&lt;/code&gt; user is now part of the &lt;code&gt;docker&lt;/code&gt; group:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;groups &lt;/span&gt;jenkins
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You should see &lt;code&gt;docker&lt;/code&gt; listed among the groups.&lt;/p&gt;

&lt;h4&gt;
  
  
  &lt;strong&gt;Step 3: Exit and Restart the Container&lt;/strong&gt;
&lt;/h4&gt;

&lt;p&gt;For the group membership changes to take effect, you need to restart the Jenkins container:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Exit the container shell&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;exit&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Restart the container&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;   docker restart &amp;lt;container-name&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Example&lt;/strong&gt;:&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;



&lt;h4&gt;
  
  
  &lt;strong&gt;Step 4: Test Docker Commands in Jenkins&lt;/strong&gt;
&lt;/h4&gt;

&lt;p&gt;Now, inside your Jenkins jobs or pipelines, you should be able to run Docker commands without needing &lt;code&gt;sudo&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Example Pipeline Step&lt;/strong&gt;:&lt;br&gt;
&lt;/p&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="n"&gt;any&lt;/span&gt;
    &lt;span class="n"&gt;stages&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;stage&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'Test Docker Command'&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;steps&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
                &lt;span class="n"&gt;sh&lt;/span&gt; &lt;span class="s1"&gt;'docker ps'&lt;/span&gt;
            &lt;span class="o"&gt;}&lt;/span&gt;
        &lt;span class="o"&gt;}&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This pipeline stage will list running Docker containers, and it should execute without permission errors.&lt;/p&gt;




&lt;h3&gt;
  
  
  &lt;strong&gt;Why These Steps Are Necessary&lt;/strong&gt;
&lt;/h3&gt;

&lt;h4&gt;
  
  
  &lt;strong&gt;Understanding User Permissions&lt;/strong&gt;
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Docker Daemon Access&lt;/strong&gt;: The Docker daemon (&lt;code&gt;dockerd&lt;/code&gt;) listens on a Unix socket (&lt;code&gt;/var/run/docker.sock&lt;/code&gt;) by default. Access to this socket is controlled by Unix file permissions.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Docker Group&lt;/strong&gt;: Users who are members of the &lt;code&gt;docker&lt;/code&gt; group can interact with the Docker daemon without &lt;code&gt;sudo&lt;/code&gt;, as the socket is owned by the &lt;code&gt;docker&lt;/code&gt; group.&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  &lt;strong&gt;Security Considerations&lt;/strong&gt;
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Root Privileges&lt;/strong&gt;: Granting access to the Docker daemon is equivalent to giving root access, as Docker commands can affect the host system.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Caution Advised&lt;/strong&gt;: Ensure that only trusted users and processes have this access.&lt;/li&gt;
&lt;/ul&gt;




&lt;h3&gt;
  
  
  &lt;strong&gt;Important Notes&lt;/strong&gt;
&lt;/h3&gt;

&lt;h4&gt;
  
  
  &lt;strong&gt;1. Security Implications&lt;/strong&gt;
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Risk of Privilege Escalation&lt;/strong&gt;: Users with access to the Docker daemon can gain root-level access to the host.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Best Practices&lt;/strong&gt;:

&lt;ul&gt;
&lt;li&gt;Limit access to the Jenkins interface.&lt;/li&gt;
&lt;li&gt;Secure your Jenkins jobs to prevent arbitrary code execution.&lt;/li&gt;
&lt;li&gt;Regularly update Jenkins and its plugins to patch security vulnerabilities.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;h4&gt;
  
  
  &lt;strong&gt;2. Alternatives to Adding Jenkins User to Docker Group&lt;/strong&gt;
&lt;/h4&gt;

&lt;p&gt;If security is a major concern, consider the following alternatives:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Docker-in-Docker (DinD)&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Run a separate Docker daemon inside the Jenkins container.&lt;/li&gt;
&lt;li&gt;Isolate Docker operations from the host.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Cons&lt;/strong&gt;: More complex setup, potential performance overhead.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

&lt;p&gt;&lt;strong&gt;Use Docker Agents&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Instead of running Docker commands on the Jenkins master, use agents (nodes) that have Docker installed and configured.&lt;/li&gt;
&lt;li&gt;Assign jobs that require Docker to these agents.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Pros&lt;/strong&gt;: Better isolation, easier to manage permissions.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

&lt;p&gt;&lt;strong&gt;Use Pipeline Plugins&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Utilize plugins like the &lt;strong&gt;Docker Pipeline&lt;/strong&gt; plugin, which provides DSL for building and running containers.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Pros&lt;/strong&gt;: Abstracts Docker operations, can improve security.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;h4&gt;
  
  
  &lt;strong&gt;3. Ensure Consistent Docker Versions&lt;/strong&gt;
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;Since you're mounting the Docker executable and socket from the host, make sure that the versions are compatible with the Jenkins environment inside the container.&lt;/li&gt;
&lt;li&gt;Incompatibilities can lead to unexpected behavior or errors.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Method 2: Installing Jenkins on Windows Subsystem for Linux (WSL)
&lt;/h2&gt;

&lt;p&gt;&lt;em&gt;Placeholder for WSL and Jenkins Logos&lt;/em&gt;&lt;/p&gt;

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

&lt;ul&gt;
&lt;li&gt;Windows 10 Version 2004 or higher&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Windows Subsystem for Linux (WSL)&lt;/strong&gt; enabled&lt;/li&gt;
&lt;li&gt;A Linux distribution installed (e.g., Ubuntu from Microsoft Store)&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Steps to Install Jenkins on WSL
&lt;/h3&gt;

&lt;h4&gt;
  
  
  Step 1: Enable WSL
&lt;/h4&gt;

&lt;ol&gt;
&lt;li&gt;Open &lt;strong&gt;PowerShell&lt;/strong&gt; as Administrator.&lt;/li&gt;
&lt;li&gt;Run:
&lt;/li&gt;
&lt;/ol&gt;

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

&lt;/div&gt;



&lt;p&gt;&lt;em&gt;Placeholder for Screenshot of WSL Installation Command&lt;/em&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Restart your computer if prompted.&lt;/li&gt;
&lt;/ol&gt;

&lt;h4&gt;
  
  
  Step 2: Install a Linux Distribution
&lt;/h4&gt;

&lt;ol&gt;
&lt;li&gt;Open the &lt;strong&gt;Microsoft Store&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;Search for &lt;strong&gt;Ubuntu&lt;/strong&gt; and install it.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;em&gt;Placeholder for Screenshot of Ubuntu in Microsoft Store&lt;/em&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Launch Ubuntu from the Start menu.&lt;/li&gt;
&lt;/ol&gt;

&lt;h4&gt;
  
  
  Step 3: Update Linux Packages
&lt;/h4&gt;

&lt;p&gt;In the Ubuntu terminal, run:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;apt update
&lt;span class="nb"&gt;sudo &lt;/span&gt;apt upgrade &lt;span class="nt"&gt;-y&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;em&gt;Placeholder for Screenshot of Package Update Commands&lt;/em&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  Step 4: Install Java
&lt;/h4&gt;

&lt;p&gt;Jenkins requires Java. Install it using:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;apt &lt;span class="nb"&gt;install &lt;/span&gt;openjdk-21-jre &lt;span class="nt"&gt;-y&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;em&gt;Placeholder for Screenshot of Java Installation Command&lt;/em&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  Step 5: Add Jenkins Repository and Key
&lt;/h4&gt;

&lt;ol&gt;
&lt;li&gt;Add the Jenkins Debian repository key:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;   wget &lt;span class="nt"&gt;-q&lt;/span&gt; &lt;span class="nt"&gt;-O&lt;/span&gt; - https://pkg.jenkins.io/debian-stable/jenkins.io.key | &lt;span class="nb"&gt;sudo &lt;/span&gt;apt-key add -
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;Add the repository to the sources list:
&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;sh &lt;span class="nt"&gt;-c&lt;/span&gt; &lt;span class="s1"&gt;'echo deb https://pkg.jenkins.io/debian-stable binary/ &amp;gt; /etc/apt/sources.list.d/jenkins.list'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;em&gt;Placeholder for Screenshot of Adding Jenkins Repository&lt;/em&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  Step 6: Install Jenkins
&lt;/h4&gt;

&lt;p&gt;Update packages and install Jenkins:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;apt update
&lt;span class="nb"&gt;sudo &lt;/span&gt;apt &lt;span class="nb"&gt;install &lt;/span&gt;jenkins &lt;span class="nt"&gt;-y&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;em&gt;Placeholder for Screenshot of Jenkins Installation Command&lt;/em&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  Step 7: Start Jenkins Service
&lt;/h4&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;service jenkins start
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Verify Jenkins is running:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;service jenkins status
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;em&gt;Placeholder for Screenshot of Jenkins Service Status&lt;/em&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  Step 8: Access Jenkins Web Interface
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;Open a web browser and navigate to &lt;code&gt;http://localhost:8080&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;em&gt;Placeholder for Screenshot of Jenkins Unlock Screen via WSL&lt;/em&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Retrieve the initial admin password:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;cat&lt;/span&gt; /var/lib/jenkins/secrets/initialAdminPassword
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Continue with the setup as described in the Docker method.&lt;/li&gt;
&lt;/ul&gt;




&lt;h3&gt;
  
  
  Advantages of Using WSL
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Linux Environment&lt;/strong&gt;: Provides a genuine Linux environment on Windows.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Direct Access&lt;/strong&gt;: Ability to use Linux commands and tools directly.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Integration&lt;/strong&gt;: Seamless integration between Windows and Linux file systems.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Why Docker is the Better Method
&lt;/h2&gt;

&lt;p&gt;While both methods allow you to run Jenkins locally, using Docker has several advantages over WSL:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Simplified Setup&lt;/strong&gt;: Docker requires fewer steps and configurations.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Resource Efficiency&lt;/strong&gt;: Docker containers are lightweight compared to running a full Linux distribution in WSL.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Isolation&lt;/strong&gt;: Docker provides better isolation, reducing potential conflicts.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Consistency Across Environments&lt;/strong&gt;: Docker ensures that the Jenkins instance behaves the same across different systems.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Easier Maintenance&lt;/strong&gt;: Updating or removing Jenkins is straightforward with Docker commands.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Portability&lt;/strong&gt;: Docker images can be easily shared and deployed on other machines or servers.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;In contrast, WSL may present challenges such as networking configurations, potential performance overhead, and a more complex setup process.&lt;/p&gt;




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

&lt;p&gt;Installing Jenkins locally on your Windows machine empowers you to develop and test CI/CD pipelines in a controlled environment. While both Docker and WSL methods are viable, Docker offers a more streamlined, efficient, and beginner-friendly approach.&lt;/p&gt;

&lt;p&gt;By leveraging Jenkins in your DevOps cycle, you can:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Automate repetitive tasks.&lt;/li&gt;
&lt;li&gt;Enhance collaboration between development and operations teams.&lt;/li&gt;
&lt;li&gt;Accelerate software delivery.&lt;/li&gt;
&lt;li&gt;Improve code quality through continuous integration and testing.&lt;/li&gt;
&lt;/ul&gt;




&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fox3kc2t4yoekd5luk6o2.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fox3kc2t4yoekd5luk6o2.png" alt="Jenkins Dashboard Screenshot" width="800" height="849"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;Happy Building with Jenkins!&lt;/strong&gt;&lt;/p&gt;

</description>
      <category>devops</category>
      <category>jenkins</category>
      <category>cicd</category>
    </item>
    <item>
      <title>How to Automate User and Group Creation and Management Using a Simple Bash Script</title>
      <dc:creator>John Doe</dc:creator>
      <pubDate>Wed, 03 Jul 2024 19:23:17 +0000</pubDate>
      <link>https://dev.to/gideonisbuilding/how-to-automate-user-and-group-creation-and-management-using-a-simple-bash-script-1321</link>
      <guid>https://dev.to/gideonisbuilding/how-to-automate-user-and-group-creation-and-management-using-a-simple-bash-script-1321</guid>
      <description>&lt;p&gt;One of the telling signs someone's a DevOps engineer is their unrivaled urge to automate process. It isn't just for automation sake, but to:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Enhance productivity&lt;/li&gt;
&lt;li&gt;Reduce human error&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;One such task is onboarding new developers to the team. This includes creating user accounts, assigning them to appropriate groups, and setting secure passwords. &lt;/p&gt;

&lt;p&gt;This article will walk you how you can streamline this process using a bash script. You don't have to be a pro at this, it shows you why each step is important.&lt;/p&gt;

&lt;p&gt;What does this script do?&lt;br&gt;
The script automates the following tasks:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Prompts the user for the path to an employee configuration file.&lt;/li&gt;
&lt;li&gt;Validates the provided file path.&lt;/li&gt;
&lt;li&gt;Creates necessary directories and sets appropriate permissions.&lt;/li&gt;
&lt;li&gt;Checks for and installs the &lt;code&gt;makepasswd&lt;/code&gt; tool if not already present.&lt;/li&gt;
&lt;li&gt;Generates secure passwords for new users.&lt;/li&gt;
&lt;li&gt;Creates user accounts and assigns them to specified groups.&lt;/li&gt;
&lt;li&gt;Logs all actions for auditing purposes.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Let's break down each section of the script.&lt;/p&gt;
&lt;h2&gt;
  
  
  Color-Coded Output Functions
&lt;/h2&gt;


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

#--------------------------
# Function to echo in green
#--------------------------
green_echo() {
    echo -e "\e[32m$1\e[0m"
}

#------------------------
# Function to echo in red
#------------------------
red_echo() {
    echo -e "\e[31m$1\e[0m"
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;These functions, &lt;code&gt;green_echo&lt;/code&gt; and &lt;code&gt;red_echo&lt;/code&gt;, are used to print messages in green and red. The idea is to help you differentiate between successful and error messages, making your script's output more readable. Typically, output messages from running scripts are in white (against the set background of your terminal) making it difficult to see errors among the sea of output messages. Red and green-codded outputs make it easier to scan your script output.&lt;/p&gt;
&lt;h2&gt;
  
  
  Checking if a File Argument Was Provided
&lt;/h2&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;#---------------------------------------------------------&lt;/span&gt;
&lt;span class="c"&gt;# Check if a file path argument is provided and validate it&lt;/span&gt;
&lt;span class="c"&gt;#---------------------------------------------------------&lt;/span&gt;
&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt; &lt;span class="nt"&gt;-z&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="o"&gt;]&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then
    &lt;/span&gt;red_echo &lt;span class="s2"&gt;"Error: No file path provided. Please provide the employee config file path as the first argument."&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;EMPLOYEE_CONFIG_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;$EMPLOYEE_CONFIG_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;red_echo &lt;span class="s2"&gt;"Error: The file '&lt;/span&gt;&lt;span class="nv"&gt;$EMPLOYEE_CONFIG_FILE&lt;/span&gt;&lt;span class="s2"&gt;' does not exist or is not a regular file."&lt;/span&gt;
    &lt;span class="nb"&gt;exit &lt;/span&gt;1
&lt;span class="k"&gt;fi

&lt;/span&gt;green_echo &lt;span class="s2"&gt;"File path is valid."&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;This portion of the script confirms the argument the user attaches to the script is a valid file and exists. If the file path is invalid, it will prompt the user to try again, ensuring an argument is provided and it exists before proceeding.&lt;/p&gt;
&lt;h2&gt;
  
  
  Defining File Paths
&lt;/h2&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;#-----------------------------------------&lt;/span&gt;
&lt;span class="c"&gt;# Variables for the password and log files&lt;/span&gt;
&lt;span class="c"&gt;#-----------------------------------------&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="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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;These variables define the paths for storing generated passwords and logs. It is standard DevOps practice to store passwords in a file. And for even better practice, ensures these files are secure and only readable by appropriate personnel. &lt;/p&gt;

&lt;p&gt;Another standard practice is logging actions. It helps you in auditing and troubleshooting should you be stuck. Defining the variables for the paths to these files early on makes it easier to maintain the script. &lt;/p&gt;
&lt;h2&gt;
  
  
  Creating and Securing Directories
&lt;/h2&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;#----------------------------------------------------------&lt;/span&gt;
&lt;span class="c"&gt;# Create necessary directories with appropriate permissions&lt;/span&gt;
&lt;span class="c"&gt;#----------------------------------------------------------&lt;/span&gt;
&lt;span class="nb"&gt;sudo mkdir&lt;/span&gt; &lt;span class="nt"&gt;-p&lt;/span&gt; /var/secure
&lt;span class="nb"&gt;sudo mkdir&lt;/span&gt; &lt;span class="nt"&gt;-p&lt;/span&gt; /var/log
&lt;span class="nb"&gt;sudo chmod &lt;/span&gt;600 /var/secure
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;This script block creates the directories to the files for storing passwords and logs if they do not already exist. It also sets strict permissions (&lt;code&gt;chmod 600&lt;/code&gt;) on the &lt;code&gt;/var/secure&lt;/code&gt; directory so that only the user can read and write to it, enhancing security.&lt;/p&gt;
&lt;h2&gt;
  
  
  Ensuring &lt;code&gt;makepasswd&lt;/code&gt; is Installed
&lt;/h2&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;#----------------------------------------------&lt;/span&gt;
&lt;span class="c"&gt;# Checking and ensuring makepasswd is installed&lt;/span&gt;
&lt;span class="c"&gt;#----------------------------------------------&lt;/span&gt;
&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt; &lt;span class="nb"&gt;command&lt;/span&gt; &lt;span class="nt"&gt;-v&lt;/span&gt; makepasswd &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;sudo &lt;/span&gt;apt-get update &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nb"&gt;sudo &lt;/span&gt;apt-get &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-y&lt;/span&gt; makepasswd
&lt;span class="k"&gt;fi&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;&lt;code&gt;makepasswd&lt;/code&gt; is a tool used to generate random passwords. It doesn't come preinstalled in most Linux/Unix systems. So, you'd have to check if it is installed before moving on to other parts. This block checks if &lt;code&gt;makepasswd&lt;/code&gt; is installed and installs it if necessary. Ensuring this dependency is met is crucial for the script to function correctly.&lt;/p&gt;
&lt;h2&gt;
  
  
  Password Generation Function
&lt;/h2&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;#--------------------------------------------&lt;/span&gt;
&lt;span class="c"&gt;# Generate a random password of 16 characters&lt;/span&gt;
&lt;span class="c"&gt;#--------------------------------------------&lt;/span&gt;
generate_password&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    makepasswd &lt;span class="nt"&gt;--chars&lt;/span&gt; 16
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;This function uses &lt;code&gt;makepasswd&lt;/code&gt; to generate a random password of 16 characters. Strong passwords are essential for security, and automating their generation helps maintain consistency and complexity.&lt;/p&gt;
&lt;h2&gt;
  
  
  Clearing Previous Logs and Passwords
&lt;/h2&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;#--------------------------------------&lt;/span&gt;
&lt;span class="c"&gt;# Clear previous log and password files&lt;/span&gt;
&lt;span class="c"&gt;#--------------------------------------&lt;/span&gt;
&lt;span class="nb"&gt;sudo truncate&lt;/span&gt; &lt;span class="nt"&gt;-s&lt;/span&gt; 0 &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;sudo truncate&lt;/span&gt; &lt;span class="nt"&gt;-s&lt;/span&gt; 0 &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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Before starting the onboarding process, the script clears previous log and password files. This ensures that the new run starts with clean files, preventing confusion with old data.&lt;/p&gt;

&lt;p&gt;Note that if you use &lt;code&gt;echo "" | sudo tee "$LOGFILE" &amp;gt; /dev/null&lt;/code&gt; or &lt;code&gt;echo "" | sudo tee "$PASSWORD_FILE" &amp;gt; /dev/null&lt;/code&gt; instead, what you get instead will be a file with an empty line. Any lines appended to the file will begin from the next line, leaving an empty first line. Using truncate sets the file to whatever size you specify. And in this case, it's zero bytes which effectively clears the file"&lt;/p&gt;
&lt;h2&gt;
  
  
  Reading and Processing the Configuration File
&lt;/h2&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="k"&gt;while &lt;/span&gt;&lt;span class="nv"&gt;IFS&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;';'&lt;/span&gt; &lt;span class="nb"&gt;read&lt;/span&gt; &lt;span class="nt"&gt;-r&lt;/span&gt; username &lt;span class="nb"&gt;groups&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;

    &lt;span class="c"&gt;#----------------------------------------&lt;/span&gt;
    &lt;span class="c"&gt;# Remove leading and trailing whitespaces&lt;/span&gt;
    &lt;span class="c"&gt;#----------------------------------------&lt;/span&gt;
    &lt;span class="nv"&gt;username&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;$username&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; | xargs&lt;span class="si"&gt;)&lt;/span&gt;
    &lt;span class="nb"&gt;groups&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;$groups&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; | xargs&lt;span class="si"&gt;)&lt;/span&gt;

    &lt;span class="c"&gt;#-----------------&lt;/span&gt;
    &lt;span class="c"&gt;# Skip empty lines&lt;/span&gt;
    &lt;span class="c"&gt;#-----------------&lt;/span&gt;
    &lt;span class="o"&gt;[&lt;/span&gt; &lt;span class="nt"&gt;-z&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$username&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="o"&gt;]&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="k"&gt;continue&lt;/span&gt;

    &lt;span class="c"&gt;#---------------------------------&lt;/span&gt;
    &lt;span class="c"&gt;# Split the groups field by commas&lt;/span&gt;
    &lt;span class="c"&gt;#---------------------------------&lt;/span&gt;
    &lt;span class="nv"&gt;IFS&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;','&lt;/span&gt; &lt;span class="nb"&gt;read&lt;/span&gt; &lt;span class="nt"&gt;-ra&lt;/span&gt; group_array &lt;span class="o"&gt;&amp;lt;&amp;lt;&amp;lt;&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$groups&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 reads the configuration file line by line, splitting each line into a username and groups. It goes further to remove any leading or trailing whitespace to ensure clean data processing. There's the added contingency to skip empty lines to prevent errors.&lt;/p&gt;
&lt;h2&gt;
  
  
  Creating Users and Setting Passwords
&lt;/h2&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;    &lt;span class="c"&gt;#---------------------------------&lt;/span&gt;
    &lt;span class="c"&gt;# Check if the user already exists&lt;/span&gt;
    &lt;span class="c"&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;$username&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;red_echo &lt;span class="s2"&gt;"The user &lt;/span&gt;&lt;span class="nv"&gt;$username&lt;/span&gt;&lt;span class="s2"&gt; already exists."&lt;/span&gt; | &lt;span class="nb"&gt;sudo 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;sudo &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;$username&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt;
            green_echo &lt;span class="s2"&gt;"The user &lt;/span&gt;&lt;span class="nv"&gt;$username&lt;/span&gt;&lt;span class="s2"&gt; has been created."&lt;/span&gt; | &lt;span class="nb"&gt;sudo 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="c"&gt;#---------------------------&lt;/span&gt;
        &lt;span class="c"&gt;# Generate a random password&lt;/span&gt;
        &lt;span class="c"&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;generate_password&lt;span class="si"&gt;)&lt;/span&gt;

        &lt;span class="c"&gt;#------------------------&lt;/span&gt;
        &lt;span class="c"&gt;# Set the user's password&lt;/span&gt;
        &lt;span class="c"&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;$username&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="nb"&gt;sudo &lt;/span&gt;chpasswd
        &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$username&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="nb"&gt;sudo 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;$PASSWORD_FILE&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
    &lt;span class="k"&gt;fi&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;This block checks if the user already exists. If the user does not exist, it creates the user with a home directory and Bash shell. A random password is generated and set for the user. The username and password are logged for record-keeping.&lt;/p&gt;
&lt;h2&gt;
  
  
  Creating Primary Groups
&lt;/h2&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;    &lt;span class="c"&gt;#--------------------------------------------------------&lt;/span&gt;
    &lt;span class="c"&gt;# Create a primary group for the user if it doesn't exist&lt;/span&gt;
    &lt;span class="c"&gt;#--------------------------------------------------------&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt; getent group &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$username&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&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;sudo &lt;/span&gt;groupadd &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$username&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt;
            green_echo &lt;span class="s2"&gt;"Primary group &lt;/span&gt;&lt;span class="nv"&gt;$username&lt;/span&gt;&lt;span class="s2"&gt; created."&lt;/span&gt; | &lt;span class="nb"&gt;sudo 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;fi&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;For each new user, the script checks if a primary group with the same name exists. If not, it creates the group. This ensures that each user has a corresponding group, which is a common practice in Unix-like systems.&lt;/p&gt;
&lt;h2&gt;
  
  
  Assigning Users to Additional Groups
&lt;/h2&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;group &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;group_array&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="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;do
        if&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt; getent group &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="o"&gt;&amp;gt;&lt;/span&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;sudo &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="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt;
                green_echo &lt;span class="s2"&gt;"Group &lt;/span&gt;&lt;span class="nv"&gt;$group&lt;/span&gt;&lt;span class="s2"&gt; created."&lt;/span&gt; | &lt;span class="nb"&gt;sudo 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;fi
        &lt;/span&gt;&lt;span class="nb"&gt;sudo &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;$username&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt;
            green_echo &lt;span class="s2"&gt;"User &lt;/span&gt;&lt;span class="nv"&gt;$username&lt;/span&gt;&lt;span class="s2"&gt; added to 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;sudo 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&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;The script processes each group specified for the user. It checks if the group exists and creates it if necessary. It then adds the user to each group, ensuring they have the required permissions and access.&lt;/p&gt;
&lt;h2&gt;
  
  
  Setting Home Directory Permissions
&lt;/h2&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;    &lt;span class="c"&gt;#-------------------------------&lt;/span&gt;
    &lt;span class="c"&gt;# Set home directory permissions&lt;/span&gt;
    &lt;span class="c"&gt;#-------------------------------&lt;/span&gt;
    &lt;span class="nb"&gt;sudo chown&lt;/span&gt; &lt;span class="nt"&gt;-R&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$username&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;:&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$username&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="s2"&gt;"/home/&lt;/span&gt;&lt;span class="nv"&gt;$username&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
    &lt;span class="nb"&gt;sudo chmod &lt;/span&gt;700 &lt;span class="s2"&gt;"/home/&lt;/span&gt;&lt;span class="nv"&gt;$username&lt;/span&gt;&lt;span class="s2"&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;$EMPLOYEE_CONFIG_FILE&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;

green_echo &lt;span class="s2"&gt;"User onboarding script completed. See &lt;/span&gt;&lt;span class="nv"&gt;$LOG_FILE&lt;/span&gt;&lt;span class="s2"&gt; for details."&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Finally, the script sets the ownership and permissions for the user's home directory. This ensures that the user has the necessary access to their files while also securing the directory from unauthorized access.&lt;/p&gt;

&lt;p&gt;To run the script, make it executable.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;chmod&lt;/span&gt; +x create_users.sh
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then execute it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;./create_users.sh new_developers.txt
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;So the script runs as intended, ensure that the file the script reads is written and formatted this way (username to the left of the semi-colon and user groups to the right):&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;The assumption behind this example is that a user can have multiple groups, each group delimited by a comma ",".&lt;/p&gt;

&lt;p&gt;Here's the &lt;a href="https://github.com/GideonIsBuilding/hng-task_01" rel="noopener noreferrer"&gt;link to the GitHub repo&lt;/a&gt; if you want to take a look at it closely.&lt;/p&gt;

&lt;h1&gt;
  
  
  Final Words...
&lt;/h1&gt;

&lt;p&gt;When you automate the user onboarding process with a Bash script ensures consistency, accuracy, and security. By following the steps outlined in this article, you can streamline the creation of user accounts, assignment of groups, and setting of secure passwords, all while maintaining detailed logs for auditing purposes. &lt;/p&gt;

&lt;p&gt;To improve the security of the script, you can:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Hash the passwords after generation&lt;/li&gt;
&lt;li&gt;Configure the script to send each employee their login details to their emails&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Tweak and improve as desired. &lt;/p&gt;

&lt;p&gt;Looking for projects like this to help you better understand DevOps concepts, enroll for &lt;a href="https://hng.tech/internship" rel="noopener noreferrer"&gt;HNG Internship&lt;/a&gt;. If you are already a professional looking for a community of professionals to collaborate with and have recruiters review your resumes, then opt for the &lt;a href="https://hng.tech/premium" rel="noopener noreferrer"&gt;HNG Premium&lt;/a&gt; package.&lt;/p&gt;

</description>
      <category>linux</category>
      <category>devops</category>
      <category>learning</category>
    </item>
  </channel>
</rss>
