Score:1

Nginx - changing root folder for specific url gives 404 error

us flag

I am trying to arrange a location block for anyone get through mydomain.com/game/admin url, make sure the nginx server to pull the content exists in /var/www/html/my-cakephp-app/ directory. My application is built using cakephp framework and its directory structure is shown below:

  • /var/www/html/my-cakephp-app/
    • admin
      • Config
      • Console
      • Controller
      • View
      • webroot (App entry-point index.php file exists in this directory)

Also I have static html/css website located in the /var/www/html directory. So anyone with mydomain.com url can see that website too.

Here is my current nginx server block:

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

    root /var/www/html;

    index index.html index.htm index.php;

    server_name mydomain.com;

    location / {
        try_files $uri $uri/ =404;
    }
    
    location /game/admin {
            return 301 /game/admin/;
    }

    location /game/admin/ {

                root /var/www/html/my-cakephp-app/admin/webroot;
                try_files $uri $uri/ /game/admin/index.php$is_args$args;
  
                location ~* \.php(/|$) {
                  include snippets/fastcgi-php.conf;
                  fastcgi_pass unix:/var/run/php/php7.4-fpm.sock;
                  fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
               } 

    }

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

    location ~ /\.ht {
        deny all;
    }
}

With this setup, my static web-site working fine. But cakephp application gives 404 not found error in browser. No any errors in the nginx/error.log.

But when I run with below nginx configuration, my application works fine. But I have to get rid of my html/css site.I am planning to upgrade html/css app with a wordpress site. So I should have the ability to run the wordpress site as the parent.

server {
    listen 80;
    server_name mydomain.com;
    root /var/www/html/my-cakephp-app/admin/webroot;
    
    index index.html index.htm index.php;
 
    location / {
        try_files $uri $uri/ /index.php$is_args$args;
        autoindex on;
    }
    
    location ~ \.php$ {
        include snippets/fastcgi-php.conf;
        fastcgi_pass unix:/run/php/php7.0-fpm.sock;
    }
    
    location ~ /\.ht {
        deny all;
    }
}

I couldn't think of what I have done wrong with the first server block. Any suggestions would be really helpful.

Score:1
jp flag

The two main problems are:

  • the outer location ~ \.php$ block takes precedence over the location /game/admin/ block unless you use the ^~ modifier (see this document for details)
  • the root directive generates a path to the file by simple concatenation, so your controller is expected to be located at /var/www/html/my-cakephp-app/admin/webroot/game/admin/index.php (see this document for details)

One option is to move the project so that the directory structure matches the URI structure. This could be achieved using a symbolic link which points /var/www/html/game/admin to /var/www/html/my-cakephp-app/admin/webroot in which case the outer location ~ \.php$ block will be able to execute both projects.


Another option is the alias directive. See this document for details.

location ^~ /game/admin {
    alias /var/www/html/my-cakephp-app/admin/webroot;

    if (!-e $request_filename) { rewrite ^ /game/admin/index.php last; }

    location ~ \.php$ {
        if (!-f $request_filename) { return 404; }

        include snippets/fastcgi-php.conf;
        fastcgi_pass unix:/var/run/php/php7.4-fpm.sock;
        fastcgi_param SCRIPT_FILENAME $request_filename;
    }
}

Note that $document_root$fastcgi_script_name will not work with alias and that $request_filename should be used instead.

I avoid using alias and try_files together due to this issue. See this caution on the use of the if directive.

Madushan Perera avatar
us flag
Your solution works perfectly fine. I was wasting my time with root directive whole day. Anyways, thank you so much for the good explanation.
mangohost

Post an answer

Most people don’t grasp that asking a lot of questions unlocks learning and improves interpersonal bonding. In Alison’s studies, for example, though people could accurately recall how many questions had been asked in their conversations, they didn’t intuit the link between questions and liking. Across four studies, in which participants were engaged in conversations themselves or read transcripts of others’ conversations, people tended not to realize that question asking would influence—or had influenced—the level of amity between the conversationalists.