Skip to main content
added 42 characters in body
Source Link
Ivan Shatsky
  • 4k
  • 2
  • 10
  • 25

So your location should look like (wrong example! see the update to answer)

So your location should look like

So your location should look like (wrong example! see the update to answer)

added 2903 characters in body
Source Link
Ivan Shatsky
  • 4k
  • 2
  • 10
  • 25

Update @ 2025.01.22

It turns out that two of the three configuration variants where the try_files directive was being used, contain mistakes regarding the usage of this directive.

The variant I proposed:

try_files /dev/null /index.php$is_args$args; 

will result in an internal redirection loop. Additionally, using /dev/null as the first parameter of the try_files directive offers no performance benefit, contrary to what is suggested here.

The variant proposed by @TeroKilkanen:

try_files /index.php$is_args$args =404; 

is closer to being correct. However, the $is_args and $args nginx variables should not be used in this context because they will be treated as part of the physical filename rather than the query string. Consequently, any request with a query string will fail with this configuration.

Moreover, the snippets/fastcgi-php.conf file (a configuration snippet packaged with nginx on Debian-based Linux distributions) contains the following:

# 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; 

If this snippet is included in the PHP location block that already contains a try_files directive, it will cause the following error during configuration validation at nginx startup:

nginx: [emerg] "try_files" directive is duplicate in ... 

That being said, there are two correct options to achieve the behavior the OP desires:

  1. Using the try_files directive to additionally check an existence of the index.php file:
    location / { try_files /index.php =404; include fastcgi_params; fastcgi_param SCRIPT_FILENAME $request_filename; fastcgi_pass unix://var/run/php/php7.3-fpm.sock; } 
  2. Skip the existence check for better performance explicitly specifying the PHP script filename (if you are certain that the index.php file always exists):
    location / { include fastcgi_params; fastcgi_param SCRIPT_FILENAME $document_root/index.php; fastcgi_pass unix://var/run/php/php7.3-fpm.sock; } 
    Or even explicitly specifying the full path to the index.php file (this way the root directive can be omitted al all):
    location / { include fastcgi_params; fastcgi_param SCRIPT_FILENAME /full/path/to/index.php; fastcgi_pass unix://var/run/php/php7.3-fpm.sock; } 

Update @ 2025.01.22

It turns out that two of the three configuration variants where the try_files directive was being used, contain mistakes regarding the usage of this directive.

The variant I proposed:

try_files /dev/null /index.php$is_args$args; 

will result in an internal redirection loop. Additionally, using /dev/null as the first parameter of the try_files directive offers no performance benefit, contrary to what is suggested here.

The variant proposed by @TeroKilkanen:

try_files /index.php$is_args$args =404; 

is closer to being correct. However, the $is_args and $args nginx variables should not be used in this context because they will be treated as part of the physical filename rather than the query string. Consequently, any request with a query string will fail with this configuration.

Moreover, the snippets/fastcgi-php.conf file (a configuration snippet packaged with nginx on Debian-based Linux distributions) contains the following:

# 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; 

If this snippet is included in the PHP location block that already contains a try_files directive, it will cause the following error during configuration validation at nginx startup:

nginx: [emerg] "try_files" directive is duplicate in ... 

That being said, there are two correct options to achieve the behavior the OP desires:

  1. Using the try_files directive to additionally check an existence of the index.php file:
    location / { try_files /index.php =404; include fastcgi_params; fastcgi_param SCRIPT_FILENAME $request_filename; fastcgi_pass unix://var/run/php/php7.3-fpm.sock; } 
  2. Skip the existence check for better performance explicitly specifying the PHP script filename (if you are certain that the index.php file always exists):
    location / { include fastcgi_params; fastcgi_param SCRIPT_FILENAME $document_root/index.php; fastcgi_pass unix://var/run/php/php7.3-fpm.sock; } 
    Or even explicitly specifying the full path to the index.php file (this way the root directive can be omitted al all):
    location / { include fastcgi_params; fastcgi_param SCRIPT_FILENAME /full/path/to/index.php; fastcgi_pass unix://var/run/php/php7.3-fpm.sock; } 
added 301 characters in body
Source Link
Ivan Shatsky
  • 4k
  • 2
  • 10
  • 25
  1. Location you used will match only the requests containing $ symbol, that's definitely not what you want.
  2. Using the try_files directive you must specify at least one file/folder to check. The easiest way to specify the file that would fail the existence check is to specify dev/null.

So your location should look like

 location / { try_files /dev/null /index.php$is_args$args; include snippets/fastcgi-.conf; fastcgi_param SCRIPT_FILENAME $request_filename; fastcgi_pass unix://var/run/php/php7.3-fpm.sock; } 

or, without the try_files directive

 location / { include fastcgi.conf; fastcgi_param SCRIPT_FILENAME $document_root/index.php; fastcgi_pass unix://var/run/php/php7.3-fpm.sock; } 
  1. Location you used will match only the requests containing $ symbol, that's definitely not what you want.
  2. Using the try_files directive you must specify at least one file/folder to check. The easiest way to specify the file that would fail the existence check is to specify dev/null.

So your location should look like

 location / { try_files /dev/null /index.php$is_args$args; include snippets/fastcgi-php.conf; fastcgi_pass unix://var/run/php/php7.3-fpm.sock; } 
  1. Location you used will match only the requests containing $ symbol, that's definitely not what you want.
  2. Using the try_files directive you must specify at least one file/folder to check. The easiest way to specify the file that would fail the existence check is to specify dev/null.

So your location should look like

 location / { try_files /dev/null /index.php$is_args$args; include fastcgi.conf; fastcgi_param SCRIPT_FILENAME $request_filename; fastcgi_pass unix://var/run/php/php7.3-fpm.sock; } 

or, without the try_files directive

 location / { include fastcgi.conf; fastcgi_param SCRIPT_FILENAME $document_root/index.php; fastcgi_pass unix://var/run/php/php7.3-fpm.sock; } 
Source Link
Ivan Shatsky
  • 4k
  • 2
  • 10
  • 25
Loading