FastCGIConfiguration: Difference between revisions

From Request Tracker Wiki
Jump to navigation Jump to search
No edit summary
(No difference)

Revision as of 10:48, 24 April 2011

NOTE: This page is a mess of facts some of which are very outdated for 2008 year. Need big refactoring.

FastCGI is a variant to run RT server. You may want to read ManualApacheConfig to decide what you want to use.

Even if you decided to use FastCGI then anyway you must read ManualApacheConfig. It's sort of mandatory reading :)

Configuring RT to run in FastCGI mode is dead simple. However, configuring Apache is hard. If you are considering a single web server to use with RT, you might like to consider a fast and simple solution such as lighttpd, nginx or any of the commercial and free web servers available that support FastCGI.

Configuring RT 3.2 and newer to run in FastCGI mode

When installing RT, run:

./configure \
  --with-web-user="webuser" \
  --with-web-group="webgroup" \
  --with-rt-user="webuser" \
  --with-rt-group="webgroup"

Don't forget to include other configuration options that matter to you, like --prefix. You will still need to customize [=etc/RT_SiteConfig.pm] using [=etc/RT_Config.pm] as a base, before you run `make install'. If you do not have `root' access to the server you are installing to, you can use `fakeroot' or a similar utility to use `make install'.

Configuring RT to run as a dynamic FastCGI application

A dynamic FastCGI application is one in which the application process is dynamically started and stopped by the webserver process, on demand.

RT's FastCGI handler defaults to assuming it is being run as as a dynamic application. So, configure your web server to start bin/mason_handler.fcgi inside the RT installation directory for requests that it is to handle. The first time RT is accessed the web server will attempt to start RT.

Note that this is a less-than-ideal approach, security wise, since the RT application runs under the same user-id as the web server. A better approach would be to have the web server somehow switch users when starting RT. This is commonly achieved via set-uid wrappers, which are generally hard to debug when things go wrong. Also, you will be relying on the process manager included with your web server.

Configuring RT to run as a static/external FastCGI application

A static/external FastCGI application is one in which the application is started manually or independently of the webserver, and the webserver connects to it when needed. This makes it easy to setup user separation between the RT process and the webserver process, but you lose out on the ability for the webserver to dynamically determine how many RT processes need to be running.

This is achieved by running the bin/mason_handler.fcgi script as the configured RT user, setting FCGI_SOCKET_PATH in the process environment to the location of the application socket, or a /hostname:port/ combination. This is a feature of the CGI::Fast perl module, so you may need to upgrade your version of that module if your version does not support this feature.

Note that the FastCGI handler for RT does not currently include a process manager, instead single threading requests. This is likely to be addressed in a later version of either CGI::Fast or RT, but for small installations this is usually acceptable. A simple workaround is simply to start more than one RT daemon.

Note that running RT in single threaded FastCGI mode is the only time that it is actually /safe/ to turn off the [=$WebFlushDbCacheEveryRequest] configuration option.

You will need to set up a script that starts RT after your web server. For best results, use a SysV-style /etc/init.d/ script. Here is an example of such a script:

#!/bin/sh
  
  RTPATH=/path/to/rt
  RTUSER=rt
  FCGI_SOCKET_PATH=$RTPATH/var/appSocket
  
  case $1 in
      start)
          echo -n "Starting RT: mason_handler.fcgi"
          cd $RTPATH
          export FCGI_SOCKET_PATH
          su $RTUSER -c perl bin/mason_handler.fcgi &
          echo
          ;;
  
      stop)
          echo -n "Stopping RT: "
          PIDS=`ps axww | awk '/[m]ason_handler.fcgi/ { print $1}'`
          if [ -n "$PIDS" ]
          then
              echo -n kill -TERM $PIDS
              kill $PIDS
              echo
          else
              echo RT not running
          fi
          ;;
  
      restart|force-reload)
          $0 stop
          $0 start
          ;;
  
      *)
          echo "Usage: /etc/init.d/rt { stop | start | restart }"
          exit 1
          ;;
  esac
  
  

(this example corresponds to the lighttpd setup example)

Web-server specific FastCGI notes

Configuring RT to run with lighttpd

A small patch needs to be applied to lighttpd 1.3.x, as its FastCGI support is slightly broken. See LighttpdPatch for the patch. Lighttpd 1.4.x does not have the problem.

First, make sure that "mod_fastcgi" is uncommented in the server.modules option. Then you can use a fastcgi.server configuration setting similar to:

fastcgi.server = ( "/rt" =>
                     ( "rt" =>
                         (
                             "socket" => "/path/to/rt/var/appSocket",
                              "check-local" => "disable"
                         )
                     )
                 )

Information for lighttpd is included as it is the easiest to setup open source web server that supports FastCGI that I am aware of. However, the process is just as simple using commercial web servers, like Zeus, LiteSpeed or thttpd professional, and no doubt other web servers with FastCGI support like Roxen or Pi3web.

Configuring RT to run with Apache

RT 3.2 includes a significant change to the FastCGI handler. It is no longer "setgid" to the RT group. Perl's setid support has been deprecated for the last several releases and a number of platforms don't bundle the "sperl" or "suidperl" executable by default. Additionally, when perl is run SetUID or SetGID, the interpreter is automatically switched into /taint mode/, in which all incoming data, no matter the source is considered suspect. At first, this seems like a great idea. But perl's taint mode is a big sledgehammer used to hit small nails. Many perl libraries aren't tested in taint mode and will fail when least expected. Moving away from a SetGID FastCGI handler will enable more users to have a smoother RT experience. It does require some changes in how you set up and configure RT.

Beginning with RT 3.2, you have several choices about how to configure RT to run as a FastCGI:

1. Install RT as the user your webserver runs as

Pros: Very easy to configure

Cons: Your webserver has access to RT's private database password

How To

First, determine whether you are using mod_fastcgi or mod_fcgid. I believe mod_fastcgi is older and supports older versions of Apache (i.e. Apache 1.x). The mod_fcgid is newer and is included with newer versions of Fedora Linux, etc. RT does not care which module is being used, but the configuration syntax is different for each module.

If you are using mod_fastcgi (apache 1.x), you'll want to add something like the following to your httpd.conf:

NOTE: Most FastCGI options are available only in apache's server config context, not in virtual host sections.

# Tell FastCGI to put its temporary files somewhere sane.
  FastCgiIpcDir /tmp
  
  # Number of processes is tunable, but you need at least 3 or 4
  FastCgiServer /opt/rt3/bin/mason_handler.fcgi -idle-timeout 120 -processes 4
  
  <VirtualHost rt.example.com>
  
     AddHandler fastcgi-script fcgi
     ScriptAlias / /opt/rt3/bin/mason_handler.fcgi/
  
  </VirtualHost>
  
  

If you are using mod_fcgid, you'll want to add something like the following to your httpd.conf:

<VirtualHost rt.example.com>

   ServerName rt.example.com
   DocumentRoot /opt/rt3/share/html

   AddHandler fcgid-script fcgi
   ScriptAlias / /opt/rt3/bin/mason_handler.fcgi/

</VirtualHost>

2. Make your webserver user a member of the "rt" group

Pros: Easy to configure

Cons: Your webserver has access to RT's private database password

How To

Install RT normally. Add whichever user your webserver runs as (whatever you set --with-web-user to) to the "rt" group (whatever you set --with-rt-group to) in /etc/groups.

To find out what user your webserver runs as, look for the line

User some-user-name

in your apache httpd.conf. Common values are www, www-data, web and nobody.

3. Run RT using _suexec_ or a similar mechanism

Pros: More secure

Cons: Sometimes very difficult to configure

How To

Apache's suexec utility allows you run CGI programs as specific users. Because that's a relatively heavy responsibility, it's very, very conservative about what it's willing to do for you. On top of that, Apache's mod_fastcgi plugin doesn't respect all of suexec's features. While suexec is designed to execute CGI scripts in a given virtual host's DocumentRoot, It can only execute FastCGI scripts in the system's main DocumentRoot.

This means you have to copy the RT FastCGI handler into your main DocumentRoot

The following example VirtualHost will run RT as a FastCGI on Apache 1.3 on a Debian Linux server.

# Tell FastCGI to put its temporary files somewhere sane.
  FastCgiIpcDir /tmp
  
  # Tell FastCGI that it should use apache's "suexec" binary to call any FastCGI script.
  # This is a GLOBAL setting
  FastCgiWrapper /usr/lib/apache/suexec
  
  # You need to copy the rt mason_handler.fcgi into a directory inside the main server DocumentRoot
  # That directory must be owned by the user and group that will execute the FastCGI script
  # In this case, that directory is /var/www/rt
  
  # To find the local DocumentRoot, run "suexec -V" as root and look for the
  #  -D DOC_ROOT parameter.
  
  # Apache 1.3 discards the user and group parameters on the FastCgiServer line.
  # Apache 2.0 requires them.
  FastCgiServer /var/www/rt/mason_handler.fcgi -idle-timeout 120 -user rt -group rt -processes 4
  
  <VirtualHost rt.example.com>
  
     DocumentRoot /opt/rt3/share/html
  
     # Set the rt user and group as the executing user for this virtual host.
     # For apache 2 you need
     #    SuexecUserGroup rt rt
     # instead
     User rt
     Group rt
  
     AddHandler fastcgi-script fcgi
     ScriptAlias / /var/www/rt/mason_handler.fcgi/
  
  </VirtualHost>
  

Configuring RT3 to run with nginx

The patch listed below is no longer required with the latest version of nginx (http://www.nginx.net),

Here is a quick excerpt that shows how to run rt3 with a FastCGI socket,

server {
    listen       80;
    server_name  localhost;

    location / {
            root   /usr/local/rt3/share/html;
            fastcgi_pass    unix:/var/run/rt3/rt3.socket;

            fastcgi_param  QUERY_STRING       $query_string;
            fastcgi_param  REQUEST_METHOD     $request_method;
            fastcgi_param  CONTENT_TYPE       $content_type;
            fastcgi_param  CONTENT_LENGTH     $content_length;
            fastcgi_param  PATH_INFO          $fastcgi_script_name;
    }

    location /NoAuth/ {
            alias   /usr/local/rt3/share/html/NoAuth/;
    }

It seems that declaring SCRIPT_NAME /and/ PATH_INFO clobbers some functions so be sure to use only PATH_INFO.

A small patch needs to be applied to mason_handler.fcgi to run properly under FastCGI witn nginx. Problem - nginx not send PATH_INFO to fastcgi server.

First apply next patch to mason_handler.fcgi:

 --- ./bin/mason_handler.fcgi    2005-12-02 08:23:20.000000000 -0500
 +++ /usr/local/rt3/bin/mason_handler.fcgi       2005-12-02 11:54:56.000000000 -0500
 @@ -68,11 +68,17 @@
     Module::Refresh->refresh if $RT::DevelMode;
     RT::ConnectToDatabase();

+    my $path_info = $cgi->script_name;
+    $path_info =~ s/^\///;
+    $cgi->path_info($path_info);
+        $RT::Logger->crit($path_info);
+
     if ( ( !$Handler->interp->comp_exists( $cgi->path_info ) )
         && ( $Handler->interp->comp_exists( $cgi->path_info . "/index.html" ) ) ) {
         $cgi->path_info( $cgi->path_info . "/index.html" );
     }
-
+
+            $RT::Logger->crit($cgi->path_info);
     eval { $Handler->handle_cgi_object($cgi); };
     if ($@) {
         $RT::Logger->crit($@);

Then create config for vhost that you want run rt3 on:

(example of config for fastcgi socket path - /tmp/request_tracker and rt3 installation path - /usr/local/rt3/

server {
listen  IP_ADDRESS:PORT;
server_name     domain.com;

location /images/ {	   alias /usr/local/rt3/share/html/NoAuth/images/;    }

   location  / {
   fastcgi_pass  unix:/tmp/request_tracker;
   fastcgi_x_powered_by off; # default on
   fastcgi_param   DOCUMENT_ROOT   /usr/local/rt3/share/html;
   fastcgi_param   SCRIPT_FILENAME /usr/local/rt3/share/html$fastcgi_script_name;
   fastcgi_param   PATH_TRANSLATED /usr/local/rt3/share/html$fastcgi_script_name;
   fastcgi_param   SCRIPT_NAME  $fastcgi_script_name;
   fastcgi_param   QUERY_STRING    $query_string;
   fastcgi_param   CONTENT_TYPE    $content_type;
   fastcgi_param   CONTENT_LENGTH  $content_length;
   fastcgi_param   REDIRECT_STATUS 200;
   fastcgi_param   SERVER_ADDR     $server_addr;
   fastcgi_param   SERVER_PORT     $server_port;
   fastcgi_param   SERVER_PROTOCOL $server_protocol;
   fastcgi_param   SERVER_SOFTWARE "nginx/0.3.15";
   fastcgi_param   GATEWAY_INTERFACE       "CGI/1.1";
   fastcgi_param   SERVER_NAME     $server_name;
   fastcgi_param   SERVER_NAME     $server_name;
   fastcgi_param   REQUEST_URI     $request_uri;
   fastcgi_param   REQUEST_METHOD  $request_method;
   fastcgi_param   REMOTE_USER     $remote_user;
   fastcgi_param   REMOTE_ADDR     $remote_addr;
   fastcgi_param   REMOTE_PORT     $remote_port;
   }

location ~* .+\.(html|js|css)$  {       ....same as above location....     }

location  /NoAuth/ {     	alias /usr/local/rt3/share/html/NoAuth/;     }
}

All tested and working with rt 3.5.5

Other information about nginx and FastCGI can be found on our site - http://www.nginx.info (now russian only, will be translated soon)

PS. If you want run rt3 with prefix - domain.com/prefix/, so need to remove that prefix for path_info (in perl code of patch above)

RT 3.0 FastCGI configuration

!FastCGI configuration for Apache 2.0

(assumes FastCGI is already installed)

This is roughly what I had to do to get RequestTracker working using FastCGI on RedHat9 system.

1. Install suidperl package, if not already installed.

2. Edit first line of /opt/rt3/bin/mason_handler.fcgi to be

#!/usr/bin/suidperl
  
  

3. Add the following to /etc/httpd/conf/httpd.conf

LoadModule fastcgi_module modules/mod_fastcgi.so

FastCgiIpcDir /tmp
FastCgiServer /opt/rt3/bin/mason_handler.fcgi -idle-timeout 300 -processes 5
<VirtualHost *>
    ServerName rt-host-name.example.org
    DocumentRoot /opt/rt3/share/html

    AddHandler fastcgi-script fcgi
    ScriptAlias / /opt/rt3/bin/mason_handler.fcgi/

    <Location />
        AddDefaultCharset UTF-8
        SetHandler fastcgi-script
    </Location>
</VirtualHost>

!FastCGI configuration for Apache 1.3

LoadModule fastcgi_module libexec/apache/mod_fastcgi.so
AddModule mod_fastcgi.c

Outside the vhost:

FastCgiServer /opt/rt3/bin/mason_handler.fcgi -idle-timeout 300 -processes 5

In your vhost:

AddHandler fastcgi-script fcgi
ScriptAlias / /opt/rt3/bin/mason_handler.fcgi/
<Location />
      AddDefaultCharset UTF-8
      SetHandler fastcgi-script
</Location>

Since the default Apache install includes a Directory directive blocking access to / and another to allow for the DocumentRoot, you might need to add something like:

<Directory "/opt/rt3">
    Order allow,deny
    Allow from all
</Directory>

To allow access to that directory, too. The symptom is getting '403 Forbidden' and a line like 'client denied by server configuration' in your Apache error log, even for index.html. -- HowardJones

See also