Search code examples
nginxsubdirectory

nginx configure /folder run from a different path than the /


I am having an issue running /folder from a different path than the main website.

my nginx.conf for that section look like this:

        location ~ \.php$ {
            try_files               $uri = 404;
            fastcgi_split_path_info ^(.+\.php)(/.+)$;
        fastcgi_param       SCRIPT_FILENAME $request_filename;
            fastcgi_pass            unix:/var/run/php/php7.2-fpm.sock;
            fastcgi_index           index.php;
           include                 fastcgi_params;
            include                 fastcgi.conf;
    }


location ~ /folder {
        alias /srv/http/folder;
    try_files $uri $uri/ @folder;

    location ~ \.php$ {
                fastcgi_param SCRIPT_FILENAME $request_filename;
                fastcgi_pass   unix:/var/run/php/php7.2-fpm.sock;
                include        fastcgi.conf;
        }
}

location @folder {
    rewrite /folder/(.*)$ /folder/index.php?/$1 last;
}

In the error.log I can see the following:

2020/06/03 09:05:26 [error] 25966#25966: *1 FastCGI sent in stderr: "Primary script unknown" while reading response header from upstream, client: 172.21.2.46, server: example.com, request: "GET /folder/xxx_v6.15.11/Resources/images/redcaplogo.gif HTTP/1.1", upstream: "fastcgi://unix:/var/run/php/php7.2-fpm.sock:", host: "example.com"

Any suggestion how to fix this?


Solution

  • Regex locations are matched from first to last, and the first found match processed by nginx. When you get a request for /folder/script.php, it is processed by the first location block. Try to swap this two locations. Additionaly, why are you do not include fastcgi_params in your second location block?

    Update

    I did some debugging, lets look at you code (assuming location block already swapped):

    location ~ /folder {
        alias /srv/http/folder;
        try_files $uri $uri/ @folder;
    
        location ~ \.php$ {
            fastcgi_param  SCRIPT_FILENAME $request_filename;
            fastcgi_pass   unix:/var/run/php/php7.2-fpm.sock;
            include        fastcgi_params;
            include        fastcgi.conf;
        }
    }
    
    location ~ \.php$ {
        try_files               $uri =404;
        fastcgi_split_path_info ^(.+\.php)(/.+)$;
        fastcgi_param           SCRIPT_FILENAME $request_filename;
        fastcgi_pass            unix:/var/run/php/php7.2-fpm.sock;
        fastcgi_index           index.php;
        include                 fastcgi_params;
        include                 fastcgi.conf;
    }
    
    location @folder {
        rewrite /folder/(.*)$ /folder/index.php?/$1 last;
    }
    

    If we get a request /folder/some/path (and there is no some/path file or directory inside the folder), inside the nested location internal nginx variables would have following values:

    • $request_filename: empty string (there is no real file or folder /some/path inside th folder directory);
    • $uri: /folder/check.php;
    • $document_root: /srv/http/folder.

    If we get a request /folder/some/path/script.php (and there is a real PHP script with this name), inside the nested location internal nginx variables would have following values:

    • $request_filename: /srv/http/folder/some/path/script.php;
    • $uri: /folder/some/path/check.php;
    • $document_root: /srv/http/folder.

    Additionally, when you get a request for a static resource from your folder, for example /folder/some/path/static.css, the try_files $uri ... directive will search folder/some/path/static.css file in a /srv/http/folder directory, which leads to check the existence of /srv/http/folder/folder/some/path/static.css file.

    One of possible solutions to get a file subpath inside the folder directory:

    location ~ ^/folder(?<subpath>.*) {
        alias /srv/http/folder;
        try_files $subpath $subpath/ @folder;
    
        location ~ \.php$ {
            fastcgi_param  SCRIPT_FILENAME $document_root$subpath;
            fastcgi_pass   unix:/var/run/php/php7.2-fpm.sock;
            include        fastcgi_params;
            include        fastcgi.conf;
        }
    }
    
    location ~ \.php$ {
        try_files               $uri =404;
        fastcgi_split_path_info ^(.+\.php)(/.+)$;
        fastcgi_param           SCRIPT_FILENAME $request_filename;
        fastcgi_pass            unix:/var/run/php/php7.2-fpm.sock;
        fastcgi_index           index.php;
        include                 fastcgi_params;
        include                 fastcgi.conf;
    }
    
    location @folder {
        rewrite ^/folder/(.*)$ /folder/index.php?/$1 last;
    }
    

    This could be simplified if your real folder directory name is the same as your /folder URI prefix:

    location ~ ^/folder {
        root /srv/http;
        try_files $uri $uri/ @folder;
    
        location ~ \.php$ {
            fastcgi_param  SCRIPT_FILENAME $document_root$uri;
            fastcgi_pass   unix:/var/run/php/php7.2-fpm.sock;
            include        fastcgi_params;
            include        fastcgi.conf;
        }
    }
    
    ...
    

    As nginx documentation states:

    When location matches the last part of the directive’s value:

    location /images/ {
      alias /data/w3/images/;
    }
    

    it is better to use the root directive instead:

    location /images/ {
      root /data/w3;
    }