Sunday 6 April 2014

Perl Dancer on Media Temple (gs)

Recently I was asked by a friend to install Dancer on Media Temple Grid Service (gs), and after I couldn't find a tutorial to do so, I decided to write one myself :)

Hopefully, you'll be able to get up an running in seven easy steps. I am assuming you know how to use remote *nix shells via ssh, editing files, etc.

You should be aware that none of this is really supported by Media Temple so if you run into trouble or if something changes on the grid, you're on your own. For anything other than simple dynamic websites (in PHP), Media Temple recommends their more robust (and expensive) dedicated virtual (dv) server solution.


Step #1 - Login with SSH on Media Temple


At the time of this writing, Media Temple's GS runs on Perl 5.10.1, which is not very recent, but is good enough for us. Teaching you how to setup ssh is a bit beyond the scope of this tutorial, but thankfully Media Temple provides a very nice ssh guide.

Media Temple runs Apache, but error logging is not enabled by default, so you should probably enable error_log on Media Temple. If you run into any trouble on the following sections of this tutorial, following the error log (by something like running "tail -f $HOME/../../logs/error_log" on another window) is definitely going to help you!

Step #2 - Sanity check


After you log in, you'll see Media Temple's domains come with 2 directories (at least that's how they showed up to me): "cgi-bin" and "html". This structure implies that dynamic content should be under cgi-bin and static content should be under "html". Just to make sure everything is sane, up and running, let's create a very simple pure-perl script and place it under the "cgi-bin" directory:

    #!/usr/bin/perl
    # ^^^ Media Temple requires the shebang!
    use strict;
    use warnings;
    print "Content-type: text/html\n\n";
    print "Hello, Media Temple";

Save this file as "test.cgi" and set permissions to 700 (required, apparently):

    chmod 700 test.cgi

The owner of the file should be the main account for that domain as well:

    chown $USER:$USER test.cgi

(where $USER is the username of the main account)

You should also make sure the cgi-bin directory's permissions is set to exactly 755, otherwise things won't work.

Now try and run it from your web browser, by opening "http://your-domain/cgi-bin/test.cgi", where "your-domain" is your Media Temple domain. If you see an "Internal Server Error" message, try checking out your error_log and review the previous steps (for example, make sure the script is exactly as it is above, and all permissions are right).

Step #3 - Installing Perl modules on Media Temple (mt) Grid


Media Temple provides a Knowledge Base tutorial on how to install Perl modules on the Grid, but it only lists manual installations which are boring and error prone. After all, we live in the future, where it's simple to install Perl modules as a user on a shared hosting service. All you have to do is type the following on your server's command line (it's just one line, and you can cut and paste as it is):

    curl -L http://cpanmin.us | perl - --local-lib=~/perl5 local::lib App::cpanminus && eval $(perl -I ~/perl5/lib/perl5/ -Mlocal::lib)

 This is going to install local::lib and cpanm into your home directory, and enable you to install any other modules there by simply typing "cpanm My::Module" (where "My::Module" is, of course, the name of the module you want to install).

While you're at it, remember to add the line:

    eval $(perl -I$HOME/perl5/lib/perl5 -Mlocal::lib)

to your ~/.bash_profile file (create it if necessary, of course).

Step #4 - Installing Dancer (and everything else!)


After the previous step, installing Dancer is easy as pie:

    cpanm Dancer

Done! Let's also install Plack::Runner, in case we need it:

   cpanm Plack::Runner

You can take this moment to install all your app's dependencies. For instance, my friend's app is also using Template Toolkit and DBIx::Class

   cpanm Template DBIx::Class

Step #5 - Making a default Dancer app (or moving your current one)


If you already have a Dancer app, just move it to Media Temple's domain directory. For example, if your Dancer app is called "my-app", move it to:  "/home/XXXXX/domains/mydomain.com/my-app" (replacing XXXXX and "mydomain.com" to the appropriate values for your grid account).

Otherwise, just go there (/home/XXXX/domains/mydomain.com) and create your Dancer app by typing "dancer -a appname".


Step #6 - Change "html" to a symlink:


Your Dancer app's base directory is usually "appname/public", but Media Temple forces you to have an "html" directory as base. So we remove the original (just rename it instead if you're not brave enough :) and create it again, only this time as a symbolic link to "appname/public":

    cd ~/domains/mydomain.com
    mv html html_old
    ln -s myapp/public html

Step #7 - Add the appropriate .htacess files


Media Temple runs Apache on the grid server, so we control what runs with .htaccess files. This is the content we put in the file "myapp/public/.htaccess":

    # Allow /public to run Perl code
    Options +ExecCGI +FollowSymLinks
    AddHandler cgi-script .cgi .pl


    # Initialize mod_rewrite
    RewriteEngine On
    RewriteBase /
 

    # If file doesn't exist on the server, dispatch!
    RewriteCond %{REQUEST_FILENAME} !-f
    RewriteRule ^(.+)$ dispatch.cgi/$1 [L]



At this point I bumped into trouble. Media Temple's Apache doesn't seem to let Perl see variables such as PERL5LIB. There's likely a clean way to fiddle with "SetEnv" on .htaccess to fix this (let me know if you get it working!),  but what I did was add a "use lib" line on top of public/dispatch.cgi, like so:

#!/usr/bin/env perl
use 5.10.0;

# Media Temple doesn't read our environment
use lib qw(
   /home/XXXXX/users/.home/perl5/lib/perl5
   /home/XXXXX/users/.home/perl5/lib/perl5/x86_64-linux-gnu-thread-multi
);

That's the basic setup! If everything went well, you should be able to point your web browser to your domain and see Dancer's main page \o/

You should notice we're running Dancer on standard cgi, which means it's going to be somewhat slow, specially when loading modules.

Appendix: Perl with FastCGI on the Media Temple Grid


Sadly, Media Temple doesn't seem to provide proper FastCGI support for Perl - at least from my understanding. Of course, that didn't stop me from trying, so here's what I did:

First, enable PHP FastCGI on the GS. It should have created a .htaccess in your domain root (i.e. the parent of your "html" dir) with some basic FastCGI settings. I changed them to this:

    # BEGIN (mt) controlled settings
    <IfModule !mod_fcgid.c>
      AddHandler cgi-script .cgi .pl
    </IfModule>
    <IfModule mod_fcgid.c>
      AddHandler fcgid-script .fcgi
      <Files *.fcgi>
        Options +ExecCGI
      </Files>
    </IfModule>
    # END (mt) controlled settings


(this is basically their default script, with "php" replaced with "cgi", "pl" and "fcgi").

Then I went to our own html/.htaccess file (it's a symlink to myapp/public/.htaccess, remember?) and replaced "dispatch.cgi" with "dispatch.fcgi" on the rewrite rules described in step 7 above. Finally, I updated the file "dispatch.fcgi" to include the same "use lib" I did for dispatch.cgi, deleted dispatch.cgi and voilá :)

Done!


Again, Media Temple recommends that any serious app go to their dedicated virtual server (dv) solution. Still, the current gs setup should be enough for you to have some fun and play around with possibilities before moving to a more expensive plan.

There are tons of other cool things you can do, such as creating remote git repositories and making hooks to do automatic deploys, but that's a bit out of the scope of this tutorial :)

Have fun, and happy Perl hacking!