First thing, I recommend keeping all your typical FCGI settings in a single file and importing them.

For example you might have an /etc/nginx/fastcgi.conf file that looks like this:

#fastcgi.conf
fastcgi_param  GATEWAY_INTERFACE  CGI/1.1;
fastcgi_param  SERVER_SOFTWARE    nginx;
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  SCRIPT_FILENAME    $document_root$fastcgi_script_name;
fastcgi_param  SCRIPT_NAME        $fastcgi_script_name;
fastcgi_param  REQUEST_URI        $request_uri;
fastcgi_param  DOCUMENT_URI       $document_uri;
fastcgi_param  DOCUMENT_ROOT      $document_root;
fastcgi_param  SERVER_PROTOCOL    $server_protocol;
fastcgi_param  REMOTE_ADDR        $remote_addr;
fastcgi_param  REMOTE_PORT        $remote_port;
fastcgi_param  SERVER_ADDR        $server_addr;
fastcgi_param  SERVER_PORT        $server_port;
fastcgi_param  SERVER_NAME        $server_name;
# PHP only, required if PHP was built with --enable-force-cgi-redirect
#fastcgi_param  REDIRECT_STATUS    200;

This allows you to keep your individual FCGI configurations as simple as possible.

To use Nginx + Virtual Host + PHP you should ommit the SCRIPT_NAME variable in order for PHP to choose the correct DOCUMENT_ROOT.

Spawning a FastCGI Process

Unlike Apache or Lighttpd, Nginx does not automatically spawn FCGI processes. You must start them separately. In fact, FCGI is a lot like proxying. There's a few ways to start FCGI programs, I happen to like using the spawn-fcgi program that comes with Lighttpd. This example shows starting an instance of PHP4 on port 10004 and PHP5 on port 10005 (adjust paths accordingly):

/usr/local/bin/spawn-fcgi -a 127.0.0.1 -p 10004 -u lighttpd -g lighttpd -f /usr/lib/php4/bin/php-cgi
/usr/local/bin/spawn-fcgi -a 127.0.0.1 -p 10005 -u lighttpd -g lighttpd -f /usr/lib/php5/bin/php-cgi

NOTE: In order to use lighttpd's spawn-fcgi process like this you'll need to do one of three things:

1. Verify (and if needed set) the proper permissions on /var/lib/php/session

$ cd /var/lib/php
$ ls -l

drwxrwx---  2 root apache   4096 Nov  9 13:56 session

$ chown root:lighttpd session
$ ls -l

drwxrwx---  2 root lighttpd 4096 Nov  9 13:56 session

2. Change the php.ini to reflect a different session directory

cd /var/my/session
mkdir dir
chown root:lighttpd dir

vi /etc/php.ini
change session.save_path = "/var/lib/php/session" to session.save_path = "/var/my/session/dir"

3. Or just use the apache user/group for the FastCGI processes (I don't use the apache user for anything else on my system, and it's already non-privileged).

/usr/local/bin/spawn-fcgi -a 127.0.0.1 -p 10004 -u apache -g apache -f /usr/lib/php4/bin/php-cgi
/usr/local/bin/spawn-fcgi -a 127.0.0.1 -p 10005 -u apache -g apache -f /usr/lib/php5/bin/php-cgi

Connecting Nginx to a running FastCGI Process

Now that the FCGI process is running, we must tell Nginx to proxy requests to it via the FCGI protocol:

http {
    index index.php;
    root  /var/www/htdocs;
    # .php and .php4 sent to php4
    location ~ .*\.php4?$ {
        include /etc/nginx/fcgi.conf;
        fastcgi_pass  127.0.0.1:10004;
        fastcgi_index index.php;
    }
    # .php5 sent to php5
    location ~ .*\.php5$ {
        include /etc/nginx/fcgi.conf;
        fastcgi_pass  127.0.0.1:10005;
        fastcgi_index index.php;
    }
}

Restart Nginx.

Secure your upload directory!!

Too many example configs fail to secure the "uploads" directory of the application. Remember that if someone can upload a file named xyz.php and the uploads dir is publically accessible then you have given the attacker an easy way to insert PHP onto your site...

So if your app has an upload dir "/images/" then adjust your fastcgi call along the lines of:

http {
    index index.php;
    root  /var/www/htdocs;
    # .php
    location ~ .*\.php$ {
        include /etc/nginx/fcgi.conf;
        if ( $uri !~ "^/images/") {
          fastcgi_pass  127.0.0.1:10004;
        }
        fastcgi_index index.php;
    }
}

NginxFcgiExample (last edited 2008-05-06 17:57:24 by NickRodgers)