In this article I present the top Vagrant plugins which you should have. Those Vagrant plugins will make working with virtual machines much easier.
Introduction
Vagrant is a very useful tool which abstracts virtual machine providers. It has a lot of features and is open source. If you don’t know it yet, then go directly to the getting started section of the Vagrant project page.
Vagrant is popular but not everyone knows that it’s extensible. Yes, Vagrant can be tuned! And you do this with plugins. And some of them are really awesome!
Discover with me the magic of most wanted Vagrant plugins.
How To Install a Vagrant Plugin
Vagrant plugins can be installed with this command:
vagrant plugin install vagrant-example-plugin
If You want to read more about Vagrant plugins visit this documentation section.
Vagrant Cachier Plugin
vagrant-cachier
enables caching for different package managers on many Linux distributions. You will love this plugin if You play a lot with provisioning!
You can find the Vagrant cachier plugin project on Github.
Basic Understanding
When this plugin is enabled and I update one of my Ubuntu VM’s with apt-get update
or install any packages with apt-get install [package]
, any other VM which uses the same base box, will reuse the downloads. This leads to faster provisioning. And the reason for that is because the updates/packages are cached. This brings a little bit of Docker goodnes into the world of Vagrant.
The diagram below helps you understand this simple but effective logic:
Requirements
- NFS
- Vagrant 1.4+
Installation
Install the vagrant-cachier
plugin with the following command:
vagrant plugin install vagrant-cachier
Usage
Enable it by extending Your Vagrantfile
like in the example below:
1 # -*- mode: ruby -*-
2 # vi: set ft=ruby :
3
4 # Vagrantfile API/syntax version. Don't touch unless you know what you're doing!
5 VAGRANTFILE_API_VERSION = "2"
6
7 Vagrant.configure(VAGRANTFILE_API_VERSION) do |config|
8 # Every Vagrant virtual environment requires a box to build off of.
9 config.vm.box = "ubuntu/trusty64"
10
11 # Configure vagrant-cachier plugin
12 if Vagrant.has_plugin?("vagrant-cachier")
13 # Configure cached packages to be shared between instances of the same base box.
14 # More info on http://fgrehm.viewdocs.io/vagrant-cachier/usage
15 config.cache.scope = :box
16
17 # OPTIONAL: If you are using VirtualBox, you might want to use that to enable
18 # NFS for shared folders. This is also very useful for vagrant-libvirt if you
19 # want bi-directional sync
20 config.cache.synced_folder_opts = {
21 type: :nfs,
22 # The nolock option can be useful for an NFSv3 client that wants to avoid the
23 # NLM sideband protocol. Without this option, apt-get might hang if it tries
24 # to lock files needed for /var/cache/* operations. All of this can be avoided
25 # by using NFSv4 everywhere. Please note that the tcp option is not the default.
26 mount_options: ['rw', 'vers=3', 'tcp', 'nolock']
27 }
28 # For more information please check http://docs.vagrantup.com/v2/synced-folders/basic_usage.html
29 end
30 # @end: Configure vagrant-cachier plugin
31
32 config.vm.provision "shell", inline: "apt-get update --fix-missing"
33 config.vm.provision "shell", inline: "apt-get install nginx -y"
34
35 config.vm.define "web1", primary: true do |web1_config|
36 web1_config.vm.network "private_network", ip: "192.168.90.11"
37 end
38
39 config.vm.define "web2" do |web2_config|
40 web2_config.vm.network "private_network", ip: "192.168.90.12"
41 end
42 end
Note
Next steps will be based on theVagrantfile
presented above.
Now spin up one of Your VM’s which does some provisioning:
vagrant up web1
Then check out the ~/.vagrant.d/cache
host directory. You will find there cached downloads like in the example below:
$ tree ~/.vagrant.d/cache
└── ubuntu
└── trusty64
├── apt
│ ├── fontconfig-config_2.11.0-0ubuntu4.1_all.deb
│ ├── ...
│ ├── nginx_1.4.6-1ubuntu3.1_all.deb
│ ├── nginx-common_1.4.6-1ubuntu3.1_all.deb
│ ├── nginx-core_1.4.6-1ubuntu3.1_amd64.deb
│ └── ...
├── apt_lists
│ ├── archive.ubuntu.com_ubuntu_dists_trusty_main_binary-amd64_Packages
│ └── ...
└── ...
Now start the second machine. This one will reuse the cache:
vagrant up web2
It should boot faster because it doesn’t need to download the updates and the nginx
package.
Isn’t it great?
But that’s not everything. The vagrant-cachier
plugin supports also other package managers:
- apt-cacher
- apt-lists
- apt
- chef
- composer
- generic
- npm
- pacman
- rubygems
- rvm
- yum
- zypper
If You are interested in deeper understanding how this plugin works visit this documentation page.
Is it Really Faster?
Yes it is. Here are some statistics:
$ time vagrant up web1
real 1m49.664s
user 0m8.164s
sys 0m4.679s
$ time vagrant up web2
real 1m20.674s
user 0m8.214s
sys 0m4.949s
About 30
seconds faster.
And we installed only one package. The cache has only 103 MB
:
du -sh ~/.vagrant.d/cache/ubuntu/trusty64/
103M /home/czerasz/.vagrant.d/cache/ubuntu/trusty64/
Imagine how much time You can save when building more complex machines.
You can find more benchmarks here.
Vagrant Host Manager Plugin
vagrant-hostmanager
makes it possible to “talk” between VM’s by their host names.
You can find the Vagrant host manager plugin project on Github.
Basic Understanding
To make the network communication based on host names possible, the vagrant-hostmanager
plugin adjusts the /etc/hosts
file on the host and guest machines.
Requirements
- Vagrant 1.1+
Installation
Install the vagrant-hostmanager
plugin with the following command:
vagrant plugin install vagrant-hostmanager
Usage
Enable it by extending Your Vagrantfile like in the example below:
1 # -*- mode: ruby -*-
2 # vi: set ft=ruby :
3
4 # Vagrantfile API/syntax version. Don't touch unless you know what you're doing!
5 VAGRANTFILE_API_VERSION = "2"
6
7 Vagrant.configure(VAGRANTFILE_API_VERSION) do |config|
8 # Every Vagrant virtual environment requires a box to build off of.
9 config.vm.box = "ubuntu/trusty64"
10
11 # Configure vagrant-cachier plugin
12 if Vagrant.has_plugin?("vagrant-hostmanager")
13 config.hostmanager.enabled = true
14 config.hostmanager.manage_host = true
15 config.hostmanager.ignore_private_ip = false
16 config.hostmanager.include_offline = true
17 end
18 # @end: Configure vagrant-cachier plugin
19
20 config.vm.define "web1", primary: true do |web1_config|
21 web1_config.vm.network "private_network", ip: "192.168.90.11"
22 web1_config.vm.hostname = 'web1'
23
24 config.vm.provision "shell", inline: "echo 'web1' > /home/vagrant/index.html; chown vagrant:vagrant /home/vagrant/index.html"
25 end
26
27 config.vm.define "web2" do |web2_config|
28 web2_config.vm.network "private_network", ip: "192.168.90.13"
29 web2_config.vm.hostname = 'web2'
30 end
31 end
Note
Next steps will be based on theVagrantfile
presented above.
Start the VM’s:
vagrant up
Let’s audit our /etc/hosts
files.
On the host we can see adjustments done by the vagrant-hostmanager
plugin:
$ cat /etc/hosts
...
## vagrant-hostmanager-start id: dbf96559-0f67-4d15-92a5-c41f255cbfc8
192.168.90.11 web1
192.168.90.12 web2
## vagrant-hostmanager-end
On the guest as well:
$ vagrant ssh web1 -c 'cat /etc/hosts'
...
## vagrant-hostmanager-start
192.168.90.11 web1
192.168.90.12 web2
## vagrant-hostmanager-end
Now, let’s run a simple static server with python
on web1
:
$ vagrant ssh web1
$ python -c 'import BaseHTTPServer as bhs, SimpleHTTPServer as shs; bhs.HTTPServer(("0.0.0.0", 8000), shs.SimpleHTTPRequestHandler).serve_forever()'
It will serve the /home/vagrant/index.html
file which we created during the provisioning process.
Open a new terminal. Finally we can request the static server on web1
from web2
by it’s host name:
$ vagrant ssh web2 -c 'curl web1:8000'
web1
Cool stuff!
Tip
If You change the private network ip of any box remember to executevagrant halt
andvagrant up
afterwords.vagrant reload
won’t do it.
Call To Action
Do You know any other amazing Vagrant plugins? Let me know and I will add them to this list.
Contact Me