Vagrant is an open-source software product for building and maintaining portable virtual software development environments; e.g., for VirtualBox, KVM, Hyper-V, Docker containers, VMware, and AWS. It is not a stand-alone virtualization provider. It relies on other virtualization providers such as Virtualbox, Libvirt/KVM, Docker, VMWare to create and run virtual machines.
By default, Vagrant uses Oracle VirtualBox as provider. If more than one providers are installed (E.g. Virtualbox and Libvirt) in your system, it will always start a VM with Virtualbox unless you explicitly provide a specific provider. One of the great features of Vagrant is that users are never tied to a specific virtualization platform. The users can create workflows that work with multiple virtualization providers.
In this guide, we will learn how to use Vagrant with Libvirt KVM provider on Linux.
Step 1 – Installing KVM
Before proceeding, you need to have KVM installed in your system. I already have KVM installed in my system, please checkout these guides on how to install KVM:
Step 2 – Installing vagrant
Next, we need to make sure that Vagrant is installed. Vagrant is available packaged for most of the distributions, please consult the downloads page here or use your package manager to install.
To confirm that vagrant is installed and working as expected, check it’s version using this command:
➜ vagrant version
Installed Version: 2.2.19
Latest Version: 2.2.19
You're running an up-to-date version of Vagrant!
Step 3 – Install vagrant-libvirt plugin
In order to run Vagrant virtual machines on KVM, you need to install the vagrant-libvirt
 plugin. This plugin adds the Libvirt provider to Vagrant and allows Vagrant to control and provision machines via Libvirt.
Install the necessary dependencies for vagrant-libvirt
 plugin.
➜ 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.6-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 vagrant-libvirt-0.8.2.gem
Installed the plugin 'vagrant-libvirt (0.8.2)'!
Once installation is complete, confirm that it has been registered fine by listing plugins:
➜ vagrant plugin list
vagrant-libvirt (0.8.2, global)
Step 4 – Use Vagrant With Libvirt KVM Provider
Make sure the Vagrant box that you want to use supports the libvirt provider. To discover vagrant boxes supported by libvirt, just select the “libvirt” option in Vagrant Cloud repository.
For the purpose of this guide, I am going to use a Rocky Linux 8 box.
To add a box, use this command:
vagrant box add generic/rocky8 --provider=libvirt
Check the list of boxes presents locally.
➜ vagrant box list
generic/rocky8 (libvirt, 3.6.14)
Another alternative is to use a project. Create a vagrant project directory and switch to it:
mkdir rocky-vm
cd rocky-vm
Then initialize with the box you want to use:
vagrant init generic/rocky8
Next, run the following command to start the virtual machine:
vagrant up --provider=libvirt
Here, --provider=libvirt
 option explicitly tells Vagrant to use libvirt KVM to run the virtual machine. Meaning – KVM acts as default provider here.
Sample output:
➜ vagrant up --provider=libvirt
Bringing machine 'default' up with 'libvirt' provider...
==> default: Checking if box 'generic/rocky8' version '3.6.14' is up to date...
==> default: Uploading base box image as volume into Libvirt storage...
==> default: Creating image (snapshot of base box volume).
==> default: Creating domain with the following settings...
==> default: -- Name: rocky-vm_default
==> default: -- Description: Source: /home/eutychus/rocky-vm/Vagrantfile
==> default: -- Domain type: kvm
==> default: -- Cpus: 2
==> default: -- Feature: acpi
==> default: -- Feature: apic
==> default: -- Feature: pae
==> default: -- Clock offset: utc
==> default: -- Memory: 2048M
==> default: -- Management MAC:
==> default: -- Loader:
==> default: -- Nvram:
==> default: -- Base box: generic/rocky8
==> default: -- Storage pool: default
==> default: -- Image(vda): /var/lib/libvirt/images/rocky-vm_default.img, virtio, 128G
==> default: -- Disk driver opts: cache='default'
==> default: -- Kernel:
==> default: -- Initrd:
==> default: -- Graphics Type: vnc
==> default: -- Graphics Port: -1
==> default: -- Graphics IP: 127.0.0.1
==> default: -- Graphics Password: Not defined
==> default: -- Video Type: cirrus
==> default: -- Video VRAM: 256
==> default: -- Video 3D accel: false
==> default: -- Sound Type:
==> default: -- Keymap: en-us
==> default: -- TPM Backend: passthrough
==> default: -- TPM Path:
==> default: -- INPUT: type=mouse, bus=ps2
==> default: Creating shared folders metadata...
==> default: Starting domain.
==> default: Waiting for domain to get an IP address...
==> default: Waiting for machine to boot. This may take a few minutes...
default: SSH address: 192.168.121.43:22
default: SSH username: vagrant
default: SSH auth method: private key
default:
default: Vagrant insecure key detected. Vagrant will automatically replace
default: this with a newly generated keypair for better security.
default:
default: Inserting generated public key within guest...
default: Removing insecure key from the guest if it's present...
default: Key inserted! Disconnecting and reconnecting using new SSH key...
==> default: Machine booted and ready!
Alternatively you can tell Vagrant to permanently use libvirt as default provider by adding the following environment variable.
export VAGRANT_DEFAULT_PROVIDER=libvirt
Vagrant will create a Linux bridge on the host system.
➜ brctl show virbr1
bridge name bridge id STP enabled interfaces
virbr1 8000.5254009d4555 yes vnet0
You can also check the ip
➜ ip addr show dev virbr1
9: virbr1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default qlen 1000
link/ether 52:54:00:9d:45:55 brd ff:ff:ff:ff:ff:ff
inet 192.168.121.1/24 brd 192.168.121.255 scope global virbr1
valid_lft forever preferred_lft forever
Step 5 – Verify that the vm is running
You can verify if the CentOS 7 VM is really running in Libvirt KVM provider from Virsh command line interface.
virsh list
Sample output:
Id Name State
----------------------------------
1 rocky-vm_default running
Or, use vagrant status
 command:
➜ vagrant status Current machine states: default running (libvirt) The Libvirt domain is running. To stop this machine, you can run `vagrant halt`. To destroy the machine, you can run `vagrant destroy`.
You can also verify it from a KVM management GUI applications like Virt-manager.
To ssh to the VM, use _vagrant ssh _command.
➜ vagrant ssh
[vagrant@rocky8 ~]$
To output .ssh/config valid syntax for connecting to this environment via ssh, run ssh-config command. You’ll need to place provided output under ~/.ssh/config directory to ssh.
➜ vagrant ssh-config
Host default
HostName 192.168.121.43
User vagrant
Port 22
UserKnownHostsFile /dev/null
StrictHostKeyChecking no
PasswordAuthentication no
IdentityFile /home/eutychus/rocky-vm/.vagrant/machines/default/libvirt/private_key
IdentitiesOnly yes
LogLevel FATAL
To shut down the VM, run:
➜ vagrant halt
==> default: Attempting graceful shutdown of VM...
To set VM to its initial state by cleaning all data, use vagrant destroy:
➜ vagrant destroy
default: Are you sure you want to destroy the 'default' VM? [y/N] y
==> default: Removing domain...
==> default: Deleting the machine folder
Conclusion
In this guide, we learned how to use Vagrant with libvirt KVM provider in Linux. We also looked at how to verify if the virtual machine is running in Libvirt KVM.