vagrant-cachier

A Vagrant plugin that helps you reduce the amount of coffee you drink while waiting for boxes to be provisioned by sharing a common package cache among similiar VM instances. Kinda like vagrant-apt_cache or this magical snippet but targetting multiple package managers and Linux distros.

Installation

Make sure you have Vagrant 1.2+ and run:

vagrant plugin install vagrant-cachier

Usage

The easiest way to set things up is just to enable cache buckets auto detection from within your Vagrantfile:

Vagrant.configure("2") do |config|
  config.vm.box = 'your-box'
  config.cache.auto_detect = true
end

For more information about available buckets, please see the configuration section below.

Compatible providers

It is possibly compatible with the VMware providers as well but I haven't tried yet.

How does it work?

Right now the plugin does not make any assumptions for you and you have to configure things properly from your Vagrantfile. Please have a look at the available cache buckets section below for more information.

Under the hood, the plugin will hook into calls to Vagrant::Builtin::Provision during vagrant up / vagrant reload and will set things up for each configured cache bucket. Before halting the machine, it will revert the changes required to set things up by hooking into calls to Vagrant::Builtin::GracefulHalt so that you can repackage the machine for others to use without requiring users to install the plugin as well.

Cache buckets will be available from /tmp/vagrant-cachier on your guest and the appropriate folders will get symlinked to the right path after the machine is up but right before it gets provisioned. We could potentially do it on one go and share bucket's folders directly to the right path if we were only using VirtualBox since it shares folders after booting the machine, but the LXC provider does that as part of the boot process (shared folders are actually lxc-start parameters) and as of now we are not able to get some information that this plugin requires about the guest machine before it is actually up and running.

Please keep in mind that this plugin won't do magic, if you are compiling things during provisioning or manually downloading packages that does not fit into a "cache bucket" you won't see that much of improvement.

Benchmarks / shameless plug

Please have a look at this blog post for the numbers I've got down here.

Configurations

Auto detect supported cache buckets

As described on the usage section above, you can enable automatic detection of supported cache "buckets" by adding the code below to your Vagrantfile:

Vagrant.configure("2") do |config|
  # ...
  config.cache.auto_detect = true
end

This will make vagrant-cachier do its best to find out what is supported on the guest machine and will set buckets accordingly.

Cache scope

By default downloaded packages will get stored on a folder scoped to base boxes under your $HOME/.vagrant.d/cache. The idea is to leverage the cache by allowing downloaded packages to be reused across projects. So, if your Vagrantfile has something like:

Vagrant.configure("2") do |config|
  config.vm.box = 'some-box'
end

The cached files will be stored under $HOME/.vagrant.d/cache/some-box.

If you are on a multi VM environment, there is a huge chance that you'll end up having issues by sharing the same bucket across different machines. For example, if you apt-get install from two machines at "almost the same time" you are probably going to hit a SystemError: Failed to lock /var/cache/apt/archives/lock. To work around that, you can set the scope to be based on machines:

Vagrant.configure("2") do |config|
  config.vm.box = 'some-box'
  config.cache.scope = :machine
end

This will tell vagrant-cachier to download packages to .vagrant/machines/<machine-name>/<provider-name>/cache on your current project directory.

Available cache "buckets"

System package managers

APT
Vagrant.configure("2") do |config|
  config.vm.box = 'some-debian-box'
  config.cache.enable :apt
end

Used by Debian-like Linux distros, will get configured under guest's /var/cache/apt/archives.

Please note that to avoid re-downloading packages, you should avoid apt-get clean as much as possible in order to make a better use of the cache, even if you are packaging a box

Yum
Vagrant.configure("2") do |config|
  config.vm.box = 'some-centos-box'
  config.cache.enable :yum
end

Used by CentOS guests, will get configured under guest's /var/cache/yum. It will also make sure that keepcache is set to 1 on guest's /etc/yum.conf.

Pacman
Vagrant.configure("2") do |config|
  config.vm.box = 'some-arch-linux-box'
  config.cache.enable :pacman
end

Used by Arch Linux, will get configured under guest's /var/cache/pacman/pkg.

RubyGems

Vagrant.configure("2") do |config|
  config.vm.box = 'some-box-with-ruby-installed'
  config.cache.enable :gem
end

Compatible with probably with any type of guest distro, will hook into the cache folder under the result of running gem env gemdir as the default SSH user (usualy vagrant) on your guest. If you use rbenv / rvm on the guest machine, make sure it is already installed before enabling the bucket, otherwise you won't benefit from this plugin.

Finding out disk space used by buckets

TODO

$ vagrant cache stats

Cleaning up cache buckets

TODO

$ vagrant cache clean apt

Contributing

  1. Fork it
  2. Create your feature branch (git checkout -b my-new-feature)
  3. Commit your changes (git commit -am 'Add some feature')
  4. Push to the branch (git push origin my-new-feature)
  5. Create new Pull Request