In this guide, we’ll look at how to use Vagrant with Libvirt on Linux. Vagrant is an open-source software written in Ruby to help you build and maintain a portable virtual software development environments, e.g. for VirtualBox, Hyper-V, Docker containers, VMware, Libvirt, and AWS. Vagrant makes it easy to create, stop and destroy Virtual Machines.
The most Vagrant use case on Local machines is the use of VirtualBox provider. If you are a KVM and QEMU user, this article is for you. KVM has been known to have a better performance and small resource utilization as compared to Virtualbox.
For CentOS Stream 8 / Rocky Linux 8 / AlmaLinux 8, check:
Vagrant with Libvirt on Linux Pre-requisites:
- Installed Vagrant
- Installed Libvirt and QEMU-KVM
- Installing libvirt plugin for Vagrant
Step 1: Install KVM and Vagrant
For installation of KVM on Linux, we have some articles already baked for you.
- Install KVM on RHEL/CentOS 8, Fedora, Arch Linux, CentOS, Ubuntu/Debian, SLES
For Vagrant installation, check below guides:
- How to Install Vagrant and Virtualbox on Fedora
- Istall Latest Vagrant on Ubuntu / Debian & Kali Linux
Step 2: Installing Vagrant plugin for Vagrant
Once you have Vagrant and KVM installed, you should be ready to install a libvirt plugin so that you can start managing KVM Virtual machines using Vagrant.
But first ensure libvirt development package is installed:
# CentOS / Fedora
sudo yum -y install libvirt-devel
sudo yum -y groupinstall "Development Tools"
Then install Vagrant libvirt plugin:
$ vagrant plugin install vagrant-libvirt
Installing the 'vagrant-libvirt' plugin. This can take a few minutes...
Building native extensions. This could take a while...
Building native extensions. This could take a while...
Installed the plugin 'vagrant-libvirt (0.0.45)'!
If you encounter an error like below:
ERROR: Failed to build gem native extension.
current directory: /home/jmutai/.vagrant.d/gems/2.5.1/gems/nokogiri-1.8.4/ext/nokogiri
/usr/bin/ruby -r ./siteconf20180704-25314-14hvlbq.rb extconf.rb
checking if the C compiler accepts ... yes
Building nokogiri using system libraries.
pkg-config could not be used to find libxml-2.0
Please install either `pkg-config` or the pkg-config gem per
gem install pkg-config -v "~> 1.1"
Then run:
$ gem install nokogiri
$ vagrant plugin install pkg-config
And retry installing the plugin.
$ vagrant plugin install vagrant-libvirt
Once the installation is complete, you can confirm that the plugin has been installed using the following command:
$ vagrant plugin list
vagrant-libvirt (0.10.8, global)
Step 3: Downloading Vagrant boxes
A Vagrant box for Libvirt is a tar archive with 3 files in it.
- A base VagrantFile
- Th metadata.json file
- QCOW2 image
If you are interested in building your own Vagrant boxes, have a look at using Packer and Packer build templates for Vagrant on chef/bento github repo. It will help you to easily get started.
In this example, we’re going to use a ready template. Let add CentOS 7 and CentOS 6 boxes.
$ vagrant box add centos/7 --provider=libvirt
==> box: Loading metadata for box 'centos/7'
box: URL: https://vagrantcloud.com/centos/7
==> box: Adding box 'centos/7' (v1902.01) for provider: libvirt
Add Ubuntu 20.04 Vagrant box:
vagrant box add generic/ubuntu2004 --provider=libvirt
Check the list of boxes presents locally.
$ vagrant box list
centos/7 (libvirt, 1902.01)
fedora/29-cloud-base (libvirt, 29.20181024.1)
generic/ubuntu1804 (libvirt, 1.9.8)
Step 4: Create Libvirt VM Vagrantfile
Vagrant needs a configuration file to get the details and settings for a VM to be created. Let’s create a single VM Vagrantfile.
mkdir ~/vagrant-vms
cd ~/vagrant-vms
Create a Vagrantfile with content similar to below:
# -*- mode: ruby -*-
# vi: set ft=ruby :
ENV['VAGRANT_DEFAULT_PROVIDER'] = 'libvirt'
Vagrant.configure("2") do |config|
##### DEFINE VM #####
config.vm.define "cent-01" do |config|
config.vm.hostname = "cent-01"
config.vm.box = "centos/7"
config.vm.box_check_update = false
#config.vm.network "private_network", ip: "192.168.18.9"
config.vm.provider :libvirt do |v|
v.memory = 1024
end
end
end
To bring the VM up, run:
$ vagrant up
Bringing machine 'cent-01' up with 'libvirt' provider...
==> cent-01: Creating image (snapshot of base box volume).
==> cent-01: Creating domain with the following settings...
==> cent-01: -- Name: centos-01_cent-01
==> cent-01: -- Domain type: kvm
==> cent-01: -- Cpus: 1
==> cent-01: -- Feature: acpi
==> cent-01: -- Feature: apic
==> cent-01: -- Feature: pae
==> cent-01: -- Memory: 1024M
==> cent-01: -- Management MAC:
==> cent-01: -- Loader:
==> cent-01: -- Nvram:
==> cent-01: -- Base box: centos/7
==> cent-01: -- Storage pool: default
==> cent-01: -- Image: /var/lib/libvirt/images/centos-01_cent-01.img (41G)
==> cent-01: -- Volume Cache: default
==> cent-01: -- Kernel:
==> cent-01: -- Initrd:
==> cent-01: -- Graphics Type: vnc
==> cent-01: -- Graphics Port: -1
==> cent-01: -- Graphics IP: 127.0.0.1
==> cent-01: -- Graphics Password: Not defined
==> cent-01: -- Video Type: cirrus
==> cent-01: -- Video VRAM: 9216
==> cent-01: -- Sound Type:
==> cent-01: -- Keymap: en-us
==> cent-01: -- TPM Path:
==> cent-01: -- INPUT: type=mouse, bus=ps2
==> cent-01: Creating shared folders metadata...
==> cent-01: Starting domain.
==> cent-01: Waiting for domain to get an IP address...
==> cent-01: Waiting for SSH to become available...
cent-01:
cent-01: Vagrant insecure key detected. Vagrant will automatically replace
cent-01: this with a newly generated keypair for better security.
cent-01:
cent-01: Inserting generated public key within guest...
cent-01: Removing insecure key from the guest if it's present...
cent-01: Key inserted! Disconnecting and reconnecting using new SSH key...
==> cent-01: Setting hostname...
==> cent-01: Configuring and enabling network interfaces...
cent-01: SSH address: 192.168.121.159:22
cent-01: SSH username: vagrant
cent-01: SSH auth method: private key
==> cent-01: Rsyncing folder: /home/jmutai/hacks/vagrant/labs/centos-01/ => /vagrant
Vagrant will create a Linux bridge on the host system.
$ brctl show virbr1
bridge name bridge id STP enabled interfaces
virbr1 8000.5254005351c7 yes virbr1-nic
vnet0
$ ip addr show dev virbr1
8: virbr1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default qlen 1000
link/ether 52:54:00:53:51:c7 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
Run virsh list to see if you’ll get a list of VMs.
$ virsh list
Id Name State
-----------------------------------
3 centos-01_cent-01 running
To ssh to the VM, use vagrant ssh command.
$ vagrant ssh
Last login: Fri Apr 19 07:40:17 2019 from 192.168.121.1
[[email protected] ~]$ cat /etc/redhat-release
CentOS Linux release 7.6.1810 (Core)
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 cent-01
HostName 192.168.121.159
User vagrant
Port 22
UserKnownHostsFile /dev/null
StrictHostKeyChecking no
PasswordAuthentication no
IdentityFile /home/jmutai/hacks/vagrant/labs/centos-01/.vagrant/machines/cent-01/libvirt/private_key
IdentitiesOnly yes
LogLevel FATAL
To redirect to output to your ssh configuration file, use:
vagrant ssh-config >>~/.ssh/config
Then use ssh command to log in with name configured above:
$ ssh cent-01
Last login: Fri Apr 19 07:40:42 2019 from 192.168.121.1
[[email protected] ~]$
To shut down the VM, run:
$ vagrant halt
==> cent-01: Halting domain…
To set VM to its initial state by cleaning all data, use vagrant destroy:
$ vagrant destroy
cent-01: Are you sure you want to destroy the 'cent-01' VM? [y/N] y
==> cent-01: Removing domain…
Step 5: Build your own Vagrant box (Optional)
You need packer installed for this to work. Check:
Then clone bento Github repo.
cd ~/
git clone https://github.com/chef/bento
cd bento/packer_templates
cd centos
To build Vagrant box of CentOS Stream 8 run:
$ packer build -only qemu -var "headless=true" centos-stream-8-x86_64.json
==> qemu: Gracefully halting virtual machine...
==> qemu: Converting hard drive...
==> qemu: Running post-processor: vagrant
==> qemu (vagrant): Creating Vagrant box for 'libvirt' provider
qemu (vagrant): Copying from artifact: ../builds/packer-centos-stream-8-x86_64-qemu/centos-stream-8-x86_64
qemu (vagrant): Compressing: Vagrantfile
qemu (vagrant): Compressing: box.img
qemu (vagrant): Compressing: metadata.json
Build 'qemu' finished.
==> Builds finished. The artifacts of successful builds are:
--> qemu: 'libvirt' provider box: ../builds/centos-stream-8.libvirt.box
If the build is successful, ready to import box files will be in the builds directory at the root of the repository.
$ vagrant box add builds/centos-stream-8.libvirt.box --name "centos-stream-8"
==> box: Box file was not detected as metadata. Adding it directly...
==> box: Adding box 'centos-stream-8' (v0) for provider:
==> box: Successfully added box 'centos-stream-8' (v0) for 'libvirt'!
Verify the box is installed.
vagrant box list