Nginx Downloads PHP instead of Rendering

nginxphp-fastcgiWordpress

I'm trying to move a WordPress site to Nginx from Apache. When I go to the main site, it renders as expected. When I click on a post, it tries to download index.php instead of processing/rendering it.

I setup nginx according to https://www.linode.com/docs/websites/lemp/lemp-server-on-ubuntu-16-04

My nginx.conf

user www-data;
worker_processes auto;
pid /run/nginx.pid;

events {
    worker_connections 768;
    # multi_accept on;
}

http {
    sendfile on;
    tcp_nopush on;
    tcp_nodelay on;
    keepalive_timeout 65;
    types_hash_max_size 2048;

    include /etc/nginx/mime.types;
    default_type application/octet-stream;

    ssl_protocols TLSv1 TLSv1.1 TLSv1.2; # Dropping SSLv3, ref: POODLE
    ssl_prefer_server_ciphers on;

    access_log /var/log/nginx/access.log;
    error_log /var/log/nginx/error.log;

    gzip on;
    gzip_disable "msie6";


    include /etc/nginx/conf.d/*.conf;
    include /etc/nginx/sites-enabled/*;
}

and my li394-200.members.linode.com file in sites-available

server {
    listen 80;
    listen [::]:80;

    server_name li394-200.members.linode.com;

    root /var/www/html/li394-200.members.linode.com/public_html;
    index index.html index.php;

    location / {
        try_files $uri $uri/ /index.php$args =404;
    }

    location ~ .*\.php$ {
        include snippets/fastcgi-php.conf;
        include fastcgi_params;
        fastcgi_pass unix:/run/php/php7.0-fpm.sock;
        fastcgi_param SCRIPT_FILENAME /var/www/html/li394-200.members.linode.com/public_html$fastcgi_script_name;
    }
}

If I navigate to http://li394-200.members.linode.com/phptest.php it renders as expected. Also http://li394-200.members.linode.com/index.php is correct. But if I go to http://li394-200.members.linode.com/archives/2016/11/02/international-keyboard-shortcut-day-2016/ it says 'You have chosen to open … application/octet-stream.' When I say OK and download it, it's index.php from my wordpress directory.

My permalink structure is /archives/%year%/%monthnum%/%day%/%postname%/. If I change the permalink to Plain, I can navigate to http://li394-200.members.linode.com/?p=11240 correctly.

I followed the advice at http://nginxlibrary.com/wordpress-permalinks/ and added

try_files $uri $uri/ /index.php?args;

to the location block. When I restart nginx, I get

[emerg] try_files directive is duplicate in /etc/nginx/snippets/fastcgi-php.conf:5

I don't even see where I'm including that file. But that file looks like

# regex to split $uri to $fastcgi_script_name and $fastcgi_path
fastcgi_split_path_info ^(.+\.php)(/.+)$;

# Check that the PHP script exists before passing it
try_files $fastcgi_script_name =404;

# Bypass the fact that try_files resets $fastcgi_path_info
# see: http://trac.nginx.org/nginx/ticket/321
set $path_info $fastcgi_path_info;
fastcgi_param PATH_INFO $path_info;

fastcgi_index index.php;
include fastcgi.conf;

so $fastcgi_script_name must contain the same thing, but I don't know how to see what that is. I don't see anything in my public_html directory that looks like a fast-cgi script (although I might not know it when I see it).

Whether I use my custom permalink or the default one, there is no .php in the URI, so I don't get how that location directive is even capturing it.

Best Answer

Two thoughts about it:

  • You state default_type application/octet-stream;. Please set this to default_type text/plain; or simply remove it, as I think you don't want to serve "multipurpose application files", correct? More information here: http://www.mime-type.net/application/octet-stream/
  • Please check, whether your php-fpm socket is set correctly. It might be /var/run/... or named differently if you have a socket running (check your php-fpm settings); otherwise most installations use loopback port 9000.

EDIT:

Just realized another problem with your config: You should change "/index.php$args" or "/index.php?args" to "/index.php?$args".

The reason is the following: nginx matches your regular expression and then sets the variable "$args" to whatever comes after your slash. The question mark in turn separates the filename from the arguments.

So "/index.php$args" would end up in "/index.phpwhateverargument" whereas "/index.php?args" would just stay "/index.php?args". What you want instead is "/index.php?whateverargument".