Unable to set up Nginx to handle PHP along with proxy_pass

I have three requirements from my Nginx setup:

  1. Forward all requests on / to my Java server running on port 9001
  2. Intercept all static file URLs and serve them through Nginx itself.
  3. Serve a particular base URL from a folder containing PHP scripts.

Of these, I'm able to achieve the first two, but when I visit http://localhost/ecwid_fu_scripts/ through my web browser, the request is intercepted by the Java server running on port 9001, and doesn't get routed to the index.php in /home/ankush/ecwid_fu_scripts/. Here's my Nginx configuration:

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

    server_name _;

    location /assets/images/ {
        root /home/ankush/fu_main_files/;
        autoindex off;
        sendfile on; 
        tcp_nopush on; 
        tcp_nodelay on; 
        keepalive_timeout 100;
    }   

    location /ecwid_fu_scripts/ {
        index index.php;
        root /home/ankush/ecwid_fu_scripts/;
        try_files $uri $uri/ /index.php?q=$uri&$args;
    }   

    location / { 
        proxy_pass http://localhost:9001;
    }   

    location ~ \.php$ {
        try_files $uri =404;
        fastcgi_split_path_info ^(.+\.php)(/.+)$;
        fastcgi_pass unix:/run/php/php7.0-fpm.sock;
        fastcgi_index index.php;
        include fastcgi_params;
    }
}

Solution 1:

Your issue is with the root directive, and the scope of this root.

location /ecwid_fu_scripts/ {
    root /home/ankush/ecwid_fu_scripts/;

In this case, when someone requests example.com/ecwid_fu_scripts/, nginx is looking for the files in the defined root, plus the location. This becomes /home/ankush/ecwid_fu_scripts/ecwid_fu_scripts/, which is not where your index.php is located.

To solve this, you have two choices (with #2 being the preferred option, if you have freedom over your project):

  1. Change the root of that location block to /home/ankush/ instead.
  2. Or restructure your project structure so everything is in one relative project folder. Now, set the global root -- the directive outside of any location block -- to the new project folder name (let's say root /home/ankush/ecwid_files/;, after the server_name directive).

Now, we still need to add the contents of the location ~ \.php$ block inside the location /ecwid_fu_scripts/ block, because when the root is changed, things relating to this new root needs to used in the same block. This is because of this type of pitfall: the location block for ecwid_fu_scripts is saying it's a .php file, it does try_files, and then it finishes with this block, and sent off to the next-related block: the global location ~ \.php$. Problem is, it doesn't know what the root is anymore, since it isn't defined globally. Thus, fastcgi_pass in this block isn't getting the full path.

So in the end, your config will look like this with option #1:

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

    server_name _;

    location /assets/images/ {
        root /home/ankush/fu_main_files/;
        autoindex off;
        sendfile on; 
        tcp_nopush on; 
        tcp_nodelay on; 
        keepalive_timeout 100;
    }   

    location /ecwid_fu_scripts/ {
        index index.php;
        root /home/ankush/;

        include snippets/fastcgi-php.conf;
        fastcgi_pass unix:/run/php/php7.0-fpm.sock;
    }   

    location / { 
        proxy_pass http://localhost:9001;
    }   

    location ~ \.php$ {
        include snippets/fastcgi-php.conf;
        fastcgi_pass unix:/run/php/php7.0-fpm.sock;
    }
}