How to Create Multiple Virtual Machines Using Vagrant Tool

Prerequisites

Surya Raj Ghimire
9 min readMay 29, 2023

· A computer with at least 8GB of RAM
· Basic knowledge of the linux operating system

A tool for building and managing VMs in a single workflow
Automation tool (IaC)
It supports Oracle VirtualBox (default, mostly used with vagrant), VMware, Hyper-V, Libvirt… Hypervisors

Required Tools and Installation

  1. Download and install Git Bash
    · Download the Git Bash setup from the official website: https://git-scm.com/.
    · Download the installer.
    · Run the .exe file you just downloaded and follow the instructions in the installer.
    · Run Git Bash by right-clicking on any folder and selecting the Git Bash Here option from the context menu (right-click menu).

2. Download and install latest version of VirtualBox
· To download VirtualBox, go to the official site VirtualBox downloads and click the Windows hosts link.
· Locate the installer file and double-click on it to run the installation process.
· The VirtualBox installation wizard will launch. Click Next to proceed.
· Select a list of the features and browse the location you want to install. By default, all components are selected. Click Next when you’re ready to continue.
· Choose whether you want to create shortcuts in the start menu folder. You can leave the default selection and click Next to continue.
· Click Install to begin the installation process. Wait for the installer to complete the installation of VirtualBox.
· The installation process takes several minutes, depending on your system speed. Click Finish to close the wizard after the installation and start using VirtualBox.

3. Download and install latest version of Vagrant
· Download the latest vagrant installation file from https://www.vagrantup.com/downloads
· Open the installer, proceed with Next and Finish prompts to set up Vagrant.
· After successful installation, you can find Vagrant icon the dashboard or from the Windows starter menu. You can also verify it on Git Bash. For that just open Git Bash and run the below command.

If the installation is successful, you will see the Vagrant version.

user@DESKTOP-HD846LJ MINGW64 ~/Desktop
$ vagrant --version
Vagrant 2.3.6

4. Search vagrant boxes
To view options related to the vagrant command

user@DESKTOP-HD846LJ MINGW64 ~/Desktop
$ vagrant --help
Usage: vagrant [options] <command> [<args>]

-h, --help Print this help.

Common commands:
autocomplete manages autocomplete installation on host
box manages boxes: installation, removal, etc.
cloud manages everything related to Vagrant Cloud
destroy stops and deletes all traces of the vagrant machine
global-status outputs status Vagrant environments for this user
halt stops the vagrant machine
help shows the help for a subcommand
init initializes a new Vagrant environment by creating a Vagrantfile
login
package packages a running vagrant environment into a box
plugin manages plugins: install, uninstall, update, etc.
port displays information about guest port mappings
powershell connects to machine via powershell remoting
provision provisions the vagrant machine
push deploys code in this environment to a configured destination
rdp connects to machine via RDP
reload restarts vagrant machine, loads new Vagrantfile configuration
resume resume a suspended vagrant machine
serve start Vagrant server
snapshot manages snapshots: saving, restoring, etc.
ssh connects to machine via SSH
ssh-config outputs OpenSSH valid configuration to connect to the machine
status outputs status of the vagrant machine
suspend suspends the machine
up starts and provisions the vagrant environment
upload upload to machine via communicator
validate validates the Vagrantfile
version prints current and latest Vagrant version
winrm executes commands on a machine via WinRM
winrm-config outputs WinRM configuration to connect to the machine

For help on any individual command run `vagrant COMMAND -h`

Additional subcommands are available, but are either more advanced
or not commonly used. To see all subcommands, run the command
`vagrant list-commands`.
--[no-]color Enable or disable color output
--machine-readable Enable machine readable output
-v, --version Display Vagrant version
--debug Enable debug output
--timestamp Enable timestamps on log output
--debug-timestamp Enable debug output with timestamps
--no-tty Enable non-interactive output

To see a list of all installed boxes on your computer

user@DESKTOP-HD846LJ MINGW64 ~/Desktop
$ vagrant box list
There are no installed boxes! Use `vagrant box add` to add some.

To download a box image to your computer: vagrant box add <name> <url>

user@DESKTOP-HD846LJ MINGW64 ~/Desktop
$ vagrant box add centos/8
==> box: Loading metadata for box 'centos/8'
box: URL: https://vagrantcloud.com/centos/8
This box can work with multiple providers! The providers that it
can work with are listed below. Please review the list and choose
the provider you will be working with.

1) libvirt
2) virtualbox

Enter your choice: 2
==> box: Adding box 'centos/8' (v2011.0) for provider: virtualbox
box: Downloading: https://vagrantcloud.com/centos/boxes/8/versions/2011.0/providers/virtualbox.box
Download redirected to host: cloud.centos.org
box:
box: Calculating and comparing box checksum...
==> box: Successfully added box 'centos/8' (v2011.0) for 'virtualbox'!

user@DESKTOP-HD846LJ MINGW64 ~/Desktop
$ vagrant box list
centos/8 (virtualbox, 2011.0)

Create a Single Virtual Machine Using Vagrant

  1. Go to your project directory and initialize vagrant to create a vagrant file: vagrant init
user@DESKTOP-HD846LJ MINGW64 ~/Desktop
$ mkdir dotnetdevelopers

user@DESKTOP-HD846LJ MINGW64 ~/Desktop
$ cd dotnetdevelopers/

user@DESKTOP-HD846LJ MINGW64 ~/Desktop/dotnetdevelopers
$ pwd
/c/Users/user/Desktop/dotnetdevelopers

user@DESKTOP-HD846LJ MINGW64 ~/Desktop/dotnetdevelopers
$ vagrant init
A `Vagrantfile` has been placed in this directory. You are now
ready to `vagrant up` your first virtual environment! Please read
the comments in the Vagrantfile as well as documentation on
`vagrantup.com` for more information on using Vagrant.

user@DESKTOP-HD846LJ MINGW64 ~/Desktop/dotnetdevelopers
$ ls
Vagrantfile

2. Open the Vagrantfile on the vim editor and remove the informational comments and define the VM specification i.e. what operating system you want, how much RAM you allocate, how many CPU cores you want to provide, what software packages you want to install automatically, etc. will leave the file like this:

# -*- mode: ruby -*-
# vi: set ft=ruby :

Vagrant.configure("2") do |config|
config.vm.box = "centos/8"
config.vm.box_check_update = false
config.vm.hostname = "dotnetdev1.srg.com"
config.vm.provider "virtualbox" do |vb|
vb.gui = false
vb.memory = "2048"
vb.cpus = 2
end
end

3. Once you defined your VM specifications, you can start the VM just by running the below command: vagrant up

user@DESKTOP-HD846LJ MINGW64 ~/Desktop/dotnetdevelopers
$ vagrant up
Bringing machine 'default' up with 'virtualbox' provider...
==> default: Importing base box 'centos/8'...
vagrant up command
Oracle VM VirtualBox

4. SSH into vagrant virtual machine: vagrant ssh

user@DESKTOP-HD846LJ MINGW64 ~/Desktop/dotnetdevelopers
$ vagrant ssh
Last login: Mon May 29 06:01:49 2023
[vagrant@dotnetdev1 ~]$ whoami
vagrant
[vagrant@dotnetdev1 ~]$ hostname
dotnetdev1.srg.com
[vagrant@dotnetdev1 ~]$ cat /etc/redhat-release
CentOS Linux release 8.3.2011
[vagrant@dotnetdev1 ~]$ ls /vagrant/
Vagrantfile

5. To shows the current status of the virtual machine, including whether it’s running, stopped, or suspended: vagrant status

user@DESKTOP-HD846LJ MINGW64 ~/Desktop/dotnetdevelopers
$ vagrant.exe status
Current machine states:

default running (virtualbox)

The VM is running. To stop this VM, you can run `vagrant halt` to
shut it down forcefully, or you can run `vagrant suspend` to simply
suspend the virtual machine. In either case, to restart it again,
simply run `vagrant up`.

6. To power off/down the virtual machine: vagrant halt

user@DESKTOP-HD846LJ MINGW64 ~/Desktop/dotnetdevelopers
$ vagrant halt
==> default: Attempting graceful shutdown of VM...

user@DESKTOP-HD846LJ MINGW64 ~/Desktop/dotnetdevelopers
$ vagrant status
Current machine states:

default poweroff (virtualbox)

The VM is powered off. To restart the VM, simply run `vagrant up`

7. To stop and delete the virtual machine and all associated resources: vagrant destroy

user@DESKTOP-HD846LJ MINGW64 ~/Desktop/dotnetdevelopers
$ vagrant destroy
default: Are you sure you want to destroy the 'default' VM? [y/N] y
==> default: Destroying VM and associated drives...

Create Multiple Virtual Machines Using Vagrant

  1. Open the Vagrantfile on the vim editor and modify the configurations as per your requirements. You can change the memory, CPU, network settings, etc., for each virtual machine individually.
# -*- mode: ruby -*-
# vi: set ft=ruby :

Vagrant.configure("2") do |config|
config.vm.box_check_update = false

#App server
config.vm.define "app" do |app|
app.vm.hostname = "appserver.srg.com"
app.vm.box = "centos/8"
app.vm.network :private_network, ip: "10.0.0.101"
end

#DB server
config.vm.define "db" do |db|
db.vm.hostname = "dbserver.srg.com"
db.vm.box = "centos/8"
db.vm.network :private_network, ip: "10.0.0.102"
end

#Mail server
config.vm.define "mail" do |mail|
mail.vm.hostname = "mailserver.srg.com"
mail.vm.box = "centos/8"
mail.vm.network :private_network, ip: "10.0.0.103"
end

config.vm.provider "virtualbox" do |vb|
vb.gui = false
vb.memory = "2048"
vb.cpus = 2
end
end

2. To starts vagrant environment: vagrant up

vagrant up command
user@DESKTOP-HD846LJ MINGW64 ~/Desktop/dotnetdevelopers
$ vagrant status
Current machine states:

app running (virtualbox)
db running (virtualbox)
mail running (virtualbox)

This environment represents multiple VMs. The VMs are all listed
above with their current state. For more information about a specific
VM, run `vagrant status NAME`.

3. To view particular vm status: vagrant status <vm name>

user@DESKTOP-HD846LJ MINGW64 ~/Desktop/dotnetdevelopers
$ vagrant status mail
Current machine states:

mail running (virtualbox)

The VM is running. To stop this VM, you can run `vagrant halt` to
shut it down forcefully, or you can run `vagrant suspend` to simply
suspend the virtual machine. In either case, to restart it again,
simply run `vagrant up`.

4. To enter into particular vm: vagrant ssh <vm name>

user@DESKTOP-HD846LJ MINGW64 ~/Desktop/dotnetdevelopers
$ vagrant ssh db
[vagrant@dbserver ~]$ hostname
dbserver.srg.com
[vagrant@dbserver ~]$ exit
logout

user@DESKTOP-HD846LJ MINGW64 ~/Desktop/dotnetdevelopers
$ vagrant ssh mail
[vagrant@mailserver ~]$ hostname -I
10.0.2.15 10.0.0.103

5. To halt particular machine: vagrant halt <vm name>

user@DESKTOP-HD846LJ MINGW64 ~/Desktop/dotnetdevelopers
$ vagrant halt mail
==> mail: Attempting graceful shutdown of VM...

6. To destroy machine: vagrant destroy <vm name>

user@DESKTOP-HD846LJ MINGW64 ~/Desktop/dotnetdevelopers
$ vagrant destroy mail
mail: Are you sure you want to destroy the 'mail' VM? [y/N] y
==> mail: Destroying VM and associated drives...

user@DESKTOP-HD846LJ MINGW64 ~/Desktop/dotnetdevelopers
$ vagrant destroy
==> mail: VM not created. Moving on...
db: Are you sure you want to destroy the 'db' VM? [y/N] y
==> db: Forcing shutdown of VM...
==> db: Destroying VM and associated drives...
app: Are you sure you want to destroy the 'app' VM? [y/N] y
==> app: Forcing shutdown of VM...
==> app: Destroying VM and associated drives...

user@DESKTOP-HD846LJ MINGW64 ~/Desktop/dotnetdevelopers
$ vagrant status
Current machine states:

app not created (virtualbox)
db not created (virtualbox)
mail not created (virtualbox)

This environment represents multiple VMs. The VMs are all listed
above with their current state. For more information about a specific
VM, run `vagrant status NAME`.

Create a VM Using Vagrant and Provision It Using Bash Shell Script

Vagrant Shell Provisioning
  1. Open the Vagrantfile in a vim editor and configure it as follows:
# -*- mode: ruby -*-
# vi: set ft=ruby :

Vagrant.configure("2") do |config|
config.vm.box = "centos/8"
config.vm.provision :shell, path: "configweb.sh"
config.vm.box_check_update = false
config.vm.hostname = "webserver.srg.com"
config.vm.provider "virtualbox" do |vb|
vb.gui = false
vb.memory = "2048"
vb.cpus = 2
end
end

2. Create a new file called configweb.sh in the same directory and add your desired provisioning script. For example, let’s install httpd and add a sample html page using the Bash script:

#!/usr/bin/env bash
yum -y install httpd curl

#setenforce 0

systemctl start httpd
systemctl enable httpd

firewall-cmd --permanent --add-service=http
firewall-cmd --reload

echo "<h1> This is a test website </h1>" >/var/www/html/index.html

3. Start the VM by running the following command: vagrant up
It will create a VM and execute the provisioning script defined in the Vagrantfile.

user@DESKTOP-HD846LJ MINGW64 ~/Desktop/dotnetdevelopers
$ vagrant up
user@DESKTOP-HD846LJ MINGW64 ~/Desktop/dotnetdevelopers
$ vagrant ssh
[vagrant@webserver ~]$ rpm -q httpd curl
httpd-2.4.6-98.el7.centos.7.x86_64
curl-7.29.0-59.el7_9.1.x86_64
[vagrant@webserver ~]$ systemctl status httpd
● httpd.service - The Apache HTTP Server
Loaded: loaded (/usr/lib/systemd/system/httpd.service; enabled; vendor preset: disabled)
Active: active (running) since Mon 2023-05-29 13:52:05 UTC; 29min ago
[vagrant@webserver ~]$ ls /var/www/html/
index.html
[vagrant@webserver ~]$ cat /var/www/html/index.html
<h1> This is a test website </h1>
[vagrant@webserver ~]$ curl http://localhost
<h1> This is a test website </h1>

Another way:

user@DESKTOP-HD846LJ MINGW64 ~/Desktop/dotnetdevelopers
$ mkdir html

user@DESKTOP-HD846LJ MINGW64 ~/Desktop/dotnetdevelopers
$ vi html/index.html

user@DESKTOP-HD846LJ MINGW64 ~/Desktop/dotnetdevelopers
$ cat html/index.html
<h1>Deploying webserver using vagrant.....</h1>

configweb.sh

#!/usr/bin/env bash
yum -y install httpd curl

setenforce 0

systemctl start httpd
systemctl enable httpd

firewall-cmd --permanent --add-service=http
firewall-cmd --reload

#echo "<h1> This is a test website </h1>" >/var/www/html/index.html

if [ -e /var/www ]; then
rm -rf /var/www/html
ln -s /vagrant/html /var/www/html
fi
user@DESKTOP-HD846LJ MINGW64 ~/Desktop/dotnetdevelopers
$ vagrant up

user@DESKTOP-HD846LJ MINGW64 ~/Desktop/dotnetdevelopers
$ vagrant ssh
[vagrant@webserver ~]$ rpm -q httpd curl
httpd-2.4.6-98.el7.centos.7.x86_64
curl-7.29.0-59.el7_9.1.x86_64
[vagrant@webserver ~]$ systemctl status httpd
● httpd.service - The Apache HTTP Server
Loaded: loaded (/usr/lib/systemd/system/httpd.service; enabled; vendor preset: disabled)
Active: active (running) since Mon 2023-05-29 14:50:24 UTC; 2min 21s ago
Docs: man:httpd(8)
man:apachectl(8)
Main PID: 2778 (httpd)
Status: "Total requests: 0; Current requests/sec: 0; Current traffic: 0 B/sec"
CGroup: /system.slice/httpd.service
├─2778 /usr/sbin/httpd -DFOREGROUND
├─2779 /usr/sbin/httpd -DFOREGROUND
├─2781 /usr/sbin/httpd -DFOREGROUND
├─2782 /usr/sbin/httpd -DFOREGROUND
├─2783 /usr/sbin/httpd -DFOREGROUND
└─2784 /usr/sbin/httpd -DFOREGROUND
[vagrant@webserver ~]$ ls -l /var/www/
total 0
drwxr-xr-x. 2 root root 6 Apr 5 17:19 cgi-bin
lrwxrwxrwx. 1 root root 13 May 29 14:50 html -> /vagrant/html
[vagrant@webserver ~]$ ls -l /var/www/html/
total 4
-rw-r--r--. 1 vagrant vagrant 48 May 29 14:42 index.html
[vagrant@webserver ~]$ cat /var/www/html/index.html
<h1>Deploying webserver using vagrant.....</h1>
[vagrant@webserver ~]$ getenforce
Enforcing
[vagrant@webserver ~]$ sudo -i
[root@webserver ~]# setenforce 0
[root@webserver ~]# exit
logout
[vagrant@webserver ~]$ getenforce
Permissive
[vagrant@webserver ~]$ curl http://localhost
<h1>Deploying webserver using vagrant.....</h1>

--

--