Use Vagrant with Libvirt KVM on Rocky Linux 8 / AlmaLinux 8

Posted on 106 views

How can I use Vagrant with Libvirt KVM Provider?. Vagrant is an open-source solution developed by HashiCorp that enable Developers to build and maintain portable software development environments in any Virtualization platform. It ships out of the box with support for VirtualBoxHyper-V, and Docker. For VMwareKVM, or Parallels users the provider is available for installation and use as well.

Before another provider can be used, it must be installed. The installation of Vagrant providers is done via the Vagrant plugin system. In this article we’ll be specific to the installation and usage of KVM Vagrant Provider on Rocky Linux 8 / AlmaLinux 8 Linux system.

The Vagrant libvirt provider is a good alternative if you already use KVM on your host to run Virtual Machines. As KVM is standard hypervisor for Linux users, this is a standard application across many spheres. Kernel-based Virtual Machine (KVM) is an open source virtualization technology built into Linux to enable you turn your Linux Server into a hypervisor running multiple virtual machines (VMs).

Perform a system update and upgrade before you proceed with this guide:

sudo dnf -y update && sudo reboot

Step 1: Install KVM on Rocky Linux 8 / AlmaLinux 8

The core dependency of this guide is KVM Hypervisor. Your system should have virtualization extensions (Intel VT or AMD-V) for this article to be successful in your application.

Login to your Rocky Linux 8 / AlmaLinux 8 and install KVM Virtualization stack tools.

sudo dnf install -y bash-completion vim @virt virt-install libvirt-devel 

Once they are installed, start libvirtd service.

sudo systemctl start libvirtd

Also set the service to be started automatically when system is rebooted.

sudo systemctl enable libvirtd

To manage Virtual Machines without sudo privileges, add your user account to libvirt group:

sudo usermod -aG libvirt $USER
newgrp libvirt

Confirm service status:

$ systemctl status libvirtd
 libvirtd.service - Virtualization daemon
   Loaded: loaded (/usr/lib/systemd/system/libvirtd.service; enabled; vendor preset: enabled)
   Active: active (running) since Sat 2022-09-24 10:30:27 EAT; 27s ago
     Docs: man:libvirtd(8)
 Main PID: 8110 (libvirtd)
    Tasks: 21 (limit: 32768)
   Memory: 22.0M
   CGroup: /system.slice/libvirtd.service
           ├─8110 /usr/sbin/libvirtd --timeout 120
           ├─8225 /usr/sbin/dnsmasq --conf-file=/var/lib/libvirt/dnsmasq/default.conf --leasefile-ro --dhcp-script=/usr/libexec/libvirt_leaseshelper
           └─8226 /usr/sbin/dnsmasq --conf-file=/var/lib/libvirt/dnsmasq/default.conf --leasefile-ro --dhcp-script=/usr/libexec/libvirt_leaseshelper

Sep 24 10:30:27 dnsmasq[8218]: listening on virbr0(#3):
Sep 24 10:30:27 dnsmasq[8225]: started, version 2.79 cachesize 150
Sep 24 10:30:27 dnsmasq[8225]: compile time options: IPv6 GNU-getopt DBus no-i18n IDN2 DHCP DHCPv6 no-Lua TFTP no-conntrack ipset auth DNSSEC loop-detect inotify
Sep 24 10:30:27 dnsmasq-dhcp[8225]: DHCP, IP range --, lease time 1h
Sep 24 10:30:27 dnsmasq-dhcp[8225]: DHCP, sockets bound exclusively to interface virbr0
Sep 24 10:30:27 dnsmasq[8225]: reading /etc/resolv.conf
Sep 24 10:30:27 dnsmasq[8225]: using nameserver
Sep 24 10:30:27 dnsmasq[8225]: read /etc/hosts - 2 addresses
Sep 24 10:30:27 dnsmasq[8225]: read /var/lib/libvirt/dnsmasq/default.addnhosts - 0 addresses
Sep 24 10:30:27 dnsmasq-dhcp[8225]: read /var/lib/libvirt/dnsmasq/default.hostsfile

Step 2: Install Vagrant on Rocky Linux 8 / AlmaLinux 8

Vagrant packages are distributed as binary and in YUM repository. Let’s add HashiCorp repository to our system.

sudo yum install -y yum-utils
sudo yum-config-manager --add-repo
sudo yum install vagrant -y

Hit the key to begin installation:

Transaction Summary
Install  1 Package

Total size: 108 M
Installed size: 257 M
Is this ok [y/N]: y

Step 3: Install Libvirt Vagrant plugin Rocky Linux 8 / AlmaLinux 8

Install dependency packages that will be required in this step.

sudo dnf groupinstall "Development Tools" -y 
sudo dnf -y install rsync zlib-devel libvirt-devel cmake libxslt-devel libxml2-devel libvirt-devel libguestfs-tools-c ruby ruby-devel

Update the Vagrant libraries:

At the time of this writing and validating this article, there is a compatibility issue between system libraries and the ones embedded with Vagrant. We’ll have to rebuild Vagrant libraries (Credits Oracle blog):

Ensure required dependencies are installed:

sudo dnf -y install libxslt-devel libxml2-devel libvirt-devel libguestfs-tools-c ruby-devel gcc byacc make cmake gcc-c++

Create directory used for builds.

mkdir -p ~/vagrant-build && cd ~/vagrant-build

Download krb5 and libssh packages locally.

dnf download --source krb5-libs libssh

Build and override krb5 library:

rpm2cpio krb5-*.src.rpm | cpio -idmv krb5-*.tar.gz
tar xzf krb5-*.tar.gz
pushd krb5-*/src
sudo cp -a lib/crypto/* /opt/vagrant/embedded/lib64/

Build and override libssh library:

rpm2cpio libssh-*.src.rpm | cpio -imdv  libssh-*.tar.xz
tar xJf libssh-*.tar.xz
mkdir build
pushd build
cmake ../libssh-*  -DOPENSSL_ROOT_DIR=/opt/vagrant/embedded
sudo cp lib/libssh* /opt/vagrant/embedded/lib64/

With the libraries updated we can now install Libvirt plugin for Vagrant:

$ vagrant plugin install vagrant-libvirt
Installing the 'vagrant-libvirt' plugin. This can take a few minutes...
Fetching formatador-1.1.0.gem
Fetching fog-core-2.3.0.gem
Fetching fog-json-1.2.0.gem
Fetching nokogiri-1.13.8-x86_64-linux.gem
Fetching fog-xml-0.1.4.gem
Fetching ruby-libvirt-0.8.0.gem
Building native extensions. This could take a while...
Fetching fog-libvirt-0.9.0.gem
Fetching xml-simple-1.1.9.gem
Fetching diffy-3.4.2.gem
Fetching vagrant-libvirt-0.10.8.gem
Installed the plugin 'vagrant-libvirt (0.10.8)'!

List available Vagrant plugins after installation:

$ vagrant plugin list
vagrant-libvirt (0.10.8, global)

To enable autocompletion for vagrant commands run:

$ vagrant autocomplete install
Autocomplete installed at paths:
- /home/jkmutai/.bashrc

Then source ~/.bashrc file:

source ~/.bashrc

Step 4: Adding Libvirt Vagrant Boxes

Boxes are the package format for Vagrant environments. A box can be used by anyone on any platform that Vagrant supports to bring up an identical working environment.

To use the provider we just installed, we need Vagrant boxes that were built for Libvirt provider. You can explore all the boxes available in Vagrant Cloud to find your match.

You cannot have both VirtualBox and KVM services running. If you also have VirtualBox stop its service.

systemctl stop vboxdrv.service

The vagrant box utility provides all the functionality for managing boxes. We can download few boxes for test.

### Rocky Linux 8 ###
vagrant box add generic/rocky8 --provider=libvirt

### Rocky Linux 9 ###
vagrant box add generic/rocky9 --provider=libvirt

### AlmaLinux 8 ###
vagrant box add generic/alma8 --provider=libvirt

### Add Ubuntu 22.04 box ###
vagrant box add generic/ubuntu2204 --provider=libvirt

### Add Debian 11 ###
vagrant box add generic/debian11 --provider=libvirt

You can get a list of all available Vagrant boxes using the following command:

$ vagrant box list
generic/rocky8 (libvirt, 4.1.12)

Step 5: Creating Vagrant Machines on KVM

Vagrantfile describes the type of machine required for a project, and how to configure and provision these machines. Consider below simple Vagrantfile that you can use to spin Vagrant machine.

vim Vagrantfile

Mine has the following contents:

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


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

  ##### DEFINE VM #####
  config.vm.define "rocky8" do |config|
  config.vm.hostname = "rocky8" = "generic/rocky8"
  config.vm.box_check_update = false
  config.vm.provider :libvirt do |v|
    v.memory = 1024

To start the machine run the commands below:

$ vagrant up
Bringing machine 'rocky8' up with 'libvirt' provider...
==> rocky8: Uploading base box image as volume into Libvirt storage...
==> rocky8: Creating image (snapshot of base box volume).
==> rocky8: Creating domain with the following settings...
==> rocky8:  -- Name:              jkmutai_rocky8
==> rocky8:  -- Description:       Source: /home/jkmutai/Vagrantfile
==> rocky8:  -- Domain type:       kvm
==> rocky8:  -- Cpus:              2
==> rocky8:  -- Feature:           acpi
==> rocky8:  -- Feature:           apic
==> rocky8:  -- Feature:           pae
==> rocky8:  -- Clock offset:      utc
==> rocky8:  -- Memory:            1024M
==> rocky8:  -- Management MAC:
==> rocky8:  -- Loader:
==> rocky8:  -- Nvram:
==> rocky8:  -- Base box:          generic/rocky8
==> rocky8:  -- Storage pool:      default
==> rocky8:  -- Image(vda):        /var/lib/libvirt/images/jkmutai_rocky8.img, virtio, 128G
==> rocky8:  -- Disk driver opts:  cache='default'
==> rocky8:  -- Kernel:
==> rocky8:  -- Initrd:
==> rocky8:  -- Graphics Type:     vnc
==> rocky8:  -- Graphics Port:     -1
==> rocky8:  -- Graphics IP:
==> rocky8:  -- Graphics Password: Not defined
==> rocky8:  -- Video Type:        cirrus
==> rocky8:  -- Video VRAM:        256
==> rocky8:  -- Video 3D accel:    false
==> rocky8:  -- Sound Type:
==> rocky8:  -- Keymap:            en-us
==> rocky8:  -- TPM Backend:       passthrough
==> rocky8:  -- TPM Path:
==> rocky8:  -- INPUT:             type=mouse, bus=ps2
==> rocky8: Creating shared folders metadata...
==> rocky8: Starting domain.
==> rocky8: Waiting for domain to get an IP address...
==> rocky8: Waiting for machine to boot. This may take a few minutes...
    rocky8: SSH address:
    rocky8: SSH username: vagrant
    rocky8: SSH auth method: private key
    rocky8: Vagrant insecure key detected. Vagrant will automatically replace
    rocky8: this with a newly generated keypair for better security.
    rocky8: Inserting generated public key within guest...
    rocky8: Removing insecure key from the guest if it's present...
    rocky8: Key inserted! Disconnecting and reconnecting using new SSH key...
==> rocky8: Machine booted and ready!
==> rocky8: Setting hostname...

To start SSH shell, run:

$ vagrant ssh
[[email protected] ~]$ cat /etc/redhat-release

[[email protected] ~]$ cat /etc/redhat-release
Rocky Linux release 8.6 (Green Obsidian)

You can interact with the machine the way you’ll do any operating system.

# Example: performing package upgrades
sudo dnf -y update

To stop server once it is running, use `vagrant halt` command.

$ vagrant halt
==> default: Attempting graceful shutdown of VM...

To destroy the virtual machine, run:

$ vagrant destroy
    default: Are you sure you want to destroy the 'default' VM? [y/N] y
==> default: Destroying VM and associated drives...
==> default: Destroying unused networking interface...

All vagrant command options available are:

vagrant --help
vagrant -h

You can learn more by reading through the official Vagrant documentation.


Gravatar Image
A systems engineer with excellent skills in systems administration, cloud computing, systems deployment, virtualization, containers, and a certified ethical hacker.