Vagrant
Vagrant is a must have CLI tool to manage local virtual machines using VirtualBox (or VMware Fusion or they-name-it). You can script every aspect of creating, provisioning, saving and destroying VMs. This makes this tool perfect for DevOps testing locally on your machine or even out in a cloud.
See the Vagrant Documentation for a primer.
Installation
The installation process is well outlined at the Download Vagrant page.
For macOS users the simplest is to use brew as Vagrant is a cask and there's bash completion formula. Just run:
brew install vagrant vagrant-completion
VM config examples
@TODO
Tips & Tricks / How to...
Change names (VM name, hostname, ...)
There are at least the following levels of naming a virtual server depending on the context:
- Machine Name: The name of the virtual server when running
vagrant status
or that you see when starting the VM:Bringing machine 'label' up with 'virtualbox' provider...
. - VM Name: The name of the underlying VirtualBox Machine that you see in the
Virtualbx GUI Client and that is used as the name for its subdir in your
VirtualBox VMs
directory or that you see when runningVBoxManage list vms
- Hostname: The hostname that is set within the virtual machine AKA the running guest OS
The question inherently arises: How are these set by default and how can I
customize them?
Well the
documentation is
not that clear about all this but fear not, you're covered with systematic
examples below.
All these examples are run in a project directory named "myproject" using Vagrant-2.2.18 on VirtualBox-6.1.26r145957.
Example 1: All defaults, e.g. only specifying the base box to use
Vagrant.configure("2") do |config|
config.vm.box = "geerlingguy/rockylinux8"
end
Result:
Machine Name | VM Name | Guest OS Nostname $(hostname -f) |
---|---|---|
default | myproject_default_1632646458961_81073 | localhost |
Discussion:
Vagrant chooses <DIRECTORY>_<MACHINE_NAME>_<TIMESTAMP>_<RANDOM_NUMBER>
unless explicitly
set, see next examples. The hostname seems to be unchanged, e.g. the
hostname of the basebox, localhost in the example.
Example 2: Explicitly define a VM and set a machine name
Vagrant.configure("2") do |config|
config.vm.box = "geerlingguy/rockylinux8"
# Explicitly define a vm; first argument is the machine name
config.vm.define "webserver"
end
Result:
Machine Name | VM Name | Guest OS Nostname $(hostname -f) |
---|---|---|
webserver | myproject_webserver_1632646458961_81073 | localhost |
Discussion: Now the default machine name has been overwritten with
webserver
. This also opens the door to mult-machine setups. As you can see
the new machine name is also found in the generated vm name that is visible
when running VBoxManage list vms
or in the VirtualBox GUI client.
Example 3: Set the hostname of the Guest OS
Vagrant.configure("2") do |config|
config.vm.box = "geerlingguy/rockylinux8"
# Explicitly define a vm; first argument is the machine name
config.vm.define "webserver"
config.vm.hostname = "web01.test.com"
end
Result:
Machine Name | VM Name | Guest OS Nostname $(hostname -f) |
---|---|---|
webserver | myproject_webserver_1632646458961_81073 | web01.test.com |
Discussion: Vagrant now sets the hostname within the guest OS to the specified value:
[vagrant@web01 ~]$ hostname -s
web01
[vagrant@web01 ~]$ hostname -f
web01.test.com
Example 4: Set the hostname of the Guest OS
Vagrant.configure("2") do |config|
config.vm.box = "geerlingguy/rockylinux8"
# Explicitly define a vm; first argument is the machine name
config.vm.define "webserver"
config.vm.hostname = "web01.test.com"
config.vm.provider :virtualbox do |vb|
vb.name = "webserver01"
end
end
Result:
Machine Name | VM Name | Guest OS Nostname $(hostname -f) |
---|---|---|
webserver | webserver01 | web01.test.com |
Discussion: This example, in addition, is setting the name on the
virtualbox provider object, which results in a renamed VM. The VM no longer
has its name generated as described in example 1, but the name is now set
explicitly, see GUI client or VBoxManage list vms
.
But wait... there's one more! Instead of setting name
on the provider
object, it's possible to have Vagrant call VBoxManage
and have it set the
name. This overrides all of the previous methods:
config.vm.provider :virtualbox do |vb|
vb.name = "webserver01"
vb.customize ["modifyvm", :id, "--name", "web01"]
end
web01
.
Conclusion
It makes sense to use of these powerful possibilities of naming things.
Especially it is useful to use them to namespace the virtual machines because
when approaching the setup from the VM perspective you can map the VM instance
to a project and the servers there in. Therefore if you set it to an absolute
name using VBoxManage
, I'd suggest to namespace it to the project it belongs
to, something like "myproject_webserver01" or something like that.
Change machine settings like RAM, network cards, ...
These configuration options are provider-specific. For VirtualBox have a look on
the respective page in the
documentation.
Summarized with two examples, it's possible to set almost everything by calling
VBoxManage
from within the Vagrantfile. The vb.customize directive calls
VBoxManage
and the contents of the array specified as its argument are passed
straight to it. See VBoxManage --help
for all the possible targets - there a
lot!
Example modifying apects of a virtualbox machine
config.vm.provider "virtualbox" do |vb|
vb.customize ["modifyvm", :id, "--cpuexecutioncap", "50"]
vb.customize ["modifyvm", :id, "--natdnshostresolver1", "on"]
vb.customize ["modifyvm", :id, "--memory", "384"]
vb.customize ["modifyvm", :id, "--nic3", "intnet"]
vb.customize ["modifyvm", :id, "--nic4", "intnet"]
end
# There are some convenience shortcuts for memory and CPU settings:
config.vm.provider "virtualbox" do |vb|
vb.memory = 1024
vb.cpus = 2
end
Setting a fixed port for SSH forwwards
Normally the ssh from the guest is automatically forwarded to port 2222 on the
host. When port the latter port is already in use for another running VM, the
next free post >2222 is choesen. This makes the port dependent of the order you
start the VMs. While most of the time this is not a problem, you sometimes still
want a fixed set of IPs for a project. Add this to your Vagrantfile
for each
machine you like to fix the forwarded SSH port:
```ruby
config.vm.network "forwarded_port", guest: 22, host: 12345, id: "ssh"
```
Source was this ticket and this blog entry.