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:
Step 2: Installing Vagrant plugin
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:
- Rocky / AlmaLinux / CentOS Stream 9:
sudo dnf config-manager --set-enabled crb
sudo yum -y install ruby libvirt-devel
sudo yum -y groupinstall "Development Tools"
- Rocky / AlmaLinux 8:
sudo dnf config-manager --set-enabled powertools
sudo yum -y install ruby 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...
Fetching formatador-1.1.0.gem
Fetching fog-core-2.6.0.gem
Fetching fog-xml-0.1.5.gem
Fetching fog-json-1.2.0.gem
Fetching fog-libvirt-0.13.2.gem
Fetching diffy-3.4.3.gem
Fetching vagrant-libvirt-0.12.2.gem
Installed the plugin 'vagrant-libvirt (0.12.2)'!
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 the commands:
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 (x.y.z, 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 Ubuntu 22.04 and Debian 12 boxes.
$ vagrant box add generic/debian12 --provider=libvirt
==> box: Loading metadata for box 'generic/debian12'
box: URL: https://vagrantcloud.com/api/v2/vagrant/generic/debian12
==> box: Adding box 'generic/debian12' (v4.3.12) for provider: libvirt (amd64)
box: Downloading: https://vagrantcloud.com/generic/boxes/debian12/versions/4.3.12/providers/libvirt/amd64/vagrant.box
box: Calculating and comparing box checksum...
==> box: Successfully added box 'generic/debian12' (v4.3.12) for 'libvirt (amd64)'!
Add Ubuntu 22.04 Vagrant box:
$ vagrant box add generic/ubuntu2204 --provider=libvirt
==> box: Loading metadata for box 'generic/ubuntu2204'
box: URL: https://vagrantcloud.com/api/v2/vagrant/generic/ubuntu2204
==> box: Adding box 'generic/ubuntu2204' (v4.3.12) for provider: libvirt (amd64)
box: Downloading: https://vagrantcloud.com/generic/boxes/ubuntu2204/versions/4.3.12/providers/libvirt/amd64/vagrant.box
box: Calculating and comparing box checksum...
==> box: Successfully added box 'generic/ubuntu2204' (v4.3.12) for 'libvirt (amd64)'!
Check the list of boxes presents locally.
$ vagrant box list
generic/debian12 (libvirt, 4.3.12, (amd64))
generic/ubuntu2204 (libvirt, 4.3.12, (amd64))
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
vim Vagrantfile
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 "debian-12" do |config|
config.vm.hostname = "debian12"
config.vm.box = "generic/debian12"
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 'debian-12' up with 'libvirt' provider...
[fog][WARNING] Unrecognized arguments: libvirt_ip_command
==> debian-12: Uploading base box image as volume into Libvirt storage...
==> debian-12: Creating image (snapshot of base box volume).
==> debian-12: Creating domain with the following settings...
==> debian-12: -- Name: vagrant-vms_debian-12
==> debian-12: -- Description: Source: /home/rocky/vagrant-vms/Vagrantfile
==> debian-12: -- Domain type: kvm
==> debian-12: -- Cpus: 2
==> debian-12: -- Feature: acpi
==> debian-12: -- Feature: apic
==> debian-12: -- Feature: pae
==> debian-12: -- Clock offset: utc
==> debian-12: -- Memory: 1024M
==> debian-12: -- Base box: generic/debian12
==> debian-12: -- Storage pool: default
==> debian-12: -- Image(vda): /var/lib/libvirt/images/vagrant-vms_debian-12.img, virtio, 128G
==> debian-12: -- Disk driver opts: cache='default'
==> debian-12: -- Graphics Type: vnc
==> debian-12: -- Video Type: cirrus
==> debian-12: -- Video VRAM: 256
==> debian-12: -- Video 3D accel: false
==> debian-12: -- Keymap: en-us
==> debian-12: -- TPM Backend: passthrough
==> debian-12: -- INPUT: type=mouse, bus=ps2
==> debian-12: Creating shared folders metadata...
==> debian-12: Starting domain.
==> debian-12: Domain launching with graphics connection settings...
==> debian-12: -- Graphics Port: 5900
==> debian-12: -- Graphics IP: 127.0.0.1
==> debian-12: -- Graphics Password: Not defined
==> debian-12: -- Graphics Websocket: 5700
==> debian-12: Waiting for domain to get an IP address...
==> debian-12: Waiting for machine to boot. This may take a few minutes...
debian-12: SSH address: 192.168.121.75:22
debian-12: SSH username: vagrant
debian-12: SSH auth method: private key
debian-12:
debian-12: Vagrant insecure key detected. Vagrant will automatically replace
debian-12: this with a newly generated keypair for better security.
debian-12:
debian-12: Inserting generated public key within guest...
debian-12: Removing insecure key from the guest if it's present...
debian-12: Key inserted! Disconnecting and reconnecting using new SSH key...
==> debian-12: Machine booted and ready!
==> debian-12: Setting hostname...
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
---------------------------------------
1 vagrant-vms_debian-12 running
To ssh to the VM, use vagrant ssh command.
vagrant ssh
cat /etc/redhat-release
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 debian-12
HostName 192.168.121.75
User vagrant
Port 22
UserKnownHostsFile /dev/null
StrictHostKeyChecking no
PasswordAuthentication no
IdentityFile /home/rocky/vagrant-vms/.vagrant/machines/debian-12/libvirt/private_key
IdentitiesOnly yes
LogLevel FATAL
PubkeyAcceptedKeyTypes +ssh-rsa
HostKeyAlgorithms +ssh-rsa
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 debian-12
vagrant@debian12:~$
To shut down the VM, run:
vagrant@debian12:~$ exit
$ vagrant halt
==> debian-12: Attempting graceful shutdown of VM...
To set VM to its initial state by cleaning all data, use vagrant destroy:
$ vagrant destroy
debian-12: Are you sure you want to destroy the 'debian-12' VM? [y/N] y
==> debian-12: Removing domain...
==> debian-12: Deleting the machine folder
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/scripts
cd ubuntu
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
Other articles: