Streamlining Webpage Deployment on Multi-VMs Using Bash Scripts
Tags: devops, bash, deployment, linux
Published: 2024-05-29 22:17:42

Hey! 👋 Today, I'll guide you through the deployment of a static website on a Linux server using the power of Bash scripting. But, before diving in, let's ensure we have the essentials in place.

## Prerequisite:
- Install Git
- Install Vagrant
- Install Virtualbox

---

## Creating a Multi-VM Vagrantfile 📄
We need to create a Vagrantfile that will allow us to create multiple VMs.

1. Open the Git Bash terminal and create a Vagrantfile using the command `vim Vagrantfile`
2. Copy and paste the below code into the Vagrantfile

```
Vagrant.configure("2") do |config|

  # VM configurations for Ubuntu
  config.vm.define "web01" do |web01|
    web01.vm.box = "ubuntu/bionic64"
    web01.vm.network "private_network", ip: "192.168.56.41"
    web01.vm.hostname = "web01"

    config.vm.provider "virtualbox" do |vb|
      vb.memory = "2048"
    end

    config.vm.provision "shell", inline: <<-SHELL
      mkdir -p /var/log/barista_cafe_logs
      sudo chown vagrant:vagrant /var/log/barista_cafe_logs/
  SHELL

  end

  # Configuration for CentOS 9 VM
  config.vm.define "web02" do |web02|
    web02.vm.box = "eurolinux-vagrant/centos-stream-9"
    web02.vm.network "private_network", ip: "192.168.56.42"
    web02.vm.hostname = "web02"

    config.vm.provision "shell", inline: <<-SHELL
      mkdir -p /var/log/barista_cafe_logs
      sudo chown vagrant:vagrant /var/log/barista_cafe_logs/
  SHELL

  end
end
```

In the above code, we have specified the configurations of two VMs, _Ubuntu OS_ (hostname as 'web01') and CentOS 9 (hostname as 'web02') with specified Memory and IPv4 addresses.

Inline shell provisioning is used to create a barista_cafe_logs folder at location '**/var/log**' for storing the website setup and teardown log files. Ownership is set for the **vagrant** user (default user) so that log files for setup and teardown can be created without any restriction.

Note that we have given Ubuntu OS and CentOS the same identifier name as the hostname. In `config.vm.define "web01"`, web01 is the identifier name/ VM name that vagrant uses to identify for which VM we want to execute any command, while in `web01.vm.hostname = "web01"`, we have set a hostname for the VM to identify the device within a local network.

--- 
## Logging in to the VM 💻

Navigate to the folder where we have created the Vagrantfile using the cd command.

- **Launching the VM:**

Command: `vagrant up`

![vagrant up](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/j09l3yd5g681xpc1h6lg.png)

**Important:** `vagrant up` command will create all the VMs mentioned in the Vagrantfile at once. We can also create a specific VM, and then we can use a command `vagrant up vm_name` e.g., `vagrant up web01` will create only an Ubuntu VM (here, web01 is the identifier name).

- **Check VM status:**

Command: `vagrant status` or `vagrant global-status`

![Check VM status](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/34rlm6ne82qdhjh51uo0.png)

`vagrant status` will give the status of VMs of Vagrantfile in the current location while `vagrant global-status` will give the status of all the VMs in the system.

- **Login to the VM:**

Commands:
- For Ubuntu OS: `vagrant ssh web01`
- For CentOS: `vagrant ssh web02`

--- 
## Create bash files in Synced Directory 📁📝

We will create two bash files, **webpage_setup.sh**, and **webpage_teardown.sh**.

> The extension of a bash file is .sh

There are two ways to proceed further:

**Way1: Create a bash file in the local machine itself**

Create bash files in a local machine at the same location where Vagrantfile is located

![create bash file](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ypcfn5ky9r6k83f66mho.png)

**Way2: Create a bash file in the VM directly**

Create bash files at location /vagrant/

Navigate to location /vagrant using the command `cd /vagrant/` and create a bash file using the command `touch webpage_setup.sh` and `touch webpage_teardown.sh`

![create bash file](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/htzhltr06mcdzvzj29ed.png)

Use command `ls` to see the files and folders in Linux

![list command](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ah41voyaywok7d9kovf3.png)


**Important:** The directory where Vagrantfile exists in our local machine and the directory /vagrant in VM are synced together. This means that if we make changes to the same location on our local machine, we can see the changes in the /vagrant directory in the VM as well.

--- 
## Writing automation bash script 👨‍💻

> In Windows/MacOS, use any Code Editor like VSCode, Sublime Text, XCode, etc.

> In Linux/Unix, navigate using cd /vagrant and edit using a command vim webpage_setup.sh

- webpage_setup.sh

```
#!/bin/bash

# Function to log messages to deploy.log file
log() {
        message="$(date) - $1"
        echo "$message" >> /var/log/barista_cafe_logs/deploy.log
        echo "$message"
}


log "*****Starting deployment*****"


# checking if user is root user or not
log "*****Checking for root user access*****"
if [ $EUID -ne 0 ]
  then
        log "Warning: Current user is not root user. Please run the script as root user or use sudo."
fi


# checking if package manager is yum or apt-get
log "*****Checking for the package manager*****"
if command -v yum >> /dev/null
  then
        packages="httpd unzip wget"
        service="httpd"
        pkg_manager="yum"

        log "$pkg_manager package manager found!!!"
elif command -v apt-get >> /dev/null
  then
        packages="apache2 unzip wget"
        service="apache2"
        pkg_manager="apt-get"

        log "$pkg_manager package manager found!!!"
else
        log "Error: Unsupported package manager"
        exit 1
fi


# installing the packages
log "*****Installing the required package*****"
if ! sudo $pkg_manager install $packages -y
  then
        log "Error: Failed to install packages"
        exit 1
else
        log "Packages installed successfully"
fi


# starting and enabling the web service
log "*****Starting and enabling $service*****"
if ! (sudo systemctl start $service && sudo systemctl enable $service)
  then
        log "Error: Failed to start and enable the $service"
        exit 1
else
        log "$service started and enabled successfully"

fi


# creating variables
url="https://www.tooplate.com/zip-templates/2137_barista_cafe.zip"
temp_folder="/temp/barista_cafe"
target_folder="/var/www/html"
artifact="2137_barista_cafe"


# creating folder /temp/barista_cafe
log "*****Creating folder $temp_folder*****"
if ! sudo mkdir -p $temp_folder
  then
        log "Error: Failed to create folder $temp_folder"
        exit 1
else
        log "$temp_folder created successfully"
fi


# navigating to the temp folder
log "*****Navigating to the folder $temp_folder*****"
if ! cd $temp_folder
  then
        log "Error: Failed to navigate to $temp_folder"
        exit 1
else
        log "Navigated to $temp_folder"
fi


# downloading the web files
log "*****Downloading the web files*****"
if ! sudo wget $url
  then
        log "Error: Failed to download the web files from url"
        exit 1
else
        log "Downloaded the web files successfully"
fi


# unzipping the downloaded files
log "*****Unzipping the downlaoded files*****"
if ! sudo unzip -o $artifact.zip
  then
        log "Error: Failed to unzip the web files"
        exit 1
else
        log "Unzipped the web files successfully"
fi


# copying the extracted files to /var/www/html
log "*****Copying the extracted files to $target_folder*****"
if ! sudo cp -r $artifact/* $target_folder
  then
        log "Error: Failed to copy the files to $target_folder"
        exit 1
else
        log "Copied the extracted files to $target_folder successfully"
fi


# printing the files at location /var/www/html
log "*****Printing the files at $target_folder*****"
ls $target_folder


# restarting the web service
log "*****Restarting the $service*****"

if ! sudo systemctl restart $service
  then
        log "Error: Failed to restart the $service"
else
        log "Re-started the $service successfully"
fi


log "Successfully deployed the website"

```

- webpage_teardown.sh

```
#!/bin/bash

log() {
    message="$(date) - $1"
    echo "$message" >> /var/log/barista_cafe_logs/teardown.log
    echo "$message"
}


log "*****Starting teardown...*****"


# checking for root user
log "*****Checking for root user access*****"
if [ $EUID -ne 0 ]
    then
        log "Warning: Warning: Current user is not root user. Please run the script as root user or use sudo."
fi


# checking for package manager
log "*****Checking for package manager*****"
if command -v yum >> /dev/null
    then
        packages="httpd unzip wget"
        service="httpd"
        pkg_manager="yum"

        log "$pkg_manager package manager found!!!"
elif command -v apt-get >> /dev/null
  then
        packages="apache2 unzip wget"
        service="apache2"
        pkg_manager="apt-get"

        log "$pkg_manager package manager found!!!"
else
        log "Error: Unsupported package manager"
        exit 1
fi


# stopping the web-service
log "*****Stopping $service*****"
if ! sudo systemctl stop $service
    then
        log "Error: Unable to stop $service"
else
    log "Successfully stopped $service"
fi


# removing installed packages
log "*****Removing installed packages*****"
if ! sudo $pkg_manager remove $packages -y
    then
        log "Error: Unable to remove packages: $packages"
        exit 1
else
    log "Packages removed successfully"
fi


# creating variables
temp_folder="/temp/barista_cafe"
target_folder="/var/www/html"
artifact="2137_barista_cafe"


# removing downloaded web files
log "*****Deleting web files*****"
if ! sudo rm -rf $temp_folder
    then
        log "Error: Unable to delete folder $temp_folder"
        exit 1
else
    log "Successfully deleted $temp_folder"
fi


# removing web files at location /var/www/html
log "*****Deleting web files*****"
if ! sudo rm -rf $target_folder
    then
        log "Error: Unable to delete folder $target_folder"
        exit 1
else
    log "Successfully deleted $target_folder"
fi


log "Teardown completed successfully!"

```

--- 
## Running the bash scripts 💨
Follow the below steps to log in to the VM and navigate to the bash files.

1. Open Git bash and navigate to the folder where the Vagrant file resides
**Command:** `cd /path_to_vagrantfile/`

2. Log in to any of the VM
**Commands:**
For Ubuntu OS: `vagrant ssh web01`
For CentOS: `vagrant ssh web02`

3. Navigate to the vagrant folder where bash scripts reside
**Command:** `cd /vagrant/`

![navigate to vagrant folder](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/9nw6lnaz1vts7vk5ivuh.png)


Now follow the below steps to execute the scripts:

#### For Website Setup:
We will run webpage_setup.sh file for the webpage setup. Follow the below steps to execute the setup file.

1. Making the webpage_setup.sh bash file executable
**Command:** `chmod +x webpage_setup.sh`

2. Running the bash script
**Command:** `./webpage_setup.sh`
Wait until the bash script runs completely; if everything goes right, we can see a success message.
![run bash script](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/mi619gmgtpxohk717h15.png)


3. Get the IPv4 address
**Command:** `ip addr show`

![get IP address](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/0k8yq2axnlttoox1g43e.png)

Copy the IP address and paste it into the browser and we can see our website live on our local Linux server

![website running](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/0jog9qt7z6vb9jyafoti.png)

Hurray 👏 ... We have successfully deployed a webpage on a Linux server using a bash script.


#### For Website Teardown:
Once we have successfully deployed the website, we can also destroy the setup if we want. Simply run the webpage_teardown.sh file that we have created previously. The steps are similar to that of setup,

1. Making the webpage_teardown.sh bash file executable
**Command:** `chmod +x webpage_teardown.sh`

2. Running the bash script
**Command:** `./webpage_teardown.sh`

Wait until the bash script runs completely; if everything goes right, we can see a success message for teardown.

![teardown bash script](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/piqkromwsliwo6ylsma6.png)

Now cross-check if we can access the website or not by copying the IP address using the command `ip addr show` and pasting it into the browser.

![re-checking website](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/xga5i8utbehnmsy3tgn1.png)

Great, we have successfully destroyed the website setup and released all the resources.


#### Destroying the VM:
Now we can destroy the created VM by running a command `vagrant destroy`. This command will destroy all the VMs that we have created. In case we want to destroy any specific VM then we can use the VM name to destroy it using the command `vagrant destroy vm_name`.

After deletion, we can check the status of the Vagrant environment and verify that the VMs have been successfully destroyed using the command `vagrant status`.

![vagrant status](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/qvskgf1892p31nosxyg1.png)

![vagrant status](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/rq4mpojdg5y0jlad2haf.png)

--- 
## Checking the Logs 📈📋
The logs of setup and teardown will be saved at the location '**/var/logs/barista_cafe_logs/**' in the files **deploy.log** and **teardown.log**. Let's see the logs,

1. Navigate to the log folder using the command `cd /var/logs/barista_cafe_logs/`

2. Use `ls` command to see the files in this folder
![list command](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/cruaukvmqjcwy1b9oiru.png)

3. Read the log files using the command `cat deploy.log` and `cat teardown.log`

- **Logs in deploy.log**

![deploy log](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/lksrqixava3wjqorzv1u.png)

- **Logs in teardown.log**

![teardown log](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/q8mq6o6nec6qupqjd06r.png)

--- 
## Download the source files: 💾
**Github Repo:** https://github.com/Ritik-Saxena/Static-Webpage-Deployment-Bash

## Connect with me: 🤝
**LinkedIn:** https://www.linkedin.com/in/ritik-saxena/


![thank you](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ks1vb6ocy9gvx1scxr7c.png)