Testing environment setup using Vagrant

Setting up a test environment with many different operating systems and versions can be a time consuming task. Installing the different operating systems and configuring them for tests or development can take up a lot of time. Vagrant makes this job simpler, by making it easy to setup virtual machines for testing and development.

Vagrant is a simple but powerful tool to create and manage VMs for testing and development. The easy interface allows to create, start, stop or destroy VMs with a single command. Vagrant is a utility which allows you to manage VMs but it is not a hypervisor itself. With vagrant it is possible to automate the setup of a VM within a number of hypervisors like Virtualbox.

Install vagrant

To use vagrant, a supported hyperviser needs to be installed as well as vagrant itself. The easiest setup to start with is to install Virtualbox via your system’s package manager. In the following command for Debian based systems, vagrant and Virtualbox are both installed.

$ sudo apt-get install virtualbox vagrant

Starting the first VM

With vagrant, VMs are created from VM images which can be directly downloaded from vagrant. Such VM images are called “boxes” and can be found directly from the public Vagrant box catalog. To start creating your first VM, create a new directory to work in. This directory is called the vagrant project directory. Inside this vagrant project directory, execute the following command.

$ vagrant init centos/7
A `Vagrantfile` has been placed in this directory. You are now
ready to `vagrant up` your first virtual environment! Please read
the comments in the Vagrantfile as well as documentation on
`vagrantup.com` for more information on using Vagrant.

The “init” command will create the “Vagrantfile” which is the configuration file of the vagrant project. The “centos/7” in the command is the name of the CentOS 7 box image from the Vagrant box catalog. This box image will be used as the base of the VM.

To start the VM using vagrant, just run the following command. Downloading the box image separately is not required, as vagrant will download it automatically if it was not already downloaded.

$ vagrant up
Bringing machine 'default' up with 'virtualbox' provider...
==> default: Box 'centos/7' could not be found. Attempting to find and install...
    default: Box Provider: virtualbox
    default: Box Version: >= 0
==> default: Loading metadata for box 'centos/7'
    default: URL: https://app.vagrantup.com/centos/boxes/7
==> default: Adding box 'centos/7' (v1611.01) for provider: virtualbox
    default: Downloading: https://app.vagrantup.com/centos/boxes/7/versions/1611.01/providers/virtualbox.box
==> default: Successfully added box 'centos/7' (v1611.01) for 'virtualbox'!
==> default: Importing base box 'centos/7'...
==> default: Matching MAC address for NAT networking...
==> default: Checking if box 'centos/7' is up to date...
==> default: Setting the name of the VM: vagrant_default_1486387809957_24475
==> default: Clearing any previously set network interfaces...
==> default: Preparing network interfaces based on configuration...
    default: Adapter 1: nat
==> default: Forwarding ports...
    default: 22 (guest) => 2222 (host) (adapter 1)
==> default: Booting VM...
==> default: Waiting for machine to boot. This may take a few minutes...
    default: SSH address: 127.0.0.1:2222
    default: SSH username: vagrant
    default: SSH auth method: private key
    default: 
    default: Vagrant insecure key detected. Vagrant will automatically replace
    default: this with a newly generated keypair for better security.
    default: 
    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: Machine booted and ready!
==> default: Checking for guest additions in VM...
    default: No guest additions were detected on the base box for this VM! Guest
    default: additions are required for forwarded ports, shared folders, host only
    default: networking, and more. If SSH fails on this machine, please install
    default: the guest additions and repackage the box to continue.
    default: 
    default: This is not an error message; everything may continue to work properly,
    default: in which case you may ignore this message.
==> default: Rsyncing folder: /path/to/vagrant/project/ => /vagrant

The above “up” command instructs vagrant to start up the VM. On the first start, vagrant will download the box to start from. The box is stored in the “.vagrant/” directory structure in your user’s home directory. If the box is used again on a different project, it is not downloaded a second time but reused. After the download, vagrant adds a VM to the hypervisor (in this case Virtualbox), adds some configuration and starts the VM.

Virtualbox starts the VM, the initial port forwarding for ssh is set and vagrant creates an ssh-key to login to the VM. The VM is now running and ready to be used. Connecting to the VM via SSH can be done directly from vagrant using the ssh command.

$ vagrant ssh
[vagrant@localhost ~]$ 

A manual connection to the VM via ssh can also be established using the ssh port from vagrant (in this example 2222) and the ssh-key vagrant created for this VM.

$ ssh vagrant@localhost -p 2222 -i .vagrant/machines/default/virtualbox/private_key 
The authenticity of host '[localhost]:2222 ([127.0.0.1]:2222)' can't be established.
ECDSA key fingerprint is SHA256:Do0ZOirosypupRJNBrgBDWIsbHQr6kily32RjPwwO/E.
Are you sure you want to continue connecting (yes/no)? yes
Warning: Permanently added '[localhost]:2222' (ECDSA) to the list of known hosts.
[vagrant@localhost ~]$ 

The user to login is vagrant, the port is from the “vagrant up” output and the ssh-key is created by vagrant for this VM.

To create a matching ssh configuration for the started VM, vagrant offers the convenient command “vagrant ssh-config”.

$ vagrant ssh-config
Host default
  HostName 127.0.0.1
  User vagrant
  Port 2222
  UserKnownHostsFile /dev/null
  StrictHostKeyChecking no
  PasswordAuthentication no
  IdentityFile "/path/to/vagrant/project/.vagrant/machines/default/virtualbox/private_key"
  IdentitiesOnly yes
  LogLevel FATAL

To manage the VM, vagrant offers a number of simple commands to stop a VM (vagrant halt) or to delete a VM to start over (vagrant destroy). When the VM is destroyed, the box image remains in place and does not need to be downloaded again.

$ vagrant status
Current machine states:

default                   running (virtualbox)

The VM is running. To stop this VM, you can run `vagrant halt` to
shut it down forcefully, or you can run `vagrant suspend` to simply
suspend the virtual machine. In either case, to restart it again,
simply run `vagrant up`.

The status command shows the status of the VM together with a short explanation of how to manage the VM.

Setup Multiple VM’s

With vagrant it is also possible to manage multiple VMs in one project. To do this, the Vagrantfile can be modified to manage multiple VMs. The created Vagrantfile shows the following configuration items. Most of the comment lines have been removed in the following listing to reduce it to the minimum.

Vagrant.configure(2) do |config|

  # Every Vagrant development environment requires a box. You can search for
  # boxes at https://app.vagrantup.com/boxes/search.
  config.vm.box = "centos/7"

end

The configuration above defined one VM with the name default and the box image “centos/7”.

To configure two VMs in the vagrant project, replace the “config.vm.box” line with the following.

Vagrant.configure(2) do |config|

  # Every Vagrant development environment requires a box. You can search for
  # boxes at https://app.vagrantup.com/boxes/search.
  config.vm.define "centos7" do |c7|
    c7.vm.box = "centos/7"
  end

  config.vm.define "centos6" do | c6|
    c6.vm.box = "centos/6"
  end

end

The configuration is now split into two VM definitions using the “config.vm.define” statements. The first statement configures the CentOS 7 VM which has the name “centos7” instead of “default”. The second configures a CentOS 6 VM with the name “centos6”.

A “vagrant status” will now show two VMs configured in this project instead of one.

$ vagrant status
Current machine states:

centos7                   not created (virtualbox)
centos6                   not created (virtualbox)

This environment represents multiple VMs. The VMs are all listed
above with their current state. For more information about a specific
VM, run `vagrant status NAME`.

Additionally to the way the VM was managed before, the name of the VM as specified in the configuration (and shown in the “status” output) needs to be added to the vagrant commands to address a specific VM.

$ vagrant up centos7
Bringing machine 'centos7' up with 'virtualbox' provider...
==> centos7: Importing base box 'centos/7'...
==> centos7: Matching MAC address for NAT networking...
==> centos7: Checking if box 'centos/7' is up to date...
==> centos7: Setting the name of the VM: vagrant_centos7_1486456659627_65580
==> centos7: Clearing any previously set network interfaces...
==> centos7: Preparing network interfaces based on configuration...
    centos7: Adapter 1: nat
==> centos7: Forwarding ports...
    centos7: 22 (guest) => 2222 (host) (adapter 1)
==> centos7: Booting VM...
==> centos7: Waiting for machine to boot. This may take a few minutes...
    centos7: SSH address: 127.0.0.1:2222
    centos7: SSH username: vagrant
    centos7: SSH auth method: private key
    centos7: 
    centos7: Vagrant insecure key detected. Vagrant will automatically replace
    centos7: this with a newly generated keypair for better security.
    centos7: 
    centos7: Inserting generated public key within guest...
    centos7: Removing insecure key from the guest if it's present...
    centos7: Key inserted! Disconnecting and reconnecting using new SSH key...
==> centos7: Machine booted and ready!
==> centos7: Checking for guest additions in VM...
    centos7: No guest additions were detected on the base box for this VM! Guest
    centos7: additions are required for forwarded ports, shared folders, host only
    centos7: networking, and more. If SSH fails on this machine, please install
    centos7: the guest additions and repackage the box to continue.
    centos7: 
    centos7: This is not an error message; everything may continue to work properly,
    centos7: in which case you may ignore this message.
==> centos7: Rsyncing folder: /media/gerhard/Data/vagrant/ => /vagrant

The above command explicitly instructs vagrant to start up the VM named “centos7”.

Additional settings

The Vagrantfile is a mighty tool to control and configure the VMs. The hostname of the VM can be set using the following statement in the VM configuration.

Vagrant.configure(2) do |config|

  # Every Vagrant development environment requires a box. You can search for
  # boxes at https://app.vagrantup.com/boxes/search.
  config.vm.define "centos7" do |c7|
    c7.vm.box = "centos/7"
    c7.vm.hostname = "centos7"
  end

  config.vm.define "centos6" do | c6|
    c6.vm.box = "centos/6"
  end

end

The Vagrant file allows for many more settings to be defined to configure the VM at startup or creation. A list of Vagrantfile options to configure a VM can be found on the Vagrant Machine Settings page. If you still miss functionality, the vagrant plugins are the place to look at.

Vagrant plugins can be found using the following command. It will list all the “vagrant-” ruby gems.

$ gem list --remote vagrant-

*** REMOTE GEMS ***
...
vagrant-proxmox (0.0.10)
vagrant-proxy (0.0.1)
vagrant-proxyconf (1.5.2)
vagrant-proxyssh (0.2.0)
vagrant-puppet-fact-generator (0.1.1)
vagrant-puppet-install (4.1.0)
vagrant-puppet-library (0.1.0)
vagrant-puppet-module-registry (0.2.1)
vagrant-puppet-modules (0.0.2)
vagrant-puppet-scp (0.0.2)
vagrant-puppetconf (0.2.2)
vagrant-puppetfile (0.3.0)
vagrant-pushbullet (0.0.3)
vagrant-pushover (1.1.1)
vagrant-putty (0.0.2)
...

The list of available plugins is long. To get details about one of the gems, add the “-d” option to display detailed information of. I suggest to pick one or only a few when adding the “-d” option.

$ gem list -d --remote vagrant-proxyconf

*** REMOTE GEMS ***

vagrant-proxyconf (1.5.2)
    Author: Teemu Matilainen
    Homepage: http://tmatilai.github.io/vagrant-proxyconf/

    A Vagrant plugin that configures the virtual machine to use proxy
    servers

The output provides a link to the homepage as well as a short description. The homepage usually provides more details about the usage of the plugin and its capabilities. The above listed plugin will let you configure a proxy server for the VM while starting it up.

To install the plugin, use the following vagrant command.

$ vagrant plugin install vagrant-proxyconf
Installing the 'vagrant-proxyconf' plugin. This can take a few minutes...
Installed the plugin 'vagrant-proxyconf (1.5.2)'!

Refer to the plugin homepage and documentation to find out how to use the plugin.


Read more of my posts on my blog at https://blog.tinned-software.net/.

This entry was posted in Linux Administration, Virtualisation and tagged , , , , . Bookmark the permalink.