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.

  • Is the file containing your server block actually linked in sites-enabled? Nov 28 '16 at 4:37
  • Download some sample Nginx config files for Wordpress from my tutorial photographerstechsupport.com/tutorials/…
    – Tim
    Nov 28 '16 at 7:14
  • Yes, the file is linked in sites-enabled. I can get the home page, the test page, and even the post pages when I set the permalinks to Plain. I assume I could not get those without the symbolic link.
    – dkusleika
    Nov 28 '16 at 14:31
  • Try changing "location ~ .*\.php$ {" to "location ~ \.php$ {"
    – Tim
    Dec 2 '16 at 0:30
  • @dkusleika, when I go to the link li394-200.members.linode.com/archives/2016/11/02/…, it is displayed correctly. Have you tried to clean the cache from your browser? If not you may try to restart it, or try it from another pc, just to be sure it's not a client side problem.
    – Diamond
    Dec 5 '16 at 8:31

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.


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".

  • One further information: You referenced /etc/nginx/snippets/fastcgi-php.conf in your second location block ;)
    – dim-0
    Dec 2 '16 at 0:57
  • Alright, one more. You are asking about FastCGI: In your second location block you advice nginx to forward all requests to a file which ends in ".php" to PHP's FastCGI Process Manager (php-fpm). This is because nginx cannot render PHP itself.
    – dim-0
    Dec 2 '16 at 1:01
  • Coming to your last question: The first location block tells nginx to act when the root directory (location /) of the server name is contacted (directive server_name example.com). If that happens, nginx is told to try different files, such as the URI, the URI plus slash and if even this fails the file index.php, which then triggers the second location block again.
    – dim-0
    Dec 2 '16 at 1:07
  • You know you can edit your answer, right? That way you can ensure you've created a coherent, easy to understand, well formatted answer.
    – Tim
    Dec 2 '16 at 1:25
  • I posted the first comment as an additional post as it only gives further information that is not directly connected to my solution. However, after sending my comment, I realized that I'm not able to edit it afterwards... And in order to make it not even more confusing, I added all the other background information as additional comments. I'm very sorry, still. I'd also prefer to keep it clean.
    – dim-0
    Dec 2 '16 at 1:36

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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