Beefy Boxes and Bandwidth Generously Provided by pair Networks
Think about Loose Coupling

Serving multiple Plack apps

by soundX (Acolyte)
on Feb 09, 2015 at 21:36 UTC ( #1116108=perlquestion: print w/replies, xml ) Need Help??

soundX has asked for the wisdom of the Perl Monks concerning the following question:

Greetings all,

I've inherited a webserver running approx 40 - 50 (mostly small) perl web applications, all using and served via Apache. We're in the process of upgrading our webservers and I thought this was a good time to look at moving away from

I need to keep all the legacy stuff running under Apache, but I want to start writing new projects using a framework and plack. My question is what do people think is the best way to go about this?

My options:

1. Keep all the legacy applications running on one server and set up a new one for psgi apps - In an ideal world this would porbably be the best option but it may not go down well with sys admins:).

2. If I have to do it all on a single server is it possible to run everything through apache and proxy any psgi requests through to something like starman.

Lastly, how would I deploy multiple psgi apps (in a similar way to my current cgi scripts)? I've been looking at Plack::App::URLMap but is this the recommended way to do it, will it scale well if I end up with a lot of apps (max < 50).

Replies are listed 'Best First'.
Re: Serving multiple Plack apps
by Your Mother (Archbishop) on Feb 09, 2015 at 23:32 UTC

    Multiple executables and apps with one PSGI server

    Proof of concept to help you and others (and me the next time I want to stub out an example). Tested to work on my OS X box. I recommend uWSGI as an app server and nginx as a webserver (it doesn’t like CGI so you might have to forgo it unless you get ALL your CGIs ironed out to PSGI).


    Install or skip/edit the parts that use: strictures, Catalyst, Catalyst::Devel, Mojolicious, Plack, Plack::Builder, Plack::Middleware::Rewrite… maybe some I missed. Judicious middleware use can let you do all kinds of unified logging or even sessions (x-app you’d need to unify the handling and name but not as hard as from scratch).

    Update: DERP indeed, left these out, Plack::App::CGIBin, Plack::App::WrapCGI.

    Make a play dir and get in it (update, added the cgi “bin”)–

    cd mkdir pm-1116108 cd pm-1116108 mkdir cgi

    Create Cat app– MyCatalystApp

    Create hello.php

    <?php print "Hello, World!"; ?>

    Create cgi/hello.cgi (need the “bin”)–

    #!/usr/bin/env perl use strictures; use CGI qw(:standard); print header(), start_html("HAI"), h1("DERP!"), end_html();


    use Mojolicious::Lite; get '/' => sub { my $c = shift; $c->render(text => "OHAI!"); }; app->start;

    Create app.psgi

    use strictures; use utf8; use Plack::Builder; use Encode; require Mojo::Server::PSGI; require Plack::App::CGIBin; require Plack::App::WrapCGI; use lib "./MyCatalystApp/lib"; require MyCatalystApp; my $root = sub { [ 200, [ "Content-Type" => "text/plain; charset=utf-8" ], [ encode_utf8("I \x{2763} Plack::Builder") ] ]; }; my $cat_app = MyCatalystApp->psgi_app; my $mojo_app = eval { my $server = Mojo::Server::PSGI->new; $server->load_app("./"); $server->to_psgi_app; }; my $cgi_app = Plack::App::CGIBin ->new( root => "./cgi" ) ->to_app; my $php = Plack::App::WrapCGI ->new( script => "/usr/bin/php ./hello.php", execute => 1 ) ->to_app; builder { enable "Rewrite", rules => sub { s,(?<=/cat)\z,/,; # Add trailing slash for Cat app’s root. }; mount "/cat" => $cat_app; mount "/mojo" => $mojo_app; mount "/cgi" => $cgi_app; mount "/php" => $php; mount "/" => $root; }; __END__

    Start it up (with restart flag to watch for edits, Cat does lots of debug for a new app so we turn it off here)–

    env CATALYST_DEBUG=0 plackup -r Watching ./lib pm-1116108.psgi for file updates. HTTP::Server::PSGI: Accepting connections at http://0:5000/

    Now visit (might need to change “localhost” depending on your box’s setup)–

    • http://localhost:5000/
    • http://localhost:5000/cat
    • http://localhost:5000/mojo
    • http://localhost:5000/cgi/hello.cgi
    • http://localhost:5000/php
Re: Serving multiple Plack apps
by Discipulus (Canon) on Feb 10, 2015 at 08:23 UTC
Re: Serving multiple Plack apps
by vincent_veyron (Sexton) on Feb 10, 2015 at 09:14 UTC


    You can use mod_perl to run your legacy cgi scripts; see : : legal case, contract and insurance claim management software
Re: Serving multiple Plack apps
by sundialsvc4 (Abbot) on Feb 10, 2015 at 14:12 UTC

    I’m a little bit confused by this thread.   Ordinarily, PSGI applications are run using Apache’s mod_fastcgi, mod_fcgi, or some other equivalent, and they are distinguished using AddHandler directives or otherwise, distinguished by virtual-host.   The web server dispatches the requests to the appropriate server process and maintains the pool of those processes.   This is true regardless of the programming language(s) being used.   You would distinguish the requests by virtual-hosts,, and configure your internal DNS entries appropriately, and Apache (or nginix as the case may be) sends only the proper requests, directly to the proper service process pool.

      Thanks for your thoughts guys, much appreciated.

      @Your Mother, thanks for the detailed example that's helpful.

      @sundialsvc4. This was part of my question, sorry I'm quite new to a lot of this so forgive my ignorance. I don't have a lot to do with our web server configs unfortunately it's done by our system admins. At the moment Apache is configured with a single vhost and ScriptAlias maps to cgi-bin.

      Ideally what I want is an easy to maintain option that allows me to write/deploy psgi apps in a similar way that I do with scripts in cgi-bin (although I know I can't just stick them in a directory and they'll work). I have read about using vhosts in Apache to deploy psgi apps, which is why I wondered whether Plack::App::URLMap was a viable alternative. I know I'm going to have to use something to handle requests so is creating vhosts for each app the way to do it?

        Vhosts have nothing to do with anything here.

        There are many ways to deploy this stuff but you cannot do anything beyond the plain CGI you already have without some modification to your webserver layer. If you think this is going to be a problem, then you’re stuck with CGI (which isn’t all bad, the ease of deployment is a perk). So, first things, first: ask your webadmin/team if they will allow a directive to run an app through apache. Again there are are a couple of different ways to do this, FastCGIExternalServer probably being the easiest (well, the most flexible anyway, otherwise you need to restart the web server to pick up application changes) for apache.

        If you do that, you can maybe run your whole CGI directory as a single psgi executable, like in my example. Some CGI code takes so many liberties that it can’t be run this way without Herculean efforts. It’s easy enough to try it as a test server, like in my example, and test it on an open port on your host. Your firewall might block it but most hosts have a lot of high ports open, like the default 5000 in the example. You would just substitute the real hostname for localhost. Note, running a live server, even a test server on a high port, can be risky (machine load, locks, security). You should never do it on a production box and make sure you have everyone’s blessing/approval before they find out what you’re up to when you accidentally lock the box with a runaway while() or something.

        A reply falls below the community's threshold of quality. You may see it by logging in.

Log In?

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://1116108]
Approved by NetWallah
Front-paged by NetWallah
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others scrutinizing the Monastery: (5)
As of 2023-03-29 11:04 GMT
Find Nodes?
    Voting Booth?
    Which type of climate do you prefer to live in?

    Results (71 votes). Check out past polls.