Toadfarm on Base Debian: An absolutely minimal multi-tenant webserver

Tags:

Here we create an absolutely minimal multi-tenant webserver, without even installing Apache or NginX. Although we can add either of those later, with our content running under them as reverse proxies, this tutorial lets you run one or more Mojolicious "apps" mounted under a single toadfarm startup script, saving you the "default perl memory" times the number of worker processes and apps.

We will b using Jan Henning Thorsen's Toadfarm:

Toadfarm is a module for configuring and starting your Mojolicious applications. You can either combine multiple applications in one script, or just use it as a init script.


First, perform a Debian Netinstall on a virtual machine or virtual host. The only modification to all the default selections is to enable only "Standard System Utilities" and disable desktop, database, mail, print, file, and web server. We will be building our own of all those!

Now boot up into that absolutely stock, base machine. For illustration, we will assume your username is gronk − change this as necessary. First let's install a few system packages (ssh for access; curl for installing Perlbrew et al; sudo for convenience; build-essential for GCC, Make, and the compiler tools; and the no-X version of emacs because I've been using it since 1980):

$ su
# apt-get install sudo ssh curl build-essential emacs-nox
# usermod -a -G sudo <em>gronk</em> # exit

Now we install our Perlbrew environment as the user:

$ \curl -L http://install.perlbrew.pl | bash
$ echo source ~/perl5/perlbrew/etc/bashrc >> ~/.bash_profile
$ perlbrew install 5.22.0 -j5

The -j5 means use five processes for the Make. Then:

$ perlbrew switch 5.22.0
$ perlbrew install-cpanm
$ curl -L https://cpanmin.us |     perl - -M https://cpan.metacpan.org -n Mojolicious
$ cpanm Toadfarm

jhthorsen explains how this goes together:

You can't run individual apps inside toadfarm as different user, but you can start toadfarm as root and change to a different user.

[

This is true of Mojolicious generally ](https://metacpan.org/pod/Mojo::Server#user) .

In particular, we create an Init script with a #! (hashbang) that points to our user's "brewed" Perl. From the documentation:

Remember that the hashbang can be anything, so if you have Toadfarm and Mojolicious running under

[

plenv ](https://github.com/tokuhirom/plenv) or Perlbrew you need to change the hashbang part…

So we change our Init script to start with:

#!/home/<em>gronk</em>/perl5/perlbrew/perls/perl-5.22.0/bin/perl

Then in the Toadfarm script called by the Init script, which is started as root, we do the switch to our user (called some-www-user in the documentation, gronk here):

#/usr/bin/env perl
use Toadfarm -init;
# …
start [qw( http://*:80 https://*:443 )], user => "<em>gronk</em>", group => "<em>www</em>";

From the documentation:

Changing user has one implication: The workers will not use some-www-user's secondary groups. So if "some-www-user" is part of the "www" and "db" groups, then the process will only be run as "some-www-user" part of the "www" group.

See also the IRC log for 26 April 2014.

Mojolicious: An interview with author Sebastian Riedel

Tags:

We are experiencing Perl's most successful period since the 1990s. I-Programmer spoke with Sebastian Riedel, originator of the relatively new Mojolicious system built on Perl.

…The truth is that installing Mojolicious is simply a very fast and pleasant experience… we've done with tight integration of WebSockets and event loops, [and] the ability to grow from single-file prototypes to well structured web applications.

The first example application you encounter on

[

our website ](http://mojolicio.us) … doesn't look very complicated at all. But once you start digging a little deeper, you'll quickly realize how crazy (in a good way) it really is, and how hard it would be to replicate with any other web framework, in any language…

Read the rest of the story at i-programmer, 11 December 2014.

Writing Extensible Systems with Pluggable Modules in Perl

Tags:

Module::Pluggable is an under-appreciated way to write extensible programs. It has been in the Perl core modules since Perl 5.8. [1] The author maintains a Github repository.

use Module::Pluggable instantiate => function_name;

Instantiates an object for each pluggable module by calling the named function (method); often you will want to pass "new". Or you might just want to load (require) the modules, and not instantiate them:

use Module::Pluggable require => 1;

The return value to plugins() will then change from a list of the installed module names, to a list of all the objects created. Note that the change in return-value is undocumented. See also the option, on_instantiate_error which controls what happens when things go wrong.

Module::Pluggable does expect the following protocol:

use Module::Pluggable search_path => "Plugins", instantiate => 'new';

searches the subdirectory ./Plugins for files named *.pm (although you can change this with the file_regex parameter). For example, if you are writing a Mojolicious model that should have pluggable submodules, you could do this:

# in lib/MyApp/Model/MyGeneralModel.pm
use Module::Pluggable require => 1, search_path => __PACKAGE__;

which would load all files matching lib/MyApp/Model/MyGeneralModel/*.pm

Each file, for example Plugins/plug1.pm in the first example above, is expected to contain a co-ordinating definition properly placed in the object namespace hierarchy by matching the filename:

package Plugins::plug1;

sub new {
  my $class = shift;
  my $self = {};
  return bless \$self, $class;
}

sub some_handler {
  my $class = shift;
  …
}

In the main program or calling class, then, you might do something like:

# Save list of created plugin objects
my @plugs = plugins(optional => 'arguments');

…

my @values;
foreach my $p (@plugs) {
  push @values, $p->some_handler()
    if $p->can('some_handler');
}

Notes

  1. One quick way to determine this is to use the also built-in Module::CoreList function first_release() from the command line: perl -MModule::CoreList -e "print Module::CoreList->first_release('Module::Pluggable')"

Zero to Mojolicious with Zurb Foundation in Five Minutes

Tags:

A short tutorial.

Let's run through creating a Perl web application with Mojolicious and styling by Zurb Foundation. We will create this first as a full "application" and then as a "Lite" version.

Installing (Perlbrew and) Mojolicious

While perlbrew is not strictly required, the latest versions of Perl have a number of features and optomizations that help Mojolicious. There are two ways to install all this: Globally for all users (I recommend this if you are administering the entire server, and want to keep just one set of software) or in your home directory (best if you share a server).

  1. *Installing in your home directory *Following the instructions here [perlbrew.pl], install Perlbrew into your home directory: something like this:

    \curl -L http://install.perlbrew.pl | bash
    nice perlbrew -j 5 install perl-5.20.2
    

    Note the 'nice' (to reduce impact on a running system) and the "-j 5" (to use up to five concurrent compilation threads) − although on an active server, you might want to just use the default single thread. Observe the final output of perlbrew: You will almost certainly have to edit ~/.bash_profile as it suggests, logout, and then log back in to enable the perlbrew command.

    Now permanently switch to the new Perl, and install Mojolicious:

    perlbrew switch perl-5.20.2
    sudo sh -c "curl get.mojolicio.us | sh"  
    
  2. *Installing globally *Assuming a brand new machine (possibly a Linode virtual machine), first we install the latest Mojolicious under /local/bin ... if you don't do this as root this way, I recommend you probably get a cpanminus version somewhere in your user home directory.

    sudo sh -c "curl get.mojolicio.us | sh"  
    

Creating a Mojo "app"

OK now we can go into a working directory somewhere and type:

mojo generate app Test

which will create an entire tree of default files under the subdirectory 'test' for a program called 'Test.'

At this point you should be able to start your example program:

cd Test
morbo script/test

and view the default text at http://localhost:3000

Adding Zurb Foundation to your "app"

Next we get the latest Foundation distribution from their website. At the time of writing, this gave me foundation-5.3.1.zip. Create a subdirectory called foundation under the public directory and unzip into there. This will create subdirectories css and js among a few others.

wget <em>latest_foundation_link_from_above
</em>cd public
mkdir foundation
cd foundation
unzip ../../foundation*.zip
cd ..          <em># back to Mojo project's public</em>

We are going to leave those files in a pristine tree so we can replace them later, and create symbolics links to them. Note the slightly curious use of relative paths in the symbolic links below. The multiple ../ are needed because symlinks are relative to the destination file, not the directory where our shell happens to be when they are created. Also, if only the destination directory and not a filename is given, the destination filename is copied from the source (linked-to) file.

# Assuming the latest Foundation framework code
# is downloaded into the 'foundation' directory,
# and that we are currently in the 'public'
# directory in your generated mojo application,
# here we make symlinks from our document root
# into there, only for the files we actually use.
mkdir css
mkdir -p js/vendor
ln -s ../foundation/css/normalize.css css/
ln -s ../foundation/css/foundation.min.css css/
ln -s ../foundation/js/foundation.min.js js/
ln -s ../../foundation/js/vendor/jquery.js js/vendor/
ln -s ../../foundation/js/vendor/modernizr.js js/vendor/

It is worth a reminder that the syntax here is:

<tt>ln -s</tt> <em><small>{source (real file)} {destination (new link name)}</small></em>

Building the HTML for Foundation

Starting with the basic HTML from here:

http://foundation.zurb.com/docs/css.html

We copy some of the code from the original default.html.ep and create the new templates/layouts/zurbish.html.ep as follows:

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="utf-8">
    <!-- Zurb Foundation stuff -->
    <meta name="viewport" content=
       "width=device-width, initial-scale=1.0">
    <link rel="stylesheet" href="css/normalize.css">
    <link rel="stylesheet" href="css/foundation.min.css">
    <script src="js/vendor/modernizr.js"></script>
    <!-- end Zurb -->
    <title><%= title %></title>
  </head>
  <body>
    <script src="js/vendor/jquery.js"></script>
    <script src="js/foundation.min.js"></script>
    <script>
      $(document).foundation();
    </script>
<%= content %>
  </body>
</html>

Then in templates/example/welcome.html.ep we change the content to be as follows:

% layout 'zurbish';
% title 'Welcome';
<h2><%= $msg %></h2>
This page was generated from the template "templates/example/welcome.html.ep"
and the layout "templates/layouts/zurbish.html.ep",
<a href="<%== url_for %>">click here</a> to reload the page or
<a href="/index.html">here</a> to move forward to a static page.
<div class="row">
  <div class="small-2 columns">2 columns</div>
  <div class="small-10 columns">10 columns</div>
</div>
<div class="row">
  <div class="small-3 columns">3 columns</div>
  <div class="small-9 columns">9 columns</div>
</div>

Now, http://localhost:3000 should give you the example text in a very, very basic Foundation based layout. From here, you might want to follow one of the excellent Mojolicious tutorials out there. Here is Zurb's official guide to the Grid, for example.

Also useful is this from "Zurb U" which explains the small/medium/large grids. The one-line gist is:

If you don't specify small-# to a column, Foundation will assume you mean "go full-width on small screens."

As a "Lite App"

For simplicity, here is basically the same program as a single file, in the form of a boilerplate Mojolicious "Lite app":

#!/usr/bin/env perl
use Mojolicious::Lite;

get '/' => sub {
  my $c = shift;
  $c->render('index',
         msg => 'Welcome to the Mojolicious real-time web framework!');
};

app->start;
__DATA__

@@ index.html.ep
% layout 'zurb';
% title 'Welcome';
<div class="row">
  <h2><%= $msg %></h2>
  <div class="small-2 columns">2 columns</div>
  <div class="small-10 columns">10 columns</div>
</div>
<div class="row">
  <div class="small-3 columns">3 columns</div>
  <div class="small-9 columns">9 columns</div>
</div>

@@ layouts/zurb.html.ep
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="utf-8">
    <!-- Zurb Foundation stuff -->
    <meta name="viewport" content=
       "width=device-width, initial-scale=1.0">
    <link rel="stylesheet" href="css/normalize.css">
    <link rel="stylesheet" href="css/foundation.min.css">
    <script src="js/vendor/modernizr.js"></script>
    <!-- end Zurb -->
    <title><%= title %></title>
  </head>
  <body>
    <script src="js/vendor/jquery.js"></script>
    <script src="js/foundation.min.js"></script>
    <script>
      $(document).foundation();
    </script>
<%= content %>
  </body>
</html>

If you save the above as example.pl for example, then the command

morbo example.pl

should permit you to view the generated one-page site at http://localhost:3000

Next steps

In the next installment, we will see how to better use Mojo's template system with Foundation.

Additional Resources

Perl Catalyst on a base Debian system

Tags:

This turns out to be amazingly easy, at least with Debian 7.3.

First, instead of MySQL, I followed instructions at the MariaDB site: Setting Up MariaDB Repositories. Then:

$ sudo apt-get install libcatalyst-modules-perl

which installed over 200 modules, but what do you know:

$ catalyst.pl Foo

creates a Foo Catalyst application under the current directory. Everything *Just Works. *Thanks to Debian and the folks who bring you Catalyst.

Further reading:

UPDATE (April 2014): Catalyst seems a bit heavy for most of my needs. I'm exploring mojolicious.