Installing lighttpd and FastCGI for Catalyst

From Dev411: The Code Wiki

One of the big benefits of using Catalyst web framework (http://www.catalystframework.org) is its ability to run on a variety of web servers and engines. Catalyst makes running your app on lighttpd and FastCGI breeze. FastCGI allows Catalyst to run in a persistent Perl process with the lighttpd web server. As an aside, while the FastCGI process is persistent, the connection between lighttpd and FastCGI isn't. The LiteSpeed webserver (http://litespeedtech.com/) supports persistent FastCGI connections but isn't open source (though there is a free standard version).

The following are notes on getting lighttpd running with FastCGI and Catalyst. Catalyst 5.65, lighttpd 1.4.10 and CentOS 4.2 were used for testing.

Table of contents

Installing lighttpd

I prefer to compile programs from source. Lighttpd is available from lighttpd.net (http://www.lighttpd.net).

To enable FastCGI with lighttpd, it must be configured with a few options. They are:

$ ./configure \
--enable-fastcgi \
--enable-discard-path \
--enable-force-cgi-redirect \
$ make
$ su -
# make install

This will install the lighttpd binary in /usr/local/sbin. Now you should copy two files into place, the startup file and the configuration file.

Configuring startup

lighttpd 1.4.10 comes with init.d files for SuSE and Red Hat/CentOS. The SuSE file is doc/rc.lighttpd and the Red Hat file is doc/rc.lighttpd.redhat.

The init.d files assume that the lighttpd binary is in /usr/sbin/lighttpd while the default install location is /usr/local/sbin/lighttpd. You'll have to either move/copy the lighttpd binary to /usr/sbin or edit the init.d file. If you want to edit the init.d file, change following line:

SuSE (rc.lighttpd) edit the following line:

LIGHTTPD_BIN=/usr/local/sbin/lighttpd

Red Hat/CentOS (rc.lighttpd.redhat) edit the following line:

lighttpd="/usr/local/sbin/lighttpd"

Then copy the relevant file to /etc/init.d/lighttpd and you're ready to configure it for automatic startup. For Red Hat, do the following as a superuser:

# cp doc/rc.lighttpd.redhat /etc/init.d/lighttpd
# chkconfig --add lighttpd
# chkconfig --level 345 lighttpd on

Creating the webserver user

You'll want an unprivileged user for lighttpd to run as. If you don't have one already, you can create one with the following commands as a superuser:

# mkdir /home/lighttpd
# groupadd lighttpd
# useradd -g lighttpd -d /home/lighttpd -s /bin/false lighttpd

First look at lighttpd.conf

The lighttpd.conf file is in doc/lighttpd.conf and is typically copied to /etc/lighttpd.conf where it can be edited for your site:

# cp ./doc/lighttpd.conf /etc

At a minimum you'll want to enable mod_fastcgi and set the unprivleged user and group. Add/modify the following in lighttpd.conf:

server.modules = (
    "mod_rewrite",
    "mod_access",
    "mod_simple_vhost",
    "mod_fastcgi",
    "mod_accesslog"
)
server.username  = "lighttpd"
server.groupname = "lighttpd"

Next, you'll need to decide whether you want to run your Catalyst app. We'll move on to configuring the Catalyst app with FastCGI before revisiting the lighttpd.conf file.

Configuring FastCGI

You'll need to have FastCGI (http://www.fastcgi.com) and Catalyst::Engine::FastCGI (http://search.cpan.org/~mramberg/Catalyst-5.65/lib/Catalyst/Engine/FastCGI.pm) installed on your system. Catalyst::Engine::FastCGI gives you several options to deploy FastCGI on your system. Here are some options:

  • Stand-alone FastCGI server with sockets
  • Multiple FastCGI servers with sockets
  • Stand-alone FastCGI server with TCP
  • Load-balanced FastCGI servers with TCP
  • Static-mode with lighttpd

Running a stand-alone FastCGI server has a few advantages, the most notable being that it can easily scale out to support server farms. It can also run as under a different user id, which makes it easier to securre from other processes that run under the web server (for example your app has to be able to connect to the database, so either the uid you run under is privaleged to do that or a file readable to that uid must contain database login information - if you run under a different uid to the webserver this does not allow other webserver processes to get at your db). If you run stand-alone FastCGI servers, you'll also want to make sure they have init.d startup scripts.

The examples below all put the Catalyst app at the document root. If you wish to run your Catalyst app in a non-root location change "" to "/myapp", or your path, in the following lighttpd.conf configurations.

The examples also use a virtual host regexp that matches either www.myapp.com or myapp.com:

$HTTP["host"] =~ "^(www.)?mysite.com"

If you wish to only match one name you can change the examples to:

$HTTP["host"] == "www.mysite.com"

Stand-alone FastCGI server with sockets

To use a stand-alone FastCGI server with lighttpd you need to start the FastCGI server and configure lighttpd.conf to use the socket.

Starting the FastCGI server

Start the Catalyst FastCGI helper script. The -l option tells FastCGI what to listen for, the -n option indicates the number of processes to start and the -d option daemonizes the process.

MyApp/script/myapp_fastcgi.pl -l /tmp/myapp.socket -n 5 -d

lighttpd.conf

Include fastcgi.server in your lighttpd.conf, optionally in a virtual host.

$HTTP["host"] =~ "^(www.)?mysite.com" {
    fastcgi.server = (
        "" => (
            "MyApp" => (
                "socket" => "/tmp/myapp.socket",
                "check-local" => "disable"
            )
        )
    )
}

Multiple FastCGI servers with sockets

You may wish to start multiple FastCGI servers listening on different sockets. This is useful for having hot-swappable FastCGI processes so the FastCGI servers can be individually restarted with an updated Catalyst app without any down time. It's also useful if, on the off chance, an update causes problems. The new processes can be shut down while the site remains online with the existing ones while the new code is debugged.

Starting the FastCGI server

Start the Catalyst FastCGI helper script multiple times:

MyApp/script/myapp_fastcgi.pl -l /tmp/myapp-0.socket -n 5 -d
MyApp/script/myapp_fastcgi.pl -l /tmp/myapp-1.socket -n 5 -d

lighttpd.conf

Include fastcgi.server in your lighttpd.conf, optionally in a virtual host.

$HTTP["host"] =~ "^(www.)?mysite.com" {
    fastcgi.server = (
        "" => (
            "MyApp" => (
                "socket" => "/tmp/myapp-0.socket",
                "check-local" => "disable"
            ),
            (
                "socket" => "/tmp/myapp-1.socket",
                "check-local" => "disable"
            )
        )
    )
}

Stand-alone FastCGI server with TCP

To use TPC, you'll have to configure FastCGI and lighttpd.

Starting the FastCGI server

You can start the FastCGI server listening on all interfaces or just to a specific host. To listen on all interfaces use:

MyApp/script/myapp_fastcgi.pl -l 1030 /tmp/myapp.socket -n 5 -d

To listen for a specific hostname only, use:

MyApp/script/myapp_fastcgi.pl -l 10.0.0.2:1030 /tmp/myapp.socket -n 5 -d

lighttpd.conf

Edit the lighttpd.conf file as follows:

$HTTP["host"] =~ "^(www.)?mysite.com" {
    fastcgi.server = (
        "" => (
            "MyApp" => (
                "host" => "10.0.0.2",
                "port" => 1030,
                "check-local" => "disable"
             )
        )
    )
}

Load-balanced FastCGI servers with TCP

One nice advantage of TCP is that it lets you call remote FastCGI servers easily. Once you have the FastCGI servers running, start up lighttpd with the following in lighttpd.conf:

$HTTP["host"] =~ "^(www.)?mysite.com" {
    fastcgi.server = (
        "" => (
            "MyApp" => (
                "host" => "10.0.0.2", "port" => 1030,
                "check-local" => "disable"
            ),
            (
                "host" => "10.0.0.3", "port" => 1030,
                "check-local" => "disable"
            )
        )
    )
}

Static-mode FastCGI with lighttpd

In this mode, there's no need to run myapp_fastcgi.pl separately since lighttpd will do it for you.

$HTTP["host"] =~ "^(www.)?mysite.com" {
    fastcgi.server = (
        "" => (
            "MyApp" => (
                "check-local" => "disable",
                "bin-path" => "/var/www/MyApp/script/myapp_fastcgi.pl",
                "min-procs"    => 2,
                "max-procs"    => 5,
                "idle-timeout" => 20
            )
        )
    )
}

Configuring FastCGI for Auto-Start

There are a number of ways to automatically start the fastcgi processes. One of the more popular ways is to use the OS-based init/startup system. Here is an init script for RedHat based distros contributed by Gavin Henry of Suretec Systems.

#!/bin/sh
#
# (c) Copyright 2007 - Suretec Systems Ltd.
# http://www.suretecsystems.com
#
# License: GPLv2
#
# Initial version: 11-06-2007
# Updated: 12-06-2007
#
# chkconfig: - 85 15
# description: Startup script for the fastcgi server
#
# processname: fastcgi
# config: /etc/sysconfig/fastcgi
# pidfile: /var/run/fastcgi.pid

# Source function library
. /etc/rc.d/init.d/functions

if [ -f /etc/sysconfig/fastcgi ]; then
        . /etc/sysconfig/fastcgi
fi

appname="ftm_fastcgi"
prog="$appname.pl"
fastcgi="$appname.pl"
children="5"
pid="/var/run/$appname.pid"
socket="/tmp/$appname.socket"
RETVAL=0

start() {
        echo -n $"Starting $prog: "
        daemon $fastcgi -l $socket -n $children -p $pid -d
        RETVAL=$?
        echo
        [ $RETVAL -eq 0 ] && touch /var/lock/subsys/$prog
        return $RETVAL
}

stop() {
        echo -n $"Stopping $prog: "
        killproc -p $pid
        RETVAL=$?
        echo
        [ $RETVAL -eq 0 ] && rm -f /var/lock/subsys/$prog
        return $RETVAL
}

reload() {
        echo -n $"Reloading $prog: "
        killproc -p $pid -HUP
        RETVAL=$?
        echo
        return $RETVAL
}

case "$1" in
        start)
                start
                ;;
        stop)
                stop
                ;;
        restart)
                stop
                start
                ;;
        condrestart)
                if [ -f /var/lock/subsys/$prog ]; then
                        stop
                        start
                fi
                ;;
        reload)
                reload
                ;;
        status)
                status -p $pid $fastcgi
                RETVAL=$?
                ;;
        *)
                echo $"Usage: $0 {start|stop|restart|condrestart|reload|status}"
                RETVAL=1
esac

exit $RETVAL

Starting lighttpd

You can use the lighttpd binary directly:

lighttpd -f /etc/lighttpd.conf

or you can use the init.d script. Red Hat/CentOS is handled by:

service lighttpd start

Further Reading

Related Entries

External Links