Running MovableType on Nginx

作者:   發佈於:  

While the lack of native CGI support in nginx, it is still possible to run MovableType (and other CGI scripts) with nginx. The tool for the missing link is fcgiwrap. It acts like a proxy that converts FCGI requests to CGI requests, so there is no need to modify the CGI programs.

fcgiwrap should be run as a daemon and take requests from an unix socket file. /var/run/fcgiwrap.socket is used in the following example,

Let's say I want my MT admin interface accessible from http://example.com`, here's a complete server section config for a MT installation under/var/www/mt`:

server {
    server_name example.com;
    root   /var/www/mt;

    location ~ ^/mt.*\.cgi {
        ## The exact pattern is required for MT.
        fastcgi_split_path_info ^(/mt.*.cgi)(.*)$;

        ## Generally needed for all FCGI scripts
        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  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;

        ## MT-related        
        fastcgi_param PERL5LIB $document_root/lib;
        fastcgi_param MT_HOME $document_root/;
        fastcgi_param MT_CONFIG $document_root/mt-config.cgi;

        ## fcgiwrap-related
        fastcgi_param SCRIPT_NAME     $document_root$fastcgi_script_name";
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name";
        fastcgi_param PATH_INFO       $fastcgi_path_info;
        fastcgi_param PATH_TRANSLATED $document_root$fastcgi_path_info;

        fastcgi_pass unix:/var/run/fcgiwrap.socket;
    }

The value of SCRIPT_FILENAME is determined per-request from URI. That is, http://example.com/mt.cgi` will be eventually translated to/var/www/mt/mt.cgi and pass-through thefcgiwrap.socket`as the program name to be executed.

Therefore it should be notified that the user and permission setting of fcgiwrap daemon and /var/www/mt should match because MT CGIs need write permission to /var/www/mt (the $MT_HOME.)

Also notice the line:

fastcgi_split_path_info ^(/mt.*.cgi)(.*)$;

The value captured in the first capture group will be the value of $fastcgi_script_name. I was previously attempted to write a more generic pattern to capture anything before the first ? like:

fastcgi_split_path_info ^(/[^/]+)(\?.*)$;

This generally works, but the MT installation wizard fails with the setting. Turns out the MT installation wizard send requests with extra spaces before query string part, that is something looks like /mt.cgi%22?r=.34234123. Therefore the pattern needs to be tweaked.