Rocky Linux is the community-driven successor to CentOS, built from RHEL sources. It gives you the same enterprise-grade stability without the licensing costs, making it a solid choice for development VMs and test environments. Vagrant makes spinning up and tearing down Rocky Linux VMs fast and repeatable across different hypervisors.
This guide covers running Rocky Linux 10 VMs with Vagrant using the official rockylinux/10 box from Vagrant Cloud. We cover VirtualBox, libvirt/KVM, and VMware Desktop providers, along with shell provisioning and multi-machine Vagrantfile examples.
Prerequisites
- A Linux, macOS, or Windows workstation with at least 4GB free RAM
- Vagrant installed – see How to Install Vagrant on Ubuntu if you haven’t set it up yet
- At least one supported provider: VirtualBox, libvirt/KVM, or VMware Desktop
- For libvirt/KVM: a Linux host with KVM installed and configured
Step 1: Add the Rocky Linux 10 Vagrant Box
The official rockylinux/10 box on Vagrant Cloud supports libvirt, VirtualBox, and VMware Desktop providers on both amd64 and arm64 architectures. Download the box for your preferred provider.
For libvirt/KVM:
vagrant box add rockylinux/10 --provider=libvirt
For VirtualBox:
vagrant box add rockylinux/10 --provider=virtualbox
For VMware Desktop:
vagrant box add rockylinux/10 --provider=vmware_desktop
Verify the box was downloaded:
$ vagrant box list
rockylinux/10 (libvirt, 0.0.0)
Step 2: Create a Vagrantfile for Rocky Linux 10
Create a project directory and initialize the Vagrantfile.
mkdir -p ~/vagrant/rocky10 && cd ~/vagrant/rocky10
Create the Vagrantfile:
vim Vagrantfile
Vagrantfile for libvirt/KVM
If you use Vagrant with libvirt as your provider, use this configuration:
# -*- mode: ruby -*-
# vi: set ft=ruby :
ENV['VAGRANT_DEFAULT_PROVIDER'] = 'libvirt'
Vagrant.configure("2") do |config|
config.vm.box = "rockylinux/10"
config.vm.hostname = "rocky10"
config.vm.box_check_update = false
# Private network for host-only access
config.vm.network "private_network", ip: "192.168.56.10"
config.vm.provider :libvirt do |v|
v.memory = 2048
v.cpus = 2
end
end
Vagrantfile for VirtualBox
For VirtualBox, the configuration is slightly different. You can set VirtualBox as your default Vagrant provider if you use it regularly:
# -*- mode: ruby -*-
# vi: set ft=ruby :
Vagrant.configure("2") do |config|
config.vm.box = "rockylinux/10"
config.vm.hostname = "rocky10"
config.vm.box_check_update = false
# Private network for host-only access
config.vm.network "private_network", ip: "192.168.56.10"
config.vm.provider "virtualbox" do |vb|
vb.gui = false
vb.memory = "2048"
vb.cpus = 2
vb.name = "rocky10"
end
end
Vagrantfile for VMware Desktop
VMware Desktop (Workstation or Fusion) requires the Vagrant VMware plugin:
vagrant plugin install vagrant-vmware-desktop
Then use this Vagrantfile:
# -*- mode: ruby -*-
# vi: set ft=ruby :
Vagrant.configure("2") do |config|
config.vm.box = "rockylinux/10"
config.vm.hostname = "rocky10"
config.vm.box_check_update = false
config.vm.provider "vmware_desktop" do |v|
v.vmx["memsize"] = "2048"
v.vmx["numvcpus"] = "2"
end
end
Step 3: Start the Rocky Linux 10 VM
From the project directory containing the Vagrantfile, bring up the VM:
vagrant up
Sample output for the libvirt provider:
$ vagrant up
Bringing machine 'default' up with 'libvirt' provider...
==> 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: rocky10_default
==> default: -- Domain type: kvm
==> default: -- Cpus: 2
==> default: -- Memory: 2048M
==> default: -- Base box: rockylinux/10
==> default: -- Storage pool: default
==> default: Creating shared folders metadata...
==> default: Starting domain.
==> default: Waiting for domain to get an IP address...
==> default: Waiting for SSH to become available...
default: Vagrant insecure key detected. Vagrant will automatically replace
default: this with a newly generated keypair for better security.
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: Setting hostname...
==> default: Configuring and enabling network interfaces...
Step 4: Connect to the VM
SSH into the running VM:
vagrant ssh
Verify the OS release:
$ cat /etc/os-release
NAME="Rocky Linux"
VERSION="10.0 (Pelican)"
ID="rocky"
ID_LIKE="rhel centos fedora"
VERSION_ID="10.0"
PLATFORM_ID="platform:el10"
PRETTY_NAME="Rocky Linux 10.0 (Pelican)"
ANSI_COLOR="0;32"
CPE_NAME="cpe:/o:rocky:rocky:10::baseos"
HOME_URL="https://rockylinux.org/"
VENDOR_NAME="RESF"
VENDOR_URL="https://resf.org/"
$ cat /etc/redhat-release
Rocky Linux release 10.0 (Pelican)
Type exit to disconnect from the VM.
Step 5: Vagrantfile with Shell Provisioning
Vagrant supports provisioning scripts that run automatically when the VM is first created. This saves time when you need the same packages installed every time you spin up a new VM.
Here is a Vagrantfile that installs common development tools and enables the firewall on first boot:
# -*- mode: ruby -*-
# vi: set ft=ruby :
ENV['VAGRANT_DEFAULT_PROVIDER'] = 'libvirt'
Vagrant.configure("2") do |config|
config.vm.box = "rockylinux/10"
config.vm.hostname = "rocky10-dev"
config.vm.box_check_update = false
config.vm.network "private_network", ip: "192.168.56.10"
# Forward port 8080 on guest to 8080 on host
config.vm.network "forwarded_port", guest: 8080, host: 8080
config.vm.provider :libvirt do |v|
v.memory = 2048
v.cpus = 2
end
# Shell provisioning - runs on first 'vagrant up'
config.vm.provision "shell", inline: <<-SHELL
dnf update -y
dnf install -y vim git curl wget tar unzip net-tools bind-utils
systemctl enable --now firewalld
echo "Provisioning complete"
SHELL
end
To re-run the provisioning script on an existing VM without destroying it:
vagrant provision
Step 6: Multi-Machine Vagrantfile
Vagrant can manage multiple VMs from a single Vagrantfile. This is useful for testing clustered setups, client-server architectures, or replication scenarios. The following example creates three Rocky Linux 10 VMs on a shared private network:
# -*- mode: ruby -*-
# vi: set ft=ruby :
ENV['VAGRANT_DEFAULT_PROVIDER'] = 'libvirt'
NODES = [
{ name: "node1", ip: "192.168.56.11", memory: 2048, cpus: 2 },
{ name: "node2", ip: "192.168.56.12", memory: 2048, cpus: 2 },
{ name: "node3", ip: "192.168.56.13", memory: 1024, cpus: 1 },
]
Vagrant.configure("2") do |config|
config.vm.box = "rockylinux/10"
config.vm.box_check_update = false
NODES.each do |node|
config.vm.define node[:name] do |n|
n.vm.hostname = node[:name]
n.vm.network "private_network", ip: node[:ip]
n.vm.provider :libvirt do |v|
v.memory = node[:memory]
v.cpus = node[:cpus]
end
n.vm.provision "shell", inline: <<-SHELL
dnf install -y vim net-tools
echo "#{node[:ip]} #{node[:name]}" >> /etc/hosts
SHELL
end
end
end
Bring up all three VMs at once:
vagrant up
Or start a specific node:
vagrant up node1
SSH into a specific node by name:
vagrant ssh node2
Common Vagrant Commands Reference
Here are the commands you will use regularly when working with Vagrant VMs:
| Command | Description |
|---|---|
vagrant up | Create and start the VM |
vagrant ssh | SSH into the running VM |
vagrant halt | Gracefully shut down the VM |
vagrant reload | Restart the VM and reload the Vagrantfile |
vagrant suspend | Save the VM state and stop it |
vagrant resume | Resume a suspended VM |
vagrant provision | Re-run provisioning scripts |
vagrant destroy | Stop and delete the VM |
vagrant status | Show the current VM status |
vagrant box list | List all downloaded Vagrant boxes |
To stop the VM without deleting it:
vagrant halt
To save the current VM state so you can resume later from exactly the same point:
vagrant suspend
When you are done and want to remove the VM entirely:
vagrant destroy -f
Conclusion
We set up Rocky Linux 10 VMs using Vagrant with libvirt/KVM, VirtualBox, and VMware Desktop providers, including shell provisioning and multi-machine configurations. Vagrant makes it straightforward to create reproducible development and test environments that you can share across your team using a single Vagrantfile.
For production-like environments, consider adding synced folders for code sharing, configuring bridged networking for full network access, and using Ansible or Puppet provisioners instead of shell scripts for complex setups.