We use versions of Ruby, Collectd, Ant, Java (and more) that are not available in CentOS or EPEL repos. Up until now, our strategy for installing these has been kind of a hack:

  • write a (version-controlled) script for each package that downloads the source or binaries off the host site with curl onto the Puppet master and compiles the source code if necessary; repackages into gzipped tarball if necessary

  • use the Puppet file server to distribute the binaries to our servers, and Puppet manifests to unpack the tarball in /usr/local (or wherever)

Writing the scripts can be a pain, and they have to be updated if one of the sites we depend on for downloads changes their API. Also software is compiled separately in every environment, which seems wasteful and could potentially result in problems with missing compile-time dependencies (eg., Ruby: require 'readline' or require 'yaml' might work in some environments but not others)

So, I can think of two other options:

  • Just check in the custom-built third-party binaries into subversion and distribute them with the rest of our Puppet code. I'm worried it will severely impact the performance of checkouts and Puppet code pushes; we're looking at nearly 800MB (and growing) of third-party code. Plus it just feels wrong to check, like, multiple versions and architectures of Java side-by-side into version control.

  • Don't version control the binaries or write download scripts -- when we decide to upgrade Ruby, compile it on a dev box and upload the new package manually to all of our Puppet masters whenever we decide to upgrade. Except, what if the packages get wiped out? Or become out of sync on the different masters? Right now we can easily re-generate all of our custom packages from scratch.

Which of the three options is better? How do people typically manage custom-compiled / repackaged third-party software with Puppet? If you create a local Yum repository, do you version control the process you use to create the RPMs? What happens if your Yum repo is wiped out?

  • "What happens if your Yum repo is wiped out?" Restore it from backup, perhaps? Commented Feb 11, 2013 at 17:19

3 Answers 3


Puppet isn't really designed to distribute large files, so you should rather do this out of band. The best approach is to package the custom/third-party software as RPMs and host your own RPM repository. The RPM packaging (i.e. specfile and patches) should ideally be version controlled, and the RPM repository backed up or hosted on multiple machines.

  • Thanks! Nice, concise answer. I was concerned that converting all of our tarballs into RPMs would be too much work, but FPM has made it very easy: github.com/jordansissel/fpm
    – choover
    Commented Feb 27, 2013 at 22:03

I highly suggest utilizing a Yum repository for deploying all your software including that which you compile. Once properly configured you'll get all your dependency issues straightened out, version control, etc.

My leaning is to have a three branch system (dev, qa, prod) for my repositories. That allows for given systems to be added to different repositories and run through its paces accordingly.

I do that (and the scheduling for the yum updates) via Puppet.


Echoing the other two answers: use your distro's existing package management system.

We do this with Ubuntu and apt to install RabbitMQ and OAuth like this:

class apt::example {

  file  {  "/etc/apt/sources.list.d/repo.example.list":
    source => "puppet:///modules/apt/repo.example.list",
    ensure => present,

  exec {"install-gpg-key":
    command => "/usr/bin/curl -s http://repo.example.com/[email protected] | /usr/bin/apt-key add -; /usr/bin/apt-get update",
    refreshonly => true,
    subscribe => File["/etc/apt/sources.list.d/repo.example.list"],
    require => File["/etc/apt/sources.list.d/repo.example.list"],


and to use the repo:

class apache2::platform {

  package { ["librabbitmq0", "php5-amqp", "php5-oauth"]:
    ensure => installed,
    notify => Service["apache2"],
    require => File["/etc/apt/sources.list.d/repo.example.list"]



The require here makes sure the repo is added before we try to install anything from it.

There may be a better way to handle adding the GPG key and running and update as this command returns a positive exit code which causes puppet to think it failed, but since it works I haven't expended much effort to fix the spurious error message.

I didn't attempt to add the repo config to puppet or automate the build and add to the repo process for new packages but once you reach a certain size, these tasks will become worthwhile. Backups are always worthwhile.

The process for RPM and yum should be very similar.

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .