Rollin like a pro

I have recently been on a bit of a devops journey in an attempt to optimize for happiness (and some substantial learning). At my work we've committed to Puppet for a variety of configuration management tasks; ranging from in office infrastructure, to developer sandboxes, to our production application. Given the recent opportunity to work on a project a bit out of band from our main application(s) I was in a mode to seek out configuration management and deployment on par with process like {heroku, appfog, phpfog, etc…}. It turns out this magic is only a few scripts and some discipline away!

Enter CloudInit + Puppet Git Receiver + Puppi

Puppet Git Receiver

I believe the most "magical" aspect of any of the PaaS offerings is the ability to push code+infrastructure changes (IMO the best being with git) to a remote server. The Puppet git reciever has to be one of the cleanest and well thought out implementations of what is essentially a fancy post-recieve git hook.

What makes this so great, besides the really clean and well thought out code to deploy reasonably complex servers with Puppet, is the simple deb package install that basically configures a git repo, with hook scripts, and configured users.


CloudInit is a nice tool that makes this whole process quite seamless. Basically CloudInit allows you to specify a set of scripts (and Ubuntu specific commands) to run at the VM creation; effectively letting you bootstrap a machine exactly the way you want it. (This is a little additional help that traditionally lives as process step to login to a new machine and "get it going")

At this point with CloudInit + Puppet git reciever - you can now have a "blank" server ready to recieve whatever infrastructure defined by Puppet. This leaves your application code, which is addressed by … (read on)


I'm curious if this Puppet module should actually be called Puppet-Deploy, because that's what it does! (along with some additional sysadmin helper tools too) By specifying a few simple instructions this module configures and stages everything for your app to run on our accompanying infrastructure.

class myapp {
  puppi::project::git { "myapp":
    source      => "",
    deploy_root => "/srv/myapp",

Simply run: puppi deploy myapp on the target server (noteworthy: this can be scripted a variety of ways: with Puppet, via SSH, etc…).

Happy Dance

But wait! There's more!

Given that we're already building out a server and deploying our app with super-simple-commands, why not make it easier? Yeah lets do that! Check out librarian-puppet a tool to manage Puppet module dependencies similar to how Bundler, Composer, and the like. This let's us specify a Puppetfile in our infrastructure repo that defines all the "common" modules we will be using - making a very clear the line between libraries and the "working set" (and avoiding those pesky submodules). Bonus points to letting the post recieve hooks auto build the Puppetfile! This can lead to some pretty simple infrastructure+app definitions:

├── Puppetfile
├── manifests
│   └── site.yml
└── modules
    ├── imapnote
    │   └── manifests
    │       └── init.pp
    └── mysites
        └── manifests
            └── init.pp

(Brought to you by: Labor Day Weekend Research Group™)