Vagrant – build always same VMs

Vagrant is a tool for building complete development environments.

With an easy-to-use workflow and focus on automation, Vagrant lowers development environment setup time, increases development/production parity, and makes the “works on my machine” excuse a relic of the past.

Install

Check your distro most likely Ubuntu version candidate

apt-cache vagrant

Download from https://releases.hashicorp.com/vagrant/

wget https://releases.hashicorp.com/vagrant/1.8.1/vagrant_1.8.1_x86_64.deb
sudo dpkg -i vagrant_1.8.1_x86_64.deb
sudo apt-get update && sudo apt-get install -f   #to resolve missing dependencies if any

Install ruby is recommended as .vagrant file is using it

sudo apt-get install ruby
sudo gem install bundler
sudo gem update bundler    #if update needed

Getting started

Create Vagrant project, by creating Vagrantfile in your current directory
vagrant init
Add boxes (standard VMs from providers in Virtualbox, VMware or Hyper-V format)
vagrant box add hashicorp/precise64        #username: hashicorp boximage: precise64, this is preconfigured repository
#Box can be specified via URLs or local file paths, Virtualbox can only nest 32bit machines
vagrant box add --force ubuntu/14.04 https://cloud-images.ubuntu.com/vagrant/trusty/current/trusty-server-cloudimg-amd64-vagrant-disk1.box
vagrant box add --force ubuntu/14.04-i386 https://cloud-images.ubuntu.com/vagrant/precise/current/precise-server-cloudimg-i386-vagrant-disk1.boxvi
Configure Vagrantfile to use the box as your base system
Vagrant.configure("2") do |config|
 config.vm.box = "ubuntu/14.04-i386"
end
Power up your Vagrant box
vagrant up

Error:

Timed out while waiting for the machine to boot. This means that
Vagrant was unable to communicate with the guest machine within
the configured ("config.vm.boot_timeout" value) time period.

If you look above, you should be able to see the error(s) that
Vagrant had when attempting to connect to the machine. These errors
are usually good hints as to what may be wrong.

If you're using a custom box, make sure that networking is properly
working and you're able to connect to the machine. It is a common
problem that networking isn't setup properly in these boxes.
Verify that authentication configurations are also setup properly,
as well.

If the box appears to be booting properly, you may want to increase
the timeout ("config.vm.boot_timeout") value.

The error above is due to Virtualbox cannot run nested 64bit virtualbox VM. Spinning up a 64bit VM stops with an error that no 64bit CPU could be found.

piotr@vm-ubuntu64:~/git/vagrant$ vagrant up
Bringing machine 'default' up with 'virtualbox' provider...
==> default: Importing base box 'ubuntu/14.04-i386'...
==> default: Matching MAC address for NAT networking...
==> default: Setting the name of the VM: vagrant_default_1456318357740_51238
==> default: Clearing any previously set forwarded ports...
==> 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: Warning: Remote connection disconnect. Retrying...
    default: Warning: Remote connection disconnect. Retrying...
    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: The guest additions on this VM do not match the installed version of
    default: VirtualBox! In most cases this is fine, but in rare cases it can
    default: prevent things such as shared folders from working properly. If you see
    default: shared folder errors, please make sure the guest additions within the
    default: virtual machine match the version of VirtualBox you have installed on
    default: your host and reload your VM.
    default: 
    default: Guest Additions Version: 4.1.44
    default: VirtualBox Version: 4.3
==> default: Mounting shared folders...
    default: /vagrant => /home/piotr/git/vagrant
Ssh to the box
piotr@vm-ubuntu64:~/git/vagrant$ vagrant ssh
vagrant@vagrant-ubuntu-precise-32:~$ w
 13:08:35 up 15 min,  1 user,  load average: 0.06, 0.31, 0.54
USER     TTY      FROM              LOGIN@   IDLE   JCPU   PCPU WHAT
vagrant  pts/0    10.0.2.2         13:02    1.00s  4.63s  0.09s w
Shared directory between Vagrant VM and an hypervisor provider

Vagrant VM shares a directory mounted at /vagrant with the directory on the host containing your Vagrantfile

Delete Vagrant VM
vagrant destroy
Delete downloaded Vagrant VM image file
vagrant box remove
Build in provisioning

Vagrant can run from shared location script or from inline: Vagrant file shell provisioning commands.

vi ~/git/vagrant/bootstrap.sh     #create provisioning script
   #!/usr/bin/env bash
   export http_proxy=http://username:password@proxyserver.local:8080
   export https_proxy=$http_proxy 
   apt-get update
   apt-get install -y apache2
   if ! [ -L /var/www ]; then
      rm -rf /var/www
   ln -fs /vagrant /var/www      #configures that shared directory will be Apache DocumentRoot directory
   fi

vi ~/git/vagrant/Vagrantfile   #configure Vagrant to run this shell script when setting up our machine
   Vagrant.configure("2") do |config|
      config.vm.box = "ubuntu/14.04-i386"
      #the provision line tells Vagrant to use the shell provisioner to setup the machine
      config.vm.provision :shell, path: "bootstrap.sh"
   end
 vagrant up                   #runs provisioning only once
 vagrant reload --provision   #reloads VM skipping import and runs provisioning
 vagrant ssh                  #ssh to VM
 wget -qO- 127.0.0.1          #test Apache is running on VM
Provisioners – shell, ansible, ansible_local and more

This section is about using Ansible with Vagrant,

*ansible, where Ansible is executed on the Vagrant host *ansible_local, where Ansible is executed on the Vagrant guest

Specify Ansible as a provisioner in Vagrant file

#
# Run Ansible from the Vagrant Host
#
config.vm.provision "ansible" do |ansible|
   ansible.playbook = "playbook.yml"
end
Networking – port forwarding

Vagrant can forward any host(hypervisor) TCP port to guest vm specyfing in ~/git/vargant/Vagrant file

config.vm.network :forwarded_port, guest: 80, host: 4567

Reload Vagrant VM

vagrant reload

Run on the host from a web browser http://127.0.0.1:4567 to test it.

Vagrant power states
  • vagrant suspend – saves the current running state of the machine and stop it
  • vagrant halt – gracefully shuts down the guest operating system and power down the guest machine
  • vagrant destroy – removes all traces of the guest machine from your system. It’ll stop the guest machine, power it down, and remove all of the guest hard disks
Vagrant providers

Vagrant can work with a wide variety of backend providers, such as VMware, AWS, and more without changing Vagrantfile. It’s enough to specify the provider and Vagrant will do the rest:

vagrant up --provider=vmware_fusion
vagrant up --provider=aws

Vagrant box images

vagrant box list   #list all downloaded boxes

Default path of boxes image

C:\Users\%username%\.vagrant.d\boxes  #Windows
~/.vagrant.d/boxes                    #LInux

Change default path via environment variable

export VAGRANT_HOME=my/new/path/goes/here/