I'm a beginner with Puppet and I would like to know if I'm on the right way to deploy applications with Puppet.

The applciations are in a tar.gz file which contains a file with the version number. So, I do this to deploy (I go on the server and do a client restart to pick up the new tarball):


node 'server1.domain.com' inherits basenode {
    apps { apps:
            version => 56,
            apps_name => "apps_tarball.tgz",

init.pp (modules)

exec {"apps_wget":
            command => "/usr/bin/wget http://web_server/${version}-${apps_name} -O /tmp/${container_zip_name}",
            unless  => "test -f /tmp/${version}-${apps_name}",
            require => [ Package["wget"] ],

exec {"apps_unzip":
            cwd     => "/usr/local/apps/path",
            command => "/usr/bin/unzip /tmp/${version}-${apps_name}",
            unless  => "test -f /usr/local/apps/path/apps-version-${version}",
            require => [ Package["unzip"], Exec["container_wget"] ],

But, when I want to upgrade, I don't know to say Puppet to delete the old directory? For example, If I want to upgrade version 56 to 57: I must delete the 56's version directory.

I heard about Capristrano and it seems to be better to use Puppet for managinig packages, config files and using Capristrano to deploy apps, isn't it?


  • I use the module forge.puppetlabs.com to manage downloading/decompressing/placing things which are only available as tarballs. It works great. – jrjohnson Feb 24 '14 at 18:02

I would like to know if I'm on the right way to deploy applications with Puppet.

No, you are not.

You should use the package management available on your operating system. If your software is in tar.gz format, you should re-package it locally as .deb, .rpm or whatever.

If the software is something developed locally, you should use whatever build/deploy tools are available for it.

| improve this answer | |
  • 10
    In a perfect world, admins will take the time to create packages from tarballs. In the real world, my experience has shown this does not happen. Our clients install many applications, sometimes very large applications, from tarballs and have no intention of changing this. – EmmEff Jan 14 '15 at 18:34
  • 4
    @EmmEff That's not a difference between perfect world and real world. That's a difference between "We are stuck to old ways and not ready for automatic configuration management" places and places where configuration management does work. I have seen both -- and even seen the latter turn into the former with a change of admins. – Daniel C. Sobral Jan 23 '15 at 3:54
  • 5
    You have the right to your opinion. My observations in the real world are different than that. – EmmEff Feb 4 '15 at 15:12

You might want to try using fpm to make RPMs or DEBs of your tarballs; it's really simple to use, and you don't have to understand anything about the package formats you don't want to.

To answer your original question, the right way to deploy applications with Puppet is to make Puppet do as little work as possible; any complicated exec resources that download and extract tarballs are bound to be very, very brittle, and making Puppet just yum install a package is much healthier long-run.

| improve this answer | |
  • I knew what I was doing was so very wrong. But rpm building has always scared me away. fpm is my salvation. Thank you Handyman5. f-yeah. – 8None1 Jan 7 '14 at 4:50
  • great comment. Rather than preaching "use rpm" you provided a simple "use a fake rpm and use this simple tool to achieve it". – Andre de Miranda Mar 28 '17 at 9:48

I would try very hard to bundle up the app as an RPM or .deb package and build a yum or apt repository to hold the packages. The packaging up of a tarball or zip that you're just opening up into a directory is pretty easy (but should be a separate question). The packaging available that way tracks versions nicely and handles all sorts of things that just opening up a tarball won't handle well.

If I really really couldn't build a proper package I would do something like this:


node 'server1.domain.com' inherits basenode {
    apps { apps:
            version    => 56,
            oldversion => 55,
            apps_name  => "apps_tarball.tgz",

init.pp (modules):

file {
   [ "/usr/local/apps/path/apps-version-${oldversion}", "/tmp/${oldversion}-${apps_name}" ]:
            recurse => true,
            ensure  => absent;
exec {
            command   => "/usr/bin/wget http://web_server/${version}-${apps_name} -O /tmp/${container_zip_name}",
            logoutput => on_failure,
            creates   => "/tmp/${version}-${apps_name}",
            require   => [ Package["wget"] ];

            cwd     => "/usr/local/apps/path",
            command => "/usr/bin/unzip /tmp/${version}-${apps_name}",
            creates => "/usr/local/apps/path/apps-version-${version}",
            require => [ Package["unzip"], Exec["container_wget"], Exec["apps_wget_${apps_name}] ];

Another alternative is to simply use a recursive puppet resource like:

file {
      source => "puppet:///modules/modulename/apps/path",
      ensure => directory,
      replace => true,
      purge   => true,
      recurse => true;

(where you've already untarred things correctly on the puppet master. Probably also require whatever package is running the service and notify whatever service it's running out of).

| improve this answer | |
file { "/usr/local/apps/path/apps-version-${old-version}":
    ensure => absent

As an aside, doing everything as execs is kinda ugly, and can be hard to troubleshoot when things start breaking; if you can, maybe keep extracted versions of the app files on the puppet server, and use a recursive file resource to retrieve?

| improve this answer | |

I certainly favor packaging the tarball (RPM or whatever), but a few hints:

To delete the old version you can simply delete all versions but the one you are installing. With a recent enough bash and extglob enabled you can rm -r /usr/local/apps/path/apps-version-!(${version}). Beware of wiping out config files and such. You can make the exec refreshonly => true and then notify it from the installation exec.

You can use the creates attribute instead of unless => 'test -f ...'. A but more understandable.

| improve this answer | |

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.