Server Fault is a question and answer site for system and network administrators. Join them; it only takes a minute:

Sign up
Here's how it works:
  1. Anybody can ask a question
  2. Anybody can answer
  3. The best answers are voted up and rise to the top

I am using Nginx + PHP-FPM to run a Wordpress based site. I have a URL that should return dynamically generated JSON data for use with the DataTables jQuery plugin. The data is returned properly, but with a return code of 404. I think this is a Nginx config issue, but I haven't been able to figure out why. The script 'getTable.php' works properly on the production version of the site which is currently using Apache. Anyone know how I can get this to work on Nginx?


SERVER: CentOS 6 + Varnish (caching disabled for development) + Nginx + PHP-FPM + Wordpress + W3 Total Cache

Nginx Config:

    server {

    # Server Parameters
    root         /var/www/;
    access_log   /var/www/ main;
    error_log    /var/www/ error;
    index        index.php;

    # Rewrite minified CSS and JS files
    location ~* \.(css|js) {
        if (!-f $request_filename) {
            rewrite ^/wp-content/w3tc/min/(.+\.(css|js))$ /wp-content/w3tc/min/index.php?file=$1 last;
            expires         max;

    # Set a variable to work around the lack of nested conditionals
    set $cache_uri $request_uri;

    # Don't cache uris containing the following segments
    if ($request_uri ~* "(\/wp-admin\/|\/xmlrpc.php|\/wp-(app|cron|login|register|mail)\.php|wp-.*\.php|index\.php|wp\-comments\-popup\.php|wp\-links\-opml\.php|wp\-locations\.php)") {
        set $cache_uri "no cache";

    # Don't use the cache for logged in users or recent commenters
    if ($http_cookie ~* "comment_author|wordpress_[a-f0-9]+|wp\-postpass|wordpress_logged_in") {
        set $cache_uri 'no cache';

    # Use cached or actual file if they exists, otherwise pass request to WordPress
    location / {
        try_files /wp-content/w3tc/pgcache/$cache_uri/_index.html $uri $uri/ /index.php?q=$uri&$args;

    # Cache static files for as long as possible
    location ~* \.(xml|ogg|ogv|svg|svgz|eot|otf|woff|mp4|ttf|css|rss|atom|js|jpg|jpeg|gif|png|ico|zip|tgz|gz|rar|bz2|doc|xls|exe|ppt|tar|mid|midi|wav|bmp|rtf)$ {
        try_files       $uri =404;
        expires         max;
        access_log      off;

    # Deny access to hidden files
    location ~* /\.ht {
        deny            all;
        access_log      off;
        log_not_found   off;

    location ~ \.php$ {

        try_files      $uri =404;
        fastcgi_split_path_info ^(.+\.php)(/.+)$;
        include        /etc/nginx/fastcgi_params;

        fastcgi_index  index.php;
        fastcgi_param  SCRIPT_FILENAME    $document_root$fastcgi_script_name;
        fastcgi_param  PATH_INFO          $fastcgi_script_name;
        fastcgi_intercept_errors on;
        fastcgi_pass   unix:/var/lib/php-fpm/php-fpm.sock;  # port where FastCGI processes were spawned



Fast CGI Params:

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  HTTPS              $https if_not_empty;

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;

UPDATE: Upon further digging, it looks like Nginx is generating the 404 and PHP-FPM is executing the script properly and returning a 200.

UPDATE: Here are the contents of the script:

 * Connect to Wordpres
require(dirname(__FILE__) . '/../../../../wp-blog-header.php');

 * Define temporary array
$aaData = array();
$aaData['aaData'] = array();

 * Execute Query
$query = new WP_Query(
        'post_type'      => 'post',
        'posts_per_page' => '-1'

foreach ($query->posts as $post) {



 * Echo JSON encoded array
echo json_encode($aaData);
share|improve this question

closed as off topic by Michael Hampton, Jay, Wesley, John Gardeniers, mdpc Nov 26 '12 at 18:10

Questions on Server Fault are expected to relate to server, networking, or related infrastructure administration within the scope defined by the community. Consider editing the question or leaving comments for improvement if you believe the question can be reworded to fit within the scope. Read more about reopening questions here.If this question can be reworded to fit the rules in the help center, please edit the question.

The dev version of the site is pretty much a copy of production. I trying to get Nginx working 100% in dev so we can move to it in production. The production version of the script (…) loads correctly and returns a 200. I'll add the contents of the script to the question. – MorfiusX Nov 24 '12 at 15:27
up vote 1 down vote accepted

Panagiotis Papadomitsos's questions caused me to test a couple of new possible causes. I found the following article:

I change the following line in my code:

regquire(dirname(__FILE__) . '/../../../../wp-blog-header.php');


require(dirname(__FILE__) . '/../../../../wp-config.php');

It seems the root cause it that Wordpress was returning the 404, not Nginx, and not PHP-FPM.

share|improve this answer
Glad you worked that out man! – Panagiotis PJ Papadomitsos Nov 25 '12 at 17:28

Try turning off error interception:

fastcgi_intercept_errors on;

and see what happens. Also, could you please paste the relevant lines of the access & error log when you request the script?

share|improve this answer
access.log - - [24/Nov/2012:18:34:20 +0000] "GET /wp-content/plugins/ils-workflow/lib/getTable.php?_=1353782052693 HTTP/1.1" 404 43476 "…; "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:16.0) Gecko/20100101 Firefox/16.0" "-" error.log (Nothing relevant, just errors from trying different configs) fastcgi_intercept_errors on; Same issue when off or on. – MorfiusX Nov 24 '12 at 18:38
Try turning on the PHP-FPM access log via the directive access_log = 'path/file.log' and check if the request is forwarded properly and what the response is. There is also the possibility that the script runs in whole, but the include directive that includes the WP blog header generates a 404 HTTP header deliberately (bug?). – Panagiotis PJ Papadomitsos Nov 25 '12 at 3:21
You comments lead me to conducting another test. If I remove the wp-blog-header.php, the document is returned with a 200 status code. – MorfiusX Nov 25 '12 at 15:18

Not the answer you're looking for? Browse other questions tagged or ask your own question.