I've lately been trying to do more with Salt at work, but I'm still very much a novice with that tool. I thought it would be great to have a nice little portable lab environment where I could deploy a few lightweight VMs and practice managing them with Salt - without impacting any systems that are actually being used for anything. Along the way, I figured I'd leverage HashiCorp Vagrant to create and manage the VMs, which would provide a declarative way to define what the VMs should look like. The VM (or even groups of VMs) would be specified in a single file, and I'd bypass all the tedious steps of creating the virtual hardware, attaching the installation media, installing the OS, and performing the initial configuration. Vagrant will help me build up, destroy, and redeploy a development environment in a simple and repeatable way.
Also, because I'm a bit of a sadist, I wanted to do this all on my new Framework Chromebook. I might as well put my 32GB of RAM to good use, right?
It took a bit of fumbling, but this article describes what it took to get a Vagrant-powered VM up and running in the Linux Development Environment on my Chromebook (which is currently running ChromeOS v111 beta).
Install the prerequisites
There are are a few packages which need to be installed before we can move on to the Vagrant-specific stuff. It's quite possible that these are already on your system.... but if they aren't already present you'll have a bad problem1.
I'll be configuring Vagrant to use
libvirt to interface with the Kernel Virtual Machine (KVM) virtualization solution (rather than something like VirtualBox that would bring more overhead) so I'll need to install some packages for that as well:
1sudo apt install virt-manager libvirt-dev
And to avoid having to
sudo each time I interact with
libvirt I'll add myself to that group:
1sudo gpasswd -a $USER libvirt ; newgrp libvirt
And to avoid this issue I'll make a tweak to the
I'm also going to use
rsync to share a synced folder between the host and the VM guest so I'll need to make sure that's installed too:
1sudo apt install rsync
With that out of the way, I'm ready to move on to the business of installing Vagrant. I'll start by adding the HashiCorp repository:
1wget -O- https://apt.releases.hashicorp.com/gpg | gpg --dearmor | sudo tee /usr/share/keyrings/hashicorp-archive-keyring.gpg 2echo "deb [signed-by=/usr/share/keyrings/hashicorp-archive-keyring.gpg] https://apt.releases.hashicorp.com $(lsb_release -cs) main" | sudo tee /etc/apt/sources.list.d/hashicorp.list
I'll then install the Vagrant package:
I also need to install the
vagrant-libvirt plugin so that Vagrant will know how to interact with
1vagrant plugin install vagrant-libvirt
Create a lightweight VM
Now I can get to the business of creating my first VM with Vagrant!
Vagrant VMs are distributed as Boxes, and I can browse some published Boxes at app.vagrantup.com/boxes/search?provider=libvirt (applying the
provider=libvirt filter so that I only see Boxes which will run on my chosen virtualization provider). For my first VM, I'll go with something light and simple:
So I'll create a new folder to contain the Vagrant configuration:
And since I'm referencing a Vagrant Box which is published on Vagrant Cloud, downloading the config is as simple as:
1vagrant init generic/alpine38
That lets me know that
vagrant up the joint, I do need to make a quick tweak to the default Vagrantfile, which is what tells Vagrant how to configure the VM. By default, Vagrant will try to create a synced folder using NFS and will throw a nasty error when that (inevitably2) fails. So I'll open up the Vagrantfile to review and edit it:
Most of the default Vagrantfile is commented out. Here's the entirey of the configuration without the comments:
There's not a lot there, is there? Well I'm just going to add these two lines somewhere between the
The first line tells Vagrant not to bother checking to see if NFS is installed, and will use
rsync to share the local directory with the VM guest, where it will be mounted at
So here's the full Vagrantfile (sans-comments3, again):
With that, I'm ready to fire up this VM with
vagrant up! Vagrant will look inside
Vagrantfile to see the config, pull down the
generic/alpine38 Box from Vagrant Cloud, boot the VM, configure it so I can SSH in to it, and mount the synced folder:
1; vagrant up 2Bringing machine 'default' up with 'libvirt' provider... 3==> default: Box 'generic/alpine38' could not be found. Attempting to find and install... 4 default: Box Provider: libvirt 5 default: Box Version: >= 0 6==> default: Loading metadata for box 'generic/alpine38' 7 default: URL: https://vagrantcloud.com/generic/alpine38 8==> default: Adding box 'generic/alpine38' (v4.2.12) for provider: libvirt 9 default: Downloading: https://vagrantcloud.com/generic/boxes/alpine38/versions/4.2.12/providers/libvirt.box 10 default: Calculating and comparing box checksum... 11==> default: Successfully added box 'generic/alpine38' (v4.2.12) for 'libvirt'! 12==> default: Uploading base box image as volume into Libvirt storage... 13[...] 14==> default: Waiting for domain to get an IP address... 15==> default: Waiting for machine to boot. This may take a few minutes... 16 default: SSH address: 192.168.121.41:22 17 default: SSH username: vagrant 18 default: SSH auth method: private key 19[...] 20 default: Key inserted! Disconnecting and reconnecting using new SSH key... 21==> default: Machine booted and ready! 22==> default: Rsyncing folder: /home/john/projects/vagrant-alpine/ => /vagrant
And then I can use
vagrant ssh to log in to the new VM:
I can also verify that the synced folder came through as expected:
Once I'm finished poking at this VM, shutting it down is as easy as:
And if I want to clean up and remove all traces of the VM, that's just:
Create a heavy VM, as a treat
Having proven to myself that Vagrant does work on a Chromebook, let's see how it does with a slightly-heavier VM.... like Windows 11.
Windows 11 makes for a pretty hefty VM which will require significant storage space. My Chromebook's Linux environment ran out of storage space the first time I attempted to deploy this guy. Fortunately ChromeOS makes it easy to allocate more space to Linux (Settings > Advanced > Developers > Linux development environment > Disk size). You'll probably need at least 30GB free to provision this VM.
Again, I'll create a new folder to hold the Vagrant configuration and do a
And, again, I'll edit the Vagrantfile before starting the VM. This time, though, I'm adding a few configuration options to tell
libvirt that I'd like more compute resources than the default 1 CPU and 512MB RAM4:
Now it's time to bring it up. This one's going to take A While as it syncs the ~12GB Box first.
Eventually it should spit out that lovely Machine booted and ready! message and I can log in! I can do a
vagrant ssh again to gain a shell in the Windows environment, but I'll probably want to interact with those sweet sweet graphics. That takes a little bit more effort.
First, I'll use
virsh -c qemu:///system list to see the running VM(s):
Then I can tell
virt-viewer that I'd like to attach a session there:
1virt-viewer -c qemu:///system -a vagrant-win11_default
I log in with the default password
vagrant, and I'm in Windows 11 land!
Well that about does it for a proof-of-concept. My next steps will be exploring multi-machine Vagrant environments to create a portable lab environment including machines running several different operating systems so that I can learn how to manage them effectively with Salt. It should be fun!
NFS doesn't work properly from within an LXD container, like the ChromeOS Linux development environment. ↩︎
Through the magic of
egrep -v "^\s*(#|$)" $file. ↩︎
Note here that
libvirt.memoryis specified in MB. Windows 11 boots happily with 4096 MB of RAM.... and somewhat less so with just 4 MB. Ask me how I know... ↩︎