Vagrant Logo

Vagrant is an open source solution designed for automatic configuration of virtual machines and containers. Vagrant can configure RAM amount, CPU count, network settings, and hostname. It can then automatically execute configuration management scripts (Ansible, Chef, Puppet, etc.). These scripts handle package installation and configuration via SSH. The first version was released on March 8, 2010, and was developed by Mitchell Hashimoto and John Bender in Ruby.

Vagrant is natively compatible with the following virtualization services:

  • VirtualBox
  • Hyper-V
  • Docker
  • VMware
  • Amazon EC2

Additional providers can be added through plugins.

Installation

To install Vagrant, go to the official website (https://www.vagrantup.com/downloads.html), download the installer for your system, and run it. The goal is to have access to the “vagrant” command via the terminal (on Windows you will need to add Vagrant to your global PATH).

Commands

To use Vagrant you must create a “project”, called “boxes”. A list of community-shared boxes is available at http://www.vagrantbox.es/.

# list boxes on the system
vagrant box list
# add a box
vagrant box add my_box_name box_url
# remove a box
vagrant box remove my_box_name
# package the vagrant project
vagrant package
# initialize the vagrant project
vagrant init box_name
# start the virtual machine
vagrant up
# test if the machine works by connecting via SSH
vagrant ssh

Configuring Virtual Machines

Vagrant project configuration is done in the “Vagrantfile”. Here are some configuration examples:

nodes = [
    { :hostname => 'ex5web', :ip => '192.168.0.42', :box => 'precise32' },
    { :hostname => 'ex5db', :ip => '192.168.0.43', :box => 'precise32', :ram => 512 }
]
Vagrant.configure("2") do |config|
    nodes.each do |node|
    config.vm.define node[:hostname] do |nodeconfig|
        nodeconfig.vm.box = "precise32"
        nodeconfig.vm.hostname = node[:hostname] + ".box"
        nodeconfig.vm.network :private_network, ip: node[:ip]
        memory = node[:ram] ? node[:ram] : 256;
        nodeconfig.vm.provider :virtualbox do |vb|
        vb.customize [
            "modifyvm", :id,
            "--cpuexecutioncap", "50",
            "--memory", memory.to_s,
        ]
    end
    end
    end
    config.vm.provision "ansible" do |ansible|
        ansible.playbook = "playbook.yml"
    end
end

The “nodes” section configures an array of machines to create with custom variables – here we configure their hostnames, IPs, RAM, and the image to use.

nodes = [
    { :hostname => 'ex5web', :ip => '192.168.0.42', :box => 'precise32' },
    { :hostname => 'ex5db', :ip => '192.168.0.43', :box => 'precise32', :ram => 512 }
]

The central section, “Vagrant.configure”, applies the node array parameters and creates each machine with its associated settings.

Vagrant.configure("2") do |config|
    nodes.each do |node|
        config.vm.define node[:hostname] do |nodeconfig|
        nodeconfig.vm.box = "precise32"
        nodeconfig.vm.hostname = node[:hostname] + ".box"
        nodeconfig.vm.network :private_network, ip: node[:ip]
        memory = node[:ram] ? node[:ram] : 256;
        nodeconfig.vm.provider :virtualbox do |vb|
            vb.customize [
                "modifyvm", :id,
                "--cpuexecutioncap", "50",
                "--memory", memory.to_s,
            ]
        end
    end
end

The “ansible” section configures the Ansible playbook to use on the previously created machines.

config.vm.provision "ansible" do |ansible|
    ansible.playbook = "playbook.yml"
end

Configuration Management

The principle of configuration management is to have a script executed via SSH on virtual machines after their creation by Vagrant. In this example we will use Ansible as the configuration manager. For more info on Ansible (see the Ansible introduction article).

Vagrant.configure("2") do |config|
    #
    # Run Ansible from the Vagrant Host
    #
    config.vm.provision "ansible" do |ansible|
        ansible.playbook = "playbook.yml"
    end
end

The line config.vm.provision "ansible" do |ansible| indicates that this section will use Vagrant’s Ansible module. The line ansible.playbook = "playbook.yml" tells Vagrant which Ansible script to execute.

Conclusion

Vagrant makes it easy to create a large number of virtual machines and containers. It complements configuration managers, which only handle service configuration on machines and do not manage virtual machine creation at all. Furthermore, the community is active and shares many resources.

More Info