<?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: rsc</title>
    <description>The latest articles on DEV Community by rsc (@rsc).</description>
    <link>https://dev.to/rsc</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%2F708719%2Fa743c378-0330-48fa-a060-83722f590ecc.jpeg</url>
      <title>DEV Community: rsc</title>
      <link>https://dev.to/rsc</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/rsc"/>
    <language>en</language>
    <item>
      <title>Hosting your static website in a linux virtual machine</title>
      <dc:creator>rsc</dc:creator>
      <pubDate>Wed, 30 Nov 2022 10:16:56 +0000</pubDate>
      <link>https://dev.to/rsc/hosting-your-static-website-in-a-linux-virtual-machine-19n4</link>
      <guid>https://dev.to/rsc/hosting-your-static-website-in-a-linux-virtual-machine-19n4</guid>
      <description>&lt;p&gt;To host a website on a linux virtual machine is fairly simple. The website hosted will be available on the internet publicly as long as our Linux virtual machine is running. &lt;br&gt;
In this tutorial, we'll be hosting a HTML template from tooplate.com, feel free to use your custom made HTML documents.&lt;/p&gt;
&lt;h2&gt;
  
  
  Prerequisites
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Vagrant&lt;/strong&gt;: This tutorial assumes a working knowledge of vagrant and how to automate creating virtual machines using &lt;code&gt;Vagrantfile&lt;/code&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Step 1. Create a virtual machine
&lt;/h2&gt;
&lt;h3&gt;
  
  
  Creating an ubuntu virtual machine
&lt;/h3&gt;

&lt;p&gt;We'll be using &lt;code&gt;spox/ubuntu-arm&lt;/code&gt; box image to setup our ubuntu virtual machine.&lt;/p&gt;

&lt;p&gt;Navigate to your project directory and create the &lt;code&gt;Vagrantfile&lt;/code&gt; with the following command.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;vagrant init spox/ubuntu-arm
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;or copy and paste the &lt;code&gt;Vagrantfile&lt;/code&gt; below.&lt;/p&gt;

&lt;p&gt;Now, the &lt;code&gt;Vagrantfile&lt;/code&gt; is created and can be edited through vim editor.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;vim Vagrantfile
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# -*- mode: ruby -*-
# vi: set ft=ruby :

# All Vagrant configuration is done below. The "2" in Vagrant.configure
# configures the configuration version (we support older styles for
# backwards compatibility). Please don't change it unless you know what
# you're doing.
Vagrant.configure("2") do |config|
  # The most common configuration options are documented and commented below.
  # For a complete reference, please see the online documentation at
  # https://docs.vagrantup.com.

  # Every Vagrant development environment requires a box. You can search for
  # boxes at https://vagrantcloud.com/search.
  config.vm.box = "spox/ubuntu-arm"

  # Disable automatic box update checking. If you disable this, then
  # boxes will only be checked for updates when the user runs
  # `vagrant box outdated`. This is not recommended.
  # config.vm.box_check_update = false

  # Create a forwarded port mapping which allows access to a specific port
  # within the machine from a port on the host machine. In the example below,
  # accessing "localhost:8080" will access port 80 on the guest machine.
  # NOTE: This will enable public access to the opened port
  # config.vm.network "forwarded_port", guest: 80, host: 8080

  # Create a forwarded port mapping which allows access to a specific port
  # within the machine from a port on the host machine and only allow access
  # via 127.0.0.1 to disable public access
  # config.vm.network "forwarded_port", guest: 80, host: 8080, host_ip: "127.0.0.1"

  # Create a private network, which allows host-only access to the machine
  # using a specific IP.
  config.vm.network "private_network", ip: "192.168.33.10"

  # Create a public network, which generally matched to bridged network.
  # Bridged networks make the machine appear as another physical device on
  # your network.
  config.vm.network "public_network"

  # Share an additional folder to the guest VM. The first argument is
  # the path on the host to the actual folder. The second argument is
  # the path on the guest to mount the folder. And the optional third
  # argument is a set of non-required options.
  # config.vm.synced_folder "../data", "/vagrant_data"

  # Provider-specific configuration so you can fine-tune various
  # backing providers for Vagrant. These expose provider-specific options.
  # Example for VirtualBox:
  #
  config.vm.provider "virtualbox" do |vb|
  #   # Display the VirtualBox GUI when booting the machine
  #   vb.gui = true
  #
  #   # Customize the amount of memory on the VM:
     vb.memory = "1024"
  end
  #
  # View the documentation for the provider you are using for more
  # information on available options.

  # Enable provisioning with a shell script. Additional provisioners such as
  # Ansible, Chef, Docker, Puppet and Salt are also available. Please see the
  # documentation for more information about their specific syntax and use.
  # config.vm.provision "shell", inline: &amp;lt;&amp;lt;-SHELL
  #   apt-get update
  #   apt-get install -y apache2
  # SHELL
end

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

&lt;/div&gt;



&lt;h3&gt;
  
  
  Creating a centos virtual machine
&lt;/h3&gt;

&lt;p&gt;We'll be using &lt;code&gt;geerlingguy/centos7&lt;/code&gt; box image to setup our cento7 virtual machine.&lt;/p&gt;

&lt;p&gt;PS: For M1 users, I recommend you use &lt;code&gt;jacobw/fedora35-arm64&lt;/code&gt; instead of the above mentioned box image.&lt;/p&gt;

&lt;p&gt;Navigate to your project directory and create the &lt;code&gt;Vagrantfile&lt;/code&gt; with the following command.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;vagrant init geerlingguy/centos7
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, the &lt;code&gt;Vagrantfile&lt;/code&gt; is created and can be edited through vim editor.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;vim Vagrantfile
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;or copy and paste the &lt;code&gt;Vagrantfile&lt;/code&gt; below.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# -*- mode: ruby -*-
# vi: set ft=ruby :

# All Vagrant configuration is done below. The "2" in Vagrant.configure
# configures the configuration version (we support older styles for
# backwards compatibility). Please don't change it unless you know what
# you're doing.
Vagrant.configure("2") do |config|
  # The most common configuration options are documented and commented below.
  # For a complete reference, please see the online documentation at
  # https://docs.vagrantup.com.

  # Every Vagrant development environment requires a box. You can search for
  # boxes at https://vagrantcloud.com/search.
  config.vm.box = "jacobw/fedora35-arm64"

  # Disable automatic box update checking. If you disable this, then
  # boxes will only be checked for updates when the user runs
  # `vagrant box outdated`. This is not recommended.
  # config.vm.box_check_update = false

  # Create a forwarded port mapping which allows access to a specific port
  # within the machine from a port on the host machine. In the example below,
  # accessing "localhost:8080" will access port 80 on the guest machine.
  # NOTE: This will enable public access to the opened port
  # config.vm.network "forwarded_port", guest: 80, host: 8080

  # Create a forwarded port mapping which allows access to a specific port
  # within the machine from a port on the host machine and only allow access
  # via 127.0.0.1 to disable public access
  # config.vm.network "forwarded_port", guest: 80, host: 8080, host_ip: "127.0.0.1"

  # Create a private network, which allows host-only access to the machine
  # using a specific IP.
  config.vm.network "private_network", ip: "192.168.33.10"

  # Create a public network, which generally matched to bridged network.
  # Bridged networks make the machine appear as another physical device on
  # your network.
  config.vm.network "public_network"

  # Share an additional folder to the guest VM. The first argument is
  # the path on the host to the actual folder. The second argument is
  # the path on the guest to mount the folder. And the optional third
  # argument is a set of non-required options.
  # config.vm.synced_folder "../data", "/vagrant_data"

  # Provider-specific configuration so you can fine-tune various
  # backing providers for Vagrant. These expose provider-specific options.
  # Example for VirtualBox:
  #
  config.vm.provider "virtualbox" do |vb|
  #   # Display the VirtualBox GUI when booting the machine
  #   vb.gui = true
  #
  #   # Customize the amount of memory on the VM:
     vb.memory = "1024"
  end
  #
  # View the documentation for the provider you are using for more
  # information on available options.

  # Enable provisioning with a shell script. Additional provisioners such as
  # Ansible, Chef, Docker, Puppet and Salt are also available. Please see the
  # documentation for more information about their specific syntax and use.
  # config.vm.provision "shell", inline: &amp;lt;&amp;lt;-SHELL
  #   apt-get update
  #   apt-get install -y apache2
  # SHELL
end

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

&lt;/div&gt;



&lt;h3&gt;
  
  
  Required components to host the website in our &lt;code&gt;Vagrantfile&lt;/code&gt;
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;IP Address to access the website: &lt;code&gt;config.vm.network "private_network", ip: "192.168.33.10"&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Optional assign a dynamic IP Address to the virtual machine: &lt;code&gt;config.vm.network "public_network"&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Hosting our website might need an extra amount of RAM, other than the default memory provided.
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;config.vm.provider "virtualbox" do |vb|
  #   # Display the VirtualBox GUI when booting the machine
  #   vb.gui = true
  #
  #   # Customize the amount of memory on the VM:
     vb.memory = "1024"
end
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;With the above configuration, we're ready to start the virtual machine.&lt;/p&gt;

&lt;p&gt;Start the VM:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;vagrant up
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Log into the VM:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;vagrant ssh
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To provide the highest level of privilege, we need to login as the root user.&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; &lt;span class="nt"&gt;-i&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Step 2. Installing required packages, inside our VM.
&lt;/h2&gt;

&lt;p&gt;Hosting our packages would require a couple of packages installed in our VM.&lt;/p&gt;

&lt;p&gt;Run the command below, to install of them at once.&lt;/p&gt;

&lt;p&gt;For ubuntu machine;&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;apache2 wget unzip &lt;span class="nt"&gt;-y&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For centos machine;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;yum &lt;span class="nb"&gt;install &lt;/span&gt;httpd wget unzip &lt;span class="nt"&gt;-y&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;P.S. httpd in centos is equivalent apache2 o ubuntu machine.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;httpd&lt;/strong&gt;: Apache web-server that hosts our website in the virtual machine.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;wget&lt;/strong&gt;: An http package to download our template from tooplate.com&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;unzip&lt;/strong&gt;: This package is required because our template will be in &lt;code&gt;.zip&lt;/code&gt; format, and needs to be extracted.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;With the installation complete, the apache2 web-server has been automatically started by ubuntu, &lt;code&gt;systemctl status apach2&lt;/code&gt; to confirm. For centos machines, we can start our service by running the following command &lt;code&gt;systemctl start httpd&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;we could also enable the service, so that it comes up at boot time &lt;code&gt;systemctl enable httpd&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Access the default IP Address assigned to the VM:&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;



&lt;p&gt;result:&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%2Fnqcu2g8ifbn43ymbtxa4.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%2Fnqcu2g8ifbn43ymbtxa4.png" alt="ifconfig result" width="623" height="427"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Access the IP Address in the browser, and the following default web page, would show up.&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%2Faefsl42ld9nhhhibj9rh.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%2Faefsl42ld9nhhhibj9rh.png" alt="Default Apache homepage" width="800" height="481"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Download and extract the html directory into virtual machine.
&lt;/h2&gt;

&lt;p&gt;Server data of our VM is located in the &lt;code&gt;/var/www/html&lt;/code&gt; directory, this is where html files can be saved and served on the browser.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 1. Navigate to &lt;code&gt;/tmp&lt;/code&gt; directory and download the zip file.
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;wget https://www.free-css.com/assets/files/free-css-templates/download/page285/cial.zip
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Step 2. Extract the directory and copy it's content into &lt;code&gt;/var/www/html&lt;/code&gt;.
&lt;/h3&gt;

&lt;p&gt;Extract the document;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;unzip cial.zip &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nb"&gt;cd &lt;/span&gt;html
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Copy the content into &lt;code&gt;/var/www/html&lt;/code&gt;&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 cp&lt;/span&gt; &lt;span class="nt"&gt;-r&lt;/span&gt; &lt;span class="k"&gt;*&lt;/span&gt; /var/www/html
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Restart apache2/httpd and reload the browser
&lt;/h3&gt;



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

&lt;/div&gt;



&lt;p&gt;Reload the browser tab with your VM IP Address.&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%2Fy8dihyfa2a354lb99hle.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%2Fy8dihyfa2a354lb99hle.png" alt="browser reload result" width="800" height="481"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>linux</category>
      <category>containers</category>
      <category>docker</category>
      <category>opensource</category>
    </item>
    <item>
      <title>Introduction to Linux concepts, processes and operations</title>
      <dc:creator>rsc</dc:creator>
      <pubDate>Tue, 06 Sep 2022 09:54:32 +0000</pubDate>
      <link>https://dev.to/rsc/introduction-to-linux-concepts-processes-and-operations-mh</link>
      <guid>https://dev.to/rsc/introduction-to-linux-concepts-processes-and-operations-mh</guid>
      <description>&lt;h2&gt;
  
  
  Outline
&lt;/h2&gt;

&lt;p&gt;By the end of this tutorial, you should be able to;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Understand Linux startup operations and boot processes.&lt;/li&gt;
&lt;li&gt;Identify the differences between partitions and filesystems on a Linux system.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Linux startup operations and boot processes.
&lt;/h2&gt;

&lt;p&gt;The linux boot process is a series of operations involved when initialising the system, it includes all series of steps involved from the power on of the machine, to when the system user interface becomes fully operational.&lt;/p&gt;

&lt;p&gt;The diagram below shows the operations involved in a Linux os boot process.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--A6O0Sn7M--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/hvp4n8hvnjfjbbioumpk.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--A6O0Sn7M--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/hvp4n8hvnjfjbbioumpk.png" alt="Linux-kernel" width="880" height="1193"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  BIOS
&lt;/h3&gt;

&lt;p&gt;The computer BIOS(Basic Input/Output system) checks and initializes all the computer hardware and ensure all of the hardwares are fully operational. This operational of hardware testing is called POST(power on self test).&lt;br&gt;
The BIOS software is stored on a ROM chip, located on the motherboard.&lt;/p&gt;
&lt;h3&gt;
  
  
  Bootloader
&lt;/h3&gt;

&lt;p&gt;The boot loader has two distinct stages:&lt;/p&gt;

&lt;p&gt;For systems using the BIOS/MBR method, the boot loader resides at the first sector of the hard-disk, which is known as the master boot record - MBR.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;For the first stage, the boot loader takes over the boot process, and search for a bootable partition such as GRUB.&lt;/li&gt;
&lt;li&gt;The boot loader loads the Linux kernel into memory(RAM), and turn over execution process to the kernel.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;For systems using the Extensible Firmware Interface(EFI)/Unified Extensible Firmware Interface (UEFI) method:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;For the first stage, the boot loader read its boot manager data, to determine which application is to be launched and from where.&lt;/li&gt;
&lt;li&gt;The firmware launches the application e.g GRUB as defined in the boot manager data&lt;/li&gt;
&lt;/ol&gt;
&lt;h3&gt;
  
  
  User login prompt
&lt;/h3&gt;

&lt;p&gt;The init starts a number of text-mode login prompts. These enables the user type in their username and password, to eventually get a command shell.&lt;/p&gt;
&lt;h3&gt;
  
  
  The linux kernel
&lt;/h3&gt;

&lt;p&gt;The boot loader loads both the kernel and an initial RAM-based file system (&lt;strong&gt;initramfs&lt;/strong&gt;) into the memory so it can be used by the kernel.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--W7nLXLYv--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/lclh1gy4t4cvmanvxg9h.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--W7nLXLYv--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/lclh1gy4t4cvmanvxg9h.png" alt="initramfs" width="854" height="950"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  Initial RAM disk
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;initramfs&lt;/strong&gt; filesystem image contains programs and binary files that perform all actions needed to mount the proper root filesystem and device drivers for mass storage controllers with a facility called &lt;strong&gt;udev&lt;/strong&gt;(user device).&lt;br&gt;
After successful mount of the filesystem, the &lt;strong&gt;mount&lt;/strong&gt; program instructs the operating system of the availability of the filesystem, and assigns a particular mount point to it, in the overall hierarchy of the system.&lt;br&gt;
If this communication/operation is successful, the initramfs program is cleared from the RAM, and the init program (&lt;strong&gt;sbin/init&lt;/strong&gt;) in the root filesystem is executed.&lt;br&gt;
The init programs handles the final mounting and pivoting of the real root file system, needed by the Operating system.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--vYtMNfGZ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/t8xuggksw6h7ua43qxzz.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--vYtMNfGZ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/t8xuggksw6h7ua43qxzz.png" alt="dmesg-content" width="880" height="296"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  sbin/init - parent process
&lt;/h3&gt;

&lt;p&gt;Once the kernel has set up all its hardware and mounted the root file system, the kernel runs &lt;strong&gt;/sbin/init&lt;/strong&gt;, which is the initial process needed to start other processes and get the system running.&lt;br&gt;
Besides starting the system, &lt;strong&gt;init&lt;/strong&gt; is responsible for shutting down the system cleanly.&lt;/p&gt;

&lt;p&gt;The boot process is important in that, it allows the Linux user to intervene at any step and customise/configure the behaviour of the system to suit a specific need.&lt;/p&gt;
&lt;h3&gt;
  
  
  Startup alternatives
&lt;/h3&gt;

&lt;p&gt;The two main startup alternatives developed were;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Upstart&lt;/li&gt;
&lt;li&gt;Systemd&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Systems with &lt;strong&gt;systemd&lt;/strong&gt; start up faster than those with the earlier init methods, because systemd replaces a series of sequential steps with aggressive parallel processing technique, which allows multiple processes to be initiated simultenously.&lt;/p&gt;

&lt;p&gt;With this approach, &lt;strong&gt;/sbin/init&lt;/strong&gt; now points to &lt;strong&gt;/lib/systemd/systemd&lt;/strong&gt; i.e &lt;strong&gt;systemd&lt;/strong&gt; takes over the init process.&lt;/p&gt;

&lt;p&gt;One &lt;strong&gt;systemd&lt;/strong&gt; command is systemctl, which is used for basic service operations in the command line.&lt;br&gt;
The following are a brief description of it's various uses;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Starting, stopping, restarting a service on a currently running system
&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="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;systemctl start|stop|restart mongodb
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;ul&gt;
&lt;li&gt;Enabling or disabling a system service from starting up at system boot
&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;sudo &lt;/span&gt;systemctl &lt;span class="nb"&gt;enable&lt;/span&gt;|disable mongodb
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h3&gt;
  
  
  Boot logs
&lt;/h3&gt;

&lt;p&gt;The boot logs contains all the processes loaded and initialised during the boot process, the boot log information is contained in a file called &lt;code&gt;dmesg&lt;/code&gt; located in the &lt;code&gt;/var/log&lt;/code&gt; directory. The &lt;code&gt;/var/log&lt;/code&gt; directory contains all the log files present on a system. &lt;/p&gt;

&lt;p&gt;To show the content of the dmesg file, run the following command in the terminal;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;dmesg | less
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;or&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;cat /var/log/dmesg
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--B1cUa2Xg--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/qcqfgb0q1otmr80afhir.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--B1cUa2Xg--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/qcqfgb0q1otmr80afhir.png" alt="boot-log" width="880" height="432"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Linux Filesystems
&lt;/h2&gt;

&lt;p&gt;Think of a refrigerator that has multiple shelves and can be used to store various items in an organised manner. The same concept applies to the filesystem, where different computer related data is stored in a human-readable format.&lt;/p&gt;

&lt;h3&gt;
  
  
  Different types of filesystems in Linux
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Conventional disk filesystems e.g ext3, ext4, ntfs etc.&lt;/li&gt;
&lt;li&gt;Flash storage filesystems e.g ubifs, yaffs, etc.&lt;/li&gt;
&lt;li&gt;Special purpose filesystems e.g procfs, sysfs, debugfs, etc.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Partition and Filesystems
&lt;/h3&gt;

&lt;p&gt;A &lt;strong&gt;Partition&lt;/strong&gt; is a section of the hard-disk,  used for specific operations.&lt;/p&gt;

&lt;p&gt;A &lt;strong&gt;Filesystem&lt;/strong&gt; is a method used for storing/finding files in the hard-disk, usually specific to a partition.&lt;/p&gt;

&lt;p&gt;One can think of a partition as a container in which filesystem resides, although filesystem can span across multiple partition and linked together using symbolic link.&lt;/p&gt;

&lt;p&gt;The Linux system stores important files according to a standard layout called the Filesystem Hierarchy Standard (FHS).&lt;br&gt;
Unit OS, uses '/' character to separate paths (unlike windows, which uses '\'), and does not have drive letters e.g E: or C: used in windows OS.&lt;br&gt;
Mounted drives and removable media devices are mounted as directory on the Linux filesystem.&lt;br&gt;
USB drives, CDs and DVDs will show up as mounted on the &lt;code&gt;/run/media/&amp;lt;your username&amp;gt;/disklabel directory or&lt;/code&gt;/media` for older Linux distributions.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--MySVicnb--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/u37ak6tgvlhya1r3juaw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--MySVicnb--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/u37ak6tgvlhya1r3juaw.png" alt="Filesystem-hierarchy" width="880" height="716"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;All Linux filesystem names are case-sensitive, so /boot, /Boot, and /BOOT represent three different directories (or folders).&lt;/p&gt;

&lt;p&gt;To get a feel of how the home directory Filesystem Hierarchy looks like, run the command below;&lt;/p&gt;

&lt;p&gt;&lt;code&gt;&lt;/code&gt;&lt;code&gt;&lt;br&gt;
$ tree -aCd -L 2 /&lt;br&gt;
&lt;/code&gt;&lt;code&gt;&lt;/code&gt;&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Build a dockerized FastAPI application with poetry and gunicorn.</title>
      <dc:creator>rsc</dc:creator>
      <pubDate>Thu, 01 Sep 2022 07:19:42 +0000</pubDate>
      <link>https://dev.to/rsc/build-a-dockerized-fastapi-application-with-poetry-and-gunicorn-23e8</link>
      <guid>https://dev.to/rsc/build-a-dockerized-fastapi-application-with-poetry-and-gunicorn-23e8</guid>
      <description>&lt;h2&gt;
  
  
  Prerequisites
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Python3&lt;/li&gt;
&lt;li&gt;docker&lt;/li&gt;
&lt;li&gt;docker-compose&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Setup FastAPI application
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Why use Poetry for dependency and virtual environment management instead of pip and it's equilvalent python setups
&lt;/h3&gt;

&lt;p&gt;Many developers loved the experience provided by Yarn and Npm in the NodeJS ecosystem. Poetry gives a similar experience to developers in the Python world.&lt;/p&gt;

&lt;p&gt;This tutorial compares the approach used by npm for dependency management with poetry to show some of it's greatest strength and why you should use it.&lt;/p&gt;

&lt;p&gt;Similar to &lt;code&gt;package.json&lt;/code&gt; file in the NodeJS world, poetry uses a file named &lt;code&gt;pyproject.toml&lt;/code&gt; file to specify the configurations for your project, and generates a lockfile automatically to describe the entire dependency tree.&lt;/p&gt;

&lt;p&gt;A &lt;code&gt;pyproject.toml&lt;/code&gt; file looks like this;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--BYDG8dmL--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn.hashnode.com/res/hashnode/image/upload/v1661895935250/AghD4Sgv3.png%2520align%3D%2522left%2522" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--BYDG8dmL--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn.hashnode.com/res/hashnode/image/upload/v1661895935250/AghD4Sgv3.png%2520align%3D%2522left%2522" alt="Screenshot 2022-08-30 at 22.44.58.png" width="" height=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Setting up poetry on your machine
&lt;/h3&gt;

&lt;p&gt;With python installed in your system, you can easily run&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;



&lt;p&gt;For python3&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;



&lt;p&gt;Successful installation can be confirmed with&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;



&lt;h3&gt;
  
  
  App dependencies and virtual environment
&lt;/h3&gt;

&lt;p&gt;With poetry installed, we can start a python application by simply running the following command&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;



&lt;p&gt;and follow the command line prompt.&lt;br&gt;
This command is similar to &lt;code&gt;npm init -y&lt;/code&gt; in the NodeJS ecosystem.&lt;/p&gt;

&lt;p&gt;a &lt;code&gt;pyproject.toml&lt;/code&gt; file should be created where you can add your dependencies (the libraries that you will use during the project).&lt;/p&gt;

&lt;p&gt;Activate the virtual environment with the following command&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;



&lt;p&gt;The last step is to add the dependencies for starting up a FastAPI application.&lt;/p&gt;

&lt;p&gt;Adding a core dependency with poetry is simply done with &lt;code&gt;poetry add [package name&lt;/code&gt;, while adding a dev dependency requires a &lt;code&gt;--dev&lt;/code&gt; flag.&lt;/p&gt;

&lt;p&gt;To begin working on our application, we need fastapi and unicorn as dependencies.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;poetry add fastapi uvicorn[standard] gunicorn
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Starting the application server with uvicorn
&lt;/h3&gt;

&lt;p&gt;Firstly we need to create a new python file called main.py, this file will contain our route and also the app object, which is responsible for instantiating the FastAPI application.&lt;/p&gt;

&lt;p&gt;Finally, we can start the application with the command shown below;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;uvicorn main:app --reload
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now your application is running on &lt;a href="http://127.0.0.1:8000"&gt;http://127.0.0.1:8000&lt;/a&gt; and the good news is: FastAPI is integrated with Swagger, the documentation is automatically generated and you can check it via &lt;a href="http://127.0.0.1:8000/docs"&gt;http://127.0.0.1:8000/docs&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Dockerize the FastAPI application
&lt;/h2&gt;

&lt;p&gt;The first step for creating a docker container is to specify what, how and on which OS we need the application to run, and all these configurations reside in a file named as &lt;code&gt;Dockerfile&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;FROM python:3.10 as python-base
RUN mkdir python_tutorial
WORKDIR  /python_tutorial
COPY /pyproject.toml /python_tutorial
RUN pip3 install poetry
RUN poetry config virtualenvs.create false
RUN poetry install 
COPY . .
CMD ["gunicorn", "-w", "4", "-k", "uvicorn.workers.UvicornWorker", "main:app", "--bind", "0.0.0.0:8000"]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Let’s follow the file, line by line:&lt;/p&gt;

&lt;p&gt;Line 1: Represents the base image (in our case its python), I have specified version 3.10 and  you may change it accordingly(eg 3.9, 3.7, ..etc)&lt;/p&gt;

&lt;p&gt;Line 2: Lets us create a folder named python_tutorial in our container&lt;/p&gt;

&lt;p&gt;Line 3: Sets the created directory as our working directly.(So, all the commands below will be executed w.r.t python_tutorial as our root directory)&lt;/p&gt;

&lt;p&gt;Line 4: Copy the file with the requirements to the application directory. Copy only the file needed to install the app dependencies only, and not the rest of the files in the app directly. As this file doesn’t change often, Docker will detect it and use the cache for this step, enabling the cache for the next step too.&lt;/p&gt;

&lt;p&gt;Line 5: We install poetry so it can be used for dependency management in our app container&lt;/p&gt;

&lt;p&gt;Line 6: We disable virtual environment creation inside the container, as it is only needed on the local machine&lt;/p&gt;

&lt;p&gt;Line 7: We install all required libraries within container.&lt;/p&gt;

&lt;p&gt;Line 8 : Copy all the files. As this has all the code which is what changes most frequently the Docker cache won’t be used for this or any following steps easily. So, it’s important to put this near the end of the Dockerfile, to optimize the container image build times.&lt;/p&gt;

&lt;p&gt;line 9: Exposes our application to use gunicorn for starting the app. setting the worker to 4, and also bind the app port to 8000&lt;/p&gt;

&lt;p&gt;Whoffff!!! Fans self! &lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--szslHw-I--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://cdn.hashnode.com/res/hashnode/image/upload/v1661898603950/nppzJa-OG.gif%2520align%3D%2522left%2522" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--szslHw-I--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://cdn.hashnode.com/res/hashnode/image/upload/v1661898603950/nppzJa-OG.gif%2520align%3D%2522left%2522" alt="fans-self-sweating.gif" width="" height=""&gt;&lt;/a&gt;&lt;br&gt;
I know that's a lot of facts, so let's take a break.😅&lt;/p&gt;

&lt;p&gt;The current structure of our directory looks like this;&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--ggwfrJXm--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn.hashnode.com/res/hashnode/image/upload/v1661899218396/i6TOf9_vQ.png%2520align%3D%2522left%2522" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--ggwfrJXm--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn.hashnode.com/res/hashnode/image/upload/v1661899218396/i6TOf9_vQ.png%2520align%3D%2522left%2522" alt="Screenshot 2022-08-30 at 23.35.12.png" width="" height=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;To elegantly manage our application docker image, we decide to use docker-compose. With docker-compose, we can configure and start multiple Docker containers connected to our application on the same host with a single command, and Hey! it looks cool🫣&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--bO-vv2aV--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://cdn.hashnode.com/res/hashnode/image/upload/v1661899536265/dzZauPiXG.gif%2520align%3D%2522left%2522" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--bO-vv2aV--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://cdn.hashnode.com/res/hashnode/image/upload/v1661899536265/dzZauPiXG.gif%2520align%3D%2522left%2522" alt="cool.gif" width="" height=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now, lets configure docker-compose.yml&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;version: "3"
services:
  api:
    build: .
    image: python_tutorial
    ports:
      - "8000:8000"
    volumes:
      - .:/python_tutorial:ro
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Let's take a look at what's going on in the file;&lt;/p&gt;

&lt;p&gt;Line 1: specifies version of docker-compose.&lt;/p&gt;

&lt;p&gt;Line 3: We set a service named api.&lt;/p&gt;

&lt;p&gt;Line 4 → 5: Specifies the path to Docker file and the tag name respectively.&lt;/p&gt;

&lt;p&gt;Line 6: Specifies port mappings :&lt;/p&gt;

&lt;p&gt;Line 7: sets the bind mount, to allow further changes to the application(development - not necessary in production)&lt;/p&gt;

&lt;p&gt;Line 8: specifies the env file, if present&lt;/p&gt;

&lt;p&gt;and finally run the following command;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;docker-compose up
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And if you are having a good day, you will get the following results on your terminal.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://cdn.hashnode.com/res/hashnode/image/upload/v1661900987252/1JVKz8FCu.png%20align="&gt;Screenshot 2022-08-31 at 00.09.30.png&lt;/a&gt;&lt;/p&gt;

</description>
      <category>docker</category>
      <category>fastapi</category>
      <category>python</category>
      <category>poetry</category>
    </item>
    <item>
      <title>Build a product review sentiment analysis with NestJS</title>
      <dc:creator>rsc</dc:creator>
      <pubDate>Thu, 01 Sep 2022 07:16:24 +0000</pubDate>
      <link>https://dev.to/rsc/build-a-product-review-sentiment-analysis-with-nestjs-169n</link>
      <guid>https://dev.to/rsc/build-a-product-review-sentiment-analysis-with-nestjs-169n</guid>
      <description>&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;In this article, we'll demonstrate how to create a NestJS-based sentiment analysis application that uses natural language processing (NLP) to evaluate text data from user reviews and identify the user's sentiment(reaction).&lt;/p&gt;

&lt;p&gt;Why do companies need sentiment analysis?&lt;/p&gt;

&lt;p&gt;Offering clients what they genuinely want rather than what companies believe they need is what product managers need in order to build a strong product roadmap.&lt;/p&gt;

&lt;p&gt;Sentiment analysis is the automated process that allows product managers to understand users' reviews of their products in an automated fashion.&lt;/p&gt;

&lt;p&gt;The benefits of automated sentiment analysis are given below;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Recognize the pros and cons that customers have with your product.&lt;/li&gt;
&lt;li&gt;Save hundreds of hours of tedious data processing and instead gain 24/7 access to the most recent product analytics automatically.&lt;/li&gt;
&lt;li&gt;Compare the testimonials for your products to those of your rivals'.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Sentiment analysis is done through natural language processing. which is a technology that processes a user's comments on a product in order to derive meaningful and actionable data from them. &lt;/p&gt;

&lt;h2&gt;
  
  
  Prerequisite
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;a href="https://git-scm.com/downloads"&gt;Git&lt;/a&gt; for version control, and source code management.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://nodejs.org/en/download/"&gt;NodeJS&lt;/a&gt; to run our application.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Setting up the application
&lt;/h2&gt;

&lt;p&gt;To get started with setting up a Nest.js application, clone the starter repository i provided on my github account.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;git clone https://github.com/r-scheele/nestjs-sentiment
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Install all of the project's dependencies by changing directories into the newly formed folder.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;cd nestjs-sentiment/ &amp;amp;&amp;amp; npm install ```



Starting the application with;


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

&lt;/div&gt;

&lt;p&gt;npm run start:dev```&lt;br&gt;
&lt;/p&gt;

&lt;p&gt;Now that our application has been successfully set up, let's use NLP to implement the sentiment analysis functionality.&lt;/p&gt;

&lt;p&gt;First, we'll set up Natural, a Node.js package that covers the majority of the NLP algorithms we'll be utilizing for our project. Let's try the following command on our terminal:&lt;/p&gt;

&lt;h2&gt;
  
  
  Controllers
&lt;/h2&gt;

&lt;p&gt;Controllers manage incoming requests and provide the client with response, so it makes sense to start our implementation from here.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// app.controller.ts

import { Body, Controller, Get } from '@nestjs/common';
import { AppService } from './app.service';
import { CreateReviewDto } from './create-review.dto';

@Controller()
export class AppController {
  constructor(private readonly appService: AppService) {}

  @Get('analyze')
  getAnalysis(@Body() analysis: CreateReviewDto) {
    return this.appService.getAnalysis(analysis);
  }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;NestJS provides a @Body() decorator that gives us easy access to the request body, by introducing the concept of a Data Transfer Object (DTO), which is used to define the format of the data sent on the request, and the response.  A DTO could be a class or a typescript interface.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// create-review.dto.ts

import { IsNotEmpty, IsString } from "class-validator";

export class CreateReviewDto {

    @IsString()
    readonly name: string;

    @IsString()
    @IsNotEmpty()
    readonly review: string;
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Class-validator allows the use of decorators to validate the structure and type of the properties on the request object.&lt;/p&gt;

&lt;h2&gt;
  
  
  Nestjs service
&lt;/h2&gt;

&lt;p&gt;The job of a service is to separate the business logic from controllers, making it cleaner and more comfortable to test. With the service, we can analyse user reviews, process it and return the sentient analysis.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// app.service.ts


// @ts-ignore

import { Injectable } from '@nestjs/common';
import { CreateReviewDto } from './create-review.dto';
import aposToLexForm from 'apos-to-lex-form';
import { WordTokenizer } from 'natural';
import SpellCorrector from 'spelling-corrector';
import { removeStopwords } from 'stopword';
import natural from 'natural';

const spellCorrector = new SpellCorrector();
spellCorrector.loadDictionary();

@Injectable()
export class AppService {
  analyzeReview(analysis: CreateReviewDto) {
    // format review
    const formattedReview: string = aposToLexForm(analysis.review)
      .toLowerCase()
      .replace(/[^a-zA-Z\s]+/g, '');

    // Tokenization
    const tokenizer = new WordTokenizer();
    const tokens = tokenizer.tokenize(formattedReview);

    // Correcting spelling errors
    const fixedSpelling = tokens.map((word) =&amp;gt; spellCorrector.correct(word));

    // Removing stop words
    const stopWordsRemoved = removeStopwords(fixedSpelling);

    // Stemming
    const { SentimentAnalyzer, PorterStemmer } = natural;
    const analyzer = new SentimentAnalyzer('English', PorterStemmer, 'afinn');

    // Sentiment analysis
    const sentiment = analyzer.getSentiment(stopWordsRemoved);


    return sentiment;
  }
}

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

&lt;/div&gt;



&lt;p&gt;The analyzeReview() method has a couple of notable sections to be aware of;&lt;/p&gt;

&lt;h3&gt;
  
  
  User review processing
&lt;/h3&gt;

&lt;p&gt;Since the raw data we receive from our user is frequently noisy and probably contains numerous errors, it must be transformed into a format that our NLP system can comprehend and use.&lt;br&gt;
We must translate contractions (such as I'm, you're, etc.) to their standard vocabulary in order to keep uniform structure in our text data (i.e., I am, you are, etc.). We use the previously installed package apos-to-lex-form to accomplish this.&lt;br&gt;
The text data is cleaned up( all non-alphabetical characters and symbols are removed), and converted to lowercase to ensure the sentiment algorithm treats good and GOOD as the same words.&lt;/p&gt;
&lt;h3&gt;
  
  
  Tokenization
&lt;/h3&gt;

&lt;p&gt;This is the procedure for dividing a text into its various insightful parts. A sentence can be thought of as a token of a paragraph, and a word as a token of a sentence.&lt;/p&gt;
&lt;h3&gt;
  
  
  Correcting spelling mistakes
&lt;/h3&gt;

&lt;p&gt;Typographical errors are likely because the product reviews will be manually authored by our consumers. Let's utilize the spelling-corrector package to fix typos before sending our data to our sentiment analysis algorithm. This way, if a user types lov accidentally, our algorithm will receive the correct spelling, love.&lt;/p&gt;
&lt;h3&gt;
  
  
  Removing stop words
&lt;/h3&gt;

&lt;p&gt;The most frequent words in a language are typically stop words, which are eliminated before processing. Stop words contain phrases like but, a, or, and what. Eliminating these words will allow us to concentrate on the crucial keywords because they have no impact on a user's emotion.&lt;/p&gt;
&lt;h3&gt;
  
  
  Stemming
&lt;/h3&gt;

&lt;p&gt;This is a word normalization procedure used in natural language processing (NLP) to return derived or inflected words to their base or root form. For instance, it is assumed that a stemmer algorithm will break down the words "giving," "gave," and "giver" into their basic constituent "give."&lt;/p&gt;
&lt;h3&gt;
  
  
  Sentiment analysis
&lt;/h3&gt;

&lt;p&gt;As soon as the text data reaches the appropriate condition, we may analyze customer reviews using Natural's SentimentAnalyzer.&lt;/p&gt;

&lt;p&gt;The Natural library's sentiment analysis system is based on a lexicon that gives words polarities. For instance, the polarity of the word "good" is 3, while the polarity of the word "evil" is -3. The algorithm calculates the sentiment by adding up the polarity of each word in a passage of text and normalizing with sentence length.&lt;/p&gt;

&lt;p&gt;To get a more accurate result, preparing the data and eliminating all the noise was an essential step.&lt;br&gt;
If our algorithm returns a negative value, The statement/word is regarded negative; if it returns a positive value, it is considered positive; and if it returns zero, it is deemed neutral.&lt;/p&gt;

&lt;p&gt;The SentimentAnalyzer constructor has three parameters:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;The language of the text data&lt;/li&gt;
&lt;li&gt;The stemmer&lt;/li&gt;
&lt;li&gt;The vocabulary (currently supports AFINN, Senticon, and Pattern) - we're using afinn in this example, because it's the simplest, yet most popular lexicon used for sentiment analysis&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The completed version of this project can be found in my github profile;&lt;br&gt;
clone the repository with&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git clone &lt;span class="nt"&gt;-b&lt;/span&gt; project-end https://github.com/r-scheele/nestjs-sentiment.git
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



</description>
      <category>typescript</category>
      <category>sentimenetanalysis</category>
      <category>nestjs</category>
      <category>nlp</category>
    </item>
  </channel>
</rss>
