29 Aug 2013, 12:37

Deploying Perl Web-Apps with Puppet

Share

Since I was asked for I’d like to show one way of how you can deploy your perl web apps using debian packages and puppet.

This post assumes that you want to install some Plack webapps, e.g. App::Standby, Monitoring::Spooler and Zabbix::Reporter.

Those are pretty straight-forward Plack Apps built using Dist::Zilla.

cd Monitoring-Spooler
dzil build
I’ve built debian packages of these CPAN modules. Using dh-make-perl this is reasonably easy, although you’ll need some switches to make dh-make-perl a little less picky:
dh-make-perl –vcs rcs –source-format “3.0 (native)” Monitoring-Spooler-0.04
After building and uploading these packages to my repository I continue to use Puppet to install and configure those.

For each of these packages there is a custom puppet module, e.g. app_standby for managing App::Standby. This module create all necessary directories, manages the configuration and installs the package from my repository. It does not, however, set up any kind of webserver or runtime wrapper. This is done by another module: starman.

For running my Plack apps I use Starman which is managed by it’s own puppet module. It will install the starman package, manage it’s config and create an apache config. The interesting part is that I use puppet to automatically create an apache config and a simple Plack/PSGI multiplexer app that allows me to handle requests to all three (or more) of these apps using a single starman instance.

If these apps were rather busy I’d use a separate starman instance for each one, but as it is I’m more than happy to avoid the overhead of running multiple starman instances.

My starman module is invoked from one of my service classes like this:

  class { ‘starman’:
    configure => {
      mounts    => {
        ‘zreporter’     => ‘/usr/bin/zreporter-web.psgi’,
        ‘monspooler’    => ‘/usr/bin/mon-spooler.psgi’,
        ‘monapi’        => ‘/usr/bin/mon-spooler-api.psgi’,
        ‘standby’       => ‘/usr/bin/standby-mgm.psgi’,
      },
    }
  }
The starman module itself is pretty straight-forward, but below are the templates for the apache config and the PSGI multiplexer.

apache.conf.erb:

<IfModule mod_proxy.c>
<% if @configure.has_key?(“mounts”) -%>
<% @configure[“mounts”].keys.sort.each do |mount| -%>
   <Location /<%= mount %>>
      Allow from all
      ProxyPass           http://localhost:<%= @configure.has_key?(‘starman_port’) ? @configure[“starman_port”] : ‘5001’ %>/<%= mount %>
      ProxyPassReverse    http://localhost:<%= @configure.has_key?(‘starman_port’) ? @configure[“starman_port”] : ‘5001’ %>/<%= mount %>
   </Location>
<% end -%>
<% end -%>
</IfModule>
mount.psgi.erb:
#!/usr/bin/perl
use strict;
use warnings;

use Plack::Util; use Plack::Builder;

my $app = builder { <% if @configure.has_key?(“mounts”) -%> <% @configure[“mounts”].keys.sort.each do |mount| -%>    mount ‘/<%= mount %>‘  => Plack::Util::load_psgi(’<%= @configure[“mounts”][mount] %>’); <% end -%> <% end -%>    mount ‘/‘           => builder {         enable ‘Plack::Middleware::Static’, path => qr#/.+#, root => ‘/var/www’;         my $app = sub { return [ 302, [‘Location’,‘/index.html’], [] ]; };         $app;    } };