tech notes

Nginx - Perl FastCGI How To

This article outlines the steps required to enable Perl cgi scripts to be ran on an Nginx web server similar to a typical Apache cgi-bin environment.

Unlike other web servers, Nginx doesn’t provide a native CGI environment for which you can execute scripts. This means that you will need to enable this feature manually. While this does mean more work, it pays of in a faster script execution environment and possible added security (depending on your implementation).

Enable execution environment for Perl scripts

  1. The first step is to provide a FastCGI wrapper to handle executing Perl code. This wrapper was posted by Denis S. Filimonov and like similar perl wrappers it requires the FCGI Perl module.
  2. For security purposes you will want to run this fastcgi wrapper script as a non privileged user.
  3. Now you will have to decide and edit the fastcgi-wrapper.pl script to define how you want Nginx to communicate with the fastcgi wrapper. You can configure this wrapper to listen on either TCP/IP sockets or UNIX sockets:
    sub main {
     #-- use IP sockets
     $socket = FCGI::OpenSocket( "127.0.0.1:8999", 10 ); 
    
     #-- use UNIX sockets - user running this script must have
     #-- write access to the '/var/run/nginx' folder!!
     $socket = FCGI::OpenSocket("/var/run/nginx/perl_cgi-dispatch.sock", 10);

    If you decide to use UNIX sockets you will need to make sure to allow write permissions for the user that this wrapper will be executed by on the directory which is designated to house the UNIX socket.

    As you can see in the excerpt above, the default location of this socket is “/var/run/nginx/perl_cgi-dispatch.sock”.  Once this Perl wrapper is running you should be able to see the UNIX socket it created in the /var/run/nginx/ directory.

     # ls -l /var/run/nginx/
      srwxrwxrwx 1 nginx nginx 0 2009-02-02 14:54 perl_cgi-dispatch.sock=

  4. Next, as with Apache, you will need to create a cgi-bin directory for your website. Here is how you configure nginx so that it knows where your cgi-bin directory is located and to allow the execution of your Perl cgi scripts from within this directory (this is contained within a server {} block):
    # /cgi-bin configuration
    location ~ ^/cgi-bin/.*\.cgi$ {
      gzip off;
      fastcgi_pass  unix:/var/run/nginx/perl_cgi-dispatch.sock;  [1]*
      fastcgi_param SCRIPT_FILENAME /www/blah.com$fastcgi_script_name; [2]*
      include fastcgi_params; [3]*
    }

    [1] The fastcgi_pass statement tells Nginx where to pass CGI requests for processing (e.g. the unix socket that the wrapper script is listening on)
    [2] The fastcgi_param SCRIPT_FILENAME statement above tells Nginx that cgi scripts are located on the file system at:

    /www/blah.com/cgi-bin/<scriptname>.cgi

    [3] Here is the contents of my fastcgi_params file:

    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_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  GATEWAY_INTERFACE  CGI/1.1;
    fastcgi_param  SERVER_SOFTWARE    nginx/$nginx_version;
    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;

  5. Once this configuration has been made, make sure that you place your perl cgi scripts with .cgi extensions in the /cgi-bin directory and make sure they are executable. Restart nginx and everything should be good to go.


6 Comments Send your comment

  1.   David

    The link to the perl script hosted on your server no longer works.

  2.   admin

    Thanks David. It got lost in a migration, but is now replaced. I also posted a link in this article so that people can grab it directly from the ruby forum from which I obtained it at: http://www.ruby-forum.com/topic/145858

    I used this particular perl-wrapper.pl script as Denis S. Filimonov has modified it to handle HTTP/CGI POST requests properly.

  3.   Gordon

    The script doesn’t work for me. It fails with an error like “can’t find unistd_64.ph”. I’ve verified that all the files listed in requires exist, and are readable, and have tried with Perl 5.8.8 and 5.10.1. Any idea what’s going wrong?

  4.   admin

    I had this problem when I was running slackware. Running ‘h2ph’ resolved this issue for me. You can read more here: http://www.ruby-forum.com/topic/168240

  5.   bob

    Thanks for the guide. After a lot of hassle, I now have perl working.

    What do I need to do to have the fcgi listener load automatically on startup?

  6.   admin

    You could create a proper init script customized to your specific OS, but this can be time consuming depending on your requirements. Alternatively, you can simply modify rc.local by adding the desired commands. Here is a quick guide on how to do this: http://www.linux4beginners.info/?q=node/boot-shellscript-non-root


Leave a Reply