=head1 NAME Catalyst::Manual::Deployment::Apache::mod_perl - Deploying Catalyst with mod_perl =head2 mod_perl Deployment mod_perl is not the best solution for many applications, but we'll list some pros and cons so you can decide for yourself. =head3 Pros =head4 Speed mod_perl is fast and your app will be loaded in memory within each Apache process. =head4 Shared memory for multiple apps If you need to run several Catalyst apps on the same server, mod_perl will share the memory for common modules. =head3 Cons =head4 Memory usage Since your application is fully loaded in memory, every Apache process will be rather large. This means a large Apache process will be tied up while serving static files, large files, or dealing with slow clients. For this reason, it is best to run a two-tiered web architecture with a lightweight frontend server passing dynamic requests to a large backend mod_perl server. =head4 Reloading Any changes made to the core code of your app require a full Apache restart. Catalyst does not support Apache::Reload or StatINC. This is another good reason to run a frontend web server where you can set up an C page to report that your app is down for maintenance. =head4 Cannot run multiple versions of the same app It is not possible to run two different versions of the same application in the same Apache instance because the namespaces will collide. =head4 Cannot run different versions of libraries. If you have two different applications which run on the same machine, which need two different versions of a library then the only way to do this is to have per-vhost perl interpreters (with different library paths). This is entirely possible, but nullifies all the memory sharing benefits that you get from having multiple applications sharing the same interpreter. =head4 Setup Now that we have that out of the way, let's talk about setting up mod_perl to run a Catalyst app. =head4 1. Install Catalyst::Engine::Apache You should install the latest versions of both Catalyst and Catalyst::Engine::Apache. The Apache engines were separated from the Catalyst core in version 5.50 to allow for updates to the engine without requiring a new Catalyst release. =head4 2. Install Apache with mod_perl Both Apache 1.3 and Apache 2 are supported, although Apache 2 is highly recommended. With Apache 2, make sure you are using the prefork MPM and not the worker MPM. The reason for this is that many Perl modules are not thread-safe and may have problems running within the threaded worker environment. Catalyst is thread-safe however, so if you know what you're doing, you may be able to run using worker. In Debian, the following commands should get you going. apt-get install apache2-mpm-prefork apt-get install libapache2-mod-perl2 =head4 3. Configure your application Every Catalyst application will automagically become a mod_perl handler when run within mod_perl. This makes the configuration extremely easy. Here is a basic Apache 2 configuration. PerlSwitches -I/var/www/MyApp/lib PerlModule MyApp SetHandler modperl PerlResponseHandler MyApp The most important line here is C. This causes mod_perl to preload your entire application into shared memory, including all of your controller, model, and view classes and configuration. If you have -Debug mode enabled, you will see the startup output scroll by when you first start Apache. For an example Apache 1.3 configuration, please see the documentation for L. =head3 Test It That's it, your app is now a full-fledged mod_perl application! Try it out by going to http://your.server.com/. =head3 Other Options =head4 Non-root location You may not always want to run your app at the root of your server or virtual host. In this case, it's a simple change to run at any non-root location of your choice. SetHandler modperl PerlResponseHandler MyApp When running this way, it is best to make use of the C method in Catalyst for constructing correct links. =head4 Static file handling Static files can be served directly by Apache for a performance boost. DocumentRoot /var/www/MyApp/root SetHandler default-handler This will let all files within root/static be handled directly by Apache. In a two-tiered setup, the frontend server should handle static files. The configuration to do this on the frontend will vary. The same is accomplished in lighttpd with the following snippet: $HTTP["url"] !~ "^/(?:img/|static/|css/|favicon.ico$)" { fastcgi.server = ( "" => ( "MyApp" => ( "socket" => "/tmp/myapp.socket", "check-local" => "disable", ) ) ) } Which serves everything in the img, static, css directories statically, as well as the favicon file. Note the path of the application needs to be stated explicitly in the web server configuration for both these recipes. =head2 Catalyst on shared hosting So, you want to put your Catalyst app out there for the whole world to see, but you don't want to break the bank. There is an answer - if you can get shared hosting with FastCGI and a shell, you can install your Catalyst app in a local directory on your shared host. First, run perl -MCPAN -e shell and go through the standard CPAN configuration process. Then exit out without installing anything. Next, open your .bashrc and add export PATH=$HOME/local/bin:$HOME/local/script:$PATH perlversion=`perl -v | grep 'built for' | awk '{print $4}' | sed -e 's/v//;'` export PERL5LIB=$HOME/local/share/perl/$perlversion:$HOME/local/lib/perl/$perlversion:$HOME/local/lib:$PERL5LIB and log out, then back in again (or run C<". .bashrc"> if you prefer). Finally, edit C<.cpan/CPAN/MyConfig.pm> and add 'make_install_arg' => qq[SITEPREFIX=$ENV{HOME}/local], 'makepl_arg' => qq[INSTALLDIRS=site install_base=$ENV{HOME}/local], Now you can install the modules you need using CPAN as normal; they will be installed into your local directory, and perl will pick them up. Finally, change directory into the root of your virtual host and symlink your application's script directory in: cd path/to/mydomain.com ln -s ~/lib/MyApp/script script And add the following lines to your .htaccess file (assuming the server is setup to handle .pl as fcgi - you may need to rename the script to myapp_fastcgi.fcgi and/or use a SetHandler directive): RewriteEngine On RewriteCond %{REQUEST_URI} !^/?script/myapp_fastcgi.pl RewriteRule ^(.*)$ script/myapp_fastcgi.pl/$1 [PT,L] Now C should now Just Work. Congratulations, now you can tell your friends about your new website (or in our case, tell the client it's time to pay the invoice :) ) =head2 FastCGI Deployment FastCGI is a high-performance extension to CGI. It is suitable for production environments. =head3 Pros =head4 Speed FastCGI performs equally as well as mod_perl. Don't let the 'CGI' fool you; your app runs as multiple persistent processes ready to receive connections from the web server. =head4 App Server When using external FastCGI servers, your application runs as a standalone application server. It may be restarted independently from the web server. This allows for a more robust environment and faster reload times when pushing new app changes. The frontend server can even be configured to display a friendly "down for maintenance" page while the application is restarting. =head4 Load-balancing You can launch your application on multiple backend servers and allow the frontend web server to load-balance between all of them. And of course, if one goes down, your app continues to run fine. =head4 Multiple versions of the same app Each FastCGI application is a separate process, so you can run different versions of the same app on a single server. =head4 Can run with threaded Apache Since your app is not running inside of Apache, the faster mpm_worker module can be used without worrying about the thread safety of your application. =head3 Cons You may have to disable mod_deflate. If you experience page hangs with mod_fastcgi then remove deflate.load and deflate.conf from mods-enabled/ =head4 More complex environment With FastCGI, there are more things to monitor and more processes running than when using mod_perl. =head3 Setup =head4 1. Install Apache with mod_fastcgi mod_fastcgi for Apache is a third party module, and can be found at L. It is also packaged in many distributions, for example, libapache2-mod-fastcgi in Debian. You will also need to install the L module from cpan. Important Note! If you experience difficulty properly rendering pages, try disabling Apache's mod_deflate (Deflate Module), e.g. 'a2dismod deflate'. =head4 2. Configure your application # Serve static content directly DocumentRoot /var/www/MyApp/root Alias /static /var/www/MyApp/root/static FastCgiServer /var/www/MyApp/script/myapp_fastcgi.pl -processes 3 Alias /myapp/ /var/www/MyApp/script/myapp_fastcgi.pl/ # Or, run at the root Alias / /var/www/MyApp/script/myapp_fastcgi.pl/ The above commands will launch 3 app processes and make the app available at /myapp/ =head3 Standalone server mode While not as easy as the previous method, running your app as an external server gives you much more flexibility. First, launch your app as a standalone server listening on a socket. script/myapp_fastcgi.pl -l /tmp/myapp.socket -n 5 -p /tmp/myapp.pid -d You can also listen on a TCP port if your web server is not on the same machine. script/myapp_fastcgi.pl -l :8080 -n 5 -p /tmp/myapp.pid -d You will probably want to write an init script to handle starting/stopping of the app using the pid file. Now, we simply configure Apache to connect to the running server. # 502 is a Bad Gateway error, and will occur if the backend server is down # This allows us to display a friendly static page that says "down for # maintenance" Alias /_errors /var/www/MyApp/root/error-pages ErrorDocument 502 /_errors/502.html FastCgiExternalServer /tmp/myapp.fcgi -socket /tmp/myapp.socket Alias /myapp/ /tmp/myapp.fcgi/ # Or, run at the root Alias / /tmp/myapp.fcgi/ =head3 More Info L. =head2 Development server deployment The development server is a mini web server written in perl. If you expect a low number of hits or you don't need mod_perl/FastCGI speed, you could use the development server as the application server with a lightweight proxy web server at the front. However, consider using L for this kind of deployment instead, since it can better handle multiple concurrent requests without forking, or can prefork a set number of servers for improved performance. =head3 Pros As this is an application server setup, the pros are the same as FastCGI (with the exception of speed). It is also: =head4 Simple The development server is what you create your code on, so if it works here, it should work in production! =head3 Cons =head4 Speed Not as fast as mod_perl or FastCGI. Needs to fork for each request that comes in - make sure static files are served by the web server to save forking. =head3 Setup =head4 Start up the development server script/myapp_server.pl -p 8080 -k -f -pidfile=/tmp/myapp.pid You will probably want to write an init script to handle stop/starting the app using the pid file. =head4 Configuring Apache Make sure mod_proxy is enabled and add: # Serve static content directly DocumentRoot /var/www/MyApp/root Alias /static /var/www/MyApp/root/static ProxyRequests Off Order deny,allow Allow from all # Need to specifically stop these paths from being passed to proxy ProxyPass /static ! ProxyPass /favicon.ico ! ProxyPass / http://localhost:8080/ ProxyPassReverse / http://localhost:8080/ # This is optional if you'd like to show a custom error page # if the proxy is not available ErrorDocument 502 /static/error_pages/http502.html You can wrap the above within a VirtualHost container if you want different apps served on the same host. =head1 AUTHORS Catalyst Contributors, see Catalyst.pm =head1 COPYRIGHT This library is free software. You can redistribute it and/or modify it under the same terms as Perl itself. =cut