Managing Puppet modules on Vagrant with Librarian-Puppet

Photo by Iñaki del Olmo on Unsplash.

When it comes to source code control I'm a purist: I avoid storing any derived files (ex. generated CSS) or third-party code. So when I started using PuPHPet to generate Vagrant and Puppet configurations, I was dismayed by the gigantic /puphpet/puppet/modules directory. 3,000 files totaling 5 MB?! There must be a better way.

Instead of keeping the Puppet dependencies in our repository, librarian-puppet lets us automatically load these modules during setup of the Vagrant box. In our Vagrantfile we add a new setup script:

config.vm.provision :shell, :path => 'puphpet/shell/'
config.vm.provision :shell, :path => 'puphpet/shell/'
config.vm.provision :shell, run: 'always' do |s|    s.path = 'puphpet/shell/'    s.args = '/vagrant/puphpet/puppet'endconfig.vm.provision :shell, run: 'always' do |s|
    s.path = 'puphpet/shell/'
    s.args = '/vagrant/node_modules'

The setup script is based on the bootstrap script from vagrant-puppet-librarian.


# Temporary directory in which to install puppet modules.
# Avoids issues with writing to a VirtualBox shared folder.

    # Skip install if the temp folder already exists
    if [ -d "$TMP_FOLDER" ]; then

        echo "Skipping puppet dependencies because the temporary installation folder already exists"


        # Create the temp folder and populate it with the Puppetfile, Puppetfile.lock, etc.
        mkdir -p $TMP_FOLDER && cd $TMP_FOLDER
        cp -r $1/* ./

        # NB: librarian-puppet might need git installed. If it is not already installed
        # in your basebox, this will manually install it at this point using apt or yum
        if [ ! -x $GIT ]; then
            if [ -x $YUM ]; then
                echo "Installing git via yum"
                yum -q -y install git-core
            elif [ -x $APT_GET ]; then
                echo "Installing git via apt-get"
                apt-get -q -y install git-core
                echo "No package installer available. You may need to install git manually."

        if [ `gem query --local | grep librarian-puppet | wc -l` -eq 0 ]; then
          echo "Installing the librarian-puppet gem"
          gem install librarian-puppet

        echo "Installing puppet dependencies"
        librarian-puppet install

        # Copy the installed modules back to the project
        rsync -Lr --inplace $TMP_FOLDER/.librarian $1/
        rsync -Lr --inplace $TMP_FOLDER/modules $1/
        rsync -Lr --inplace $TMP_FOLDER/Puppetfile.lock $1/

if [ ! "$1" -o -z "$1" ]; then
    echo "You must specify a destination for the Puppet module installation (recommend an absolute path)"
elif [ ! -d "$1" ]; then
    echo "Puppet module installation destination $1 must already exist"
    install $1

librarian-puppet reads from our Puppetfile -- also provided by PuPHPet -- for a list of all the Puppet dependencies to download. It behaves similar to the Windows path limit fix:

  • The modules install to a temporary directory because I had issues running librarian-puppet install inside the /vagrant directory, presumably because it's shared with Windows. After installation, the modules are copied to /vagrant/puphpet/puppet/modules so Vagrant's setup can continue as usual.
  • If the temp directory already exists during setup, the script assumes that the Puppet dependencies are ready and aborts.
  • Temporary files are stored in /var/tmp to persist during restarts, and the run: 'always' parameter in the Vagrantfile ensures that the script will fire during both vagrant reload and vagrant up.

Finally we add two entries to our .gitignore.


Now we can keep our repository lean while leveraging the power of third-party Puppet modules!



Hi! I'm Drew, the Wimpy Programmer. I'm a software developer and formerly a Windows server administrator. I use this blog to share my mistakes and ideas.