Do I need to make any changes to my Nginx Config?

Created on 13 July 2024, 8 months ago
Updated 20 September 2024, 5 months ago

Problem/Motivation

At https://www.drupal.org/node/3223395#s-statistics →
I see

# Allow access to Statistics module's custom front controller.
# Copy and adapt this rule to directly execute PHP files in contributed or
# custom modules or to run another PHP application in the same directory.
RewriteCond %{REQUEST_URI} !/core/modules/statistics/statistics\.php$

Remaining tasks

I use Nginx. Do I need to make any changes to my standard config?

My Nginx config:

location ~ \.well-known{allow all;}# Allow "Well-Known URIs"
if ( $uri ~ "^/\.well-known/.*\.(php|jsp|py|js|css|lua|ts|go|zip|tar\.gz|rar|7z|sql|bak)$" ) {return 403;}

if ($host = carignitions.com) {return 301 https://www.$host$request_uri;}

#https://www.nginx.com/resources/wiki/start/topics/recipes/drupal/
location = /12e3o302=op302cache/ {allow all;log_not_found off;access_log off;}
location = /ads.txt {allow all; log_not_found off; access_log off;}
location = /robots.txt {allow all; log_not_found off; access_log off;}
location = /favicon.ico {allow all; expires max; log_not_found off; access_log off;}
# Very rarely should these ever be accessed outside of your lan
location ~* \.(txt|log)$ { allow 192.168.0.0/16; deny all; }

location ~ \..*/.*\.php$ {
    return 403;
}

location ~ ^/sites/.*/private/ {
	return 403;
}

# Block access to scripts in site files directory
location ~ ^/sites/[^/]+/files/.*\.php$ {
	deny all;
}

# Allow "Well-Known URIs" as per RFC 5785
location ~* ^/.well-known/ {
    allow all;
}

# Block access to "hidden" files and directories whose names begin with a
# period. This includes directories used by version control systems such
# as Subversion or Git to store control files.
location ~ (^|/)\. {
    return 403;
}

location / {
    # try_files $uri @rewrite; # For Drupal <= 6
    try_files $uri /index.php?$query_string; # For Drupal >= 7
}

location @rewrite {
   rewrite ^ /index.php;
}

# Don't allow direct access to PHP files in the vendor directory.
location ~ /vendor/.*\.php$ {
	deny all;
	return 404;
}

# Protect files and directories from prying eyes.
location ~* \.(engine|inc|install|make|module|profile|po|sh|.*sql|theme|twig|tpl(\.php)?|xtmpl|yml)(~|\.sw[op]|\.bak|\.orig|\.save)?$|composer\.(lock|json)$|web\.config$|^(\.(?!well-known).*|Entries.*|Repository|Root|Tag|Template)$|^#.*#$|\.php(~|\.sw[op]|\.bak|\.orig|\.save)$ {
	deny all;
	return 404;
}
# In Drupal 8, we must also match new paths where the '.php' appears in
# the middle, such as update.php/selection.
location ~ '\.php$|^/update.php' {
  fastcgi_split_path_info ^(.+?\.php)(|/.*)$;
  # Ensure the php file exists. Mitigates CVE-2019-11043
  try_files $fastcgi_script_name =404;
  # Security note: If you're running a version of PHP older than the
  # latest 5.3, you should have "cgi.fix_pathinfo = 0;" in php.ini.
  # See http://serverfault.com/q/627903/94922 for details.
  include fastcgi_params;
  # Block httpoxy attacks. See https://httpoxy.org/.
  fastcgi_param HTTP_PROXY "";
  fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
  fastcgi_param PATH_INFO $fastcgi_path_info;
  fastcgi_param QUERY_STRING $query_string;
  fastcgi_intercept_errors on;
	# PHP 8 socket location.
  #fastcgi_pass unix:/var/run/php/php8.3-fpm.sock;
  fastcgi_pass  unix:/tmp/php-cgi-83.sock;
}
location ~* \.(js|css|webp|png|jpg|jpeg|gif|ico|svg|eot|ttf|woff|woff2)$ {
	try_files $uri @rewrite;
}
# Fighting with Styles? This little gem is amazing.
location ~ ^/sites/.*/files/styles/ {
	try_files $uri @rewrite;
}
# Handle private files through Drupal. Private file's path can come
# with a language prefix.
location ~ ^(/[a-z\-]+)?/system/files/ { # For Drupal >= 7
	try_files $uri /index.php?$query_string;
}

# Enforce clean URLs
# Removes index.php from urls like www.example.com/index.php/my-page --> www.example.com/my-page
# Could be done with 301 (was 307) for permanent or other redirect codes.
if ($request_uri ~* "^(.*/)index\.php(.*)") {
	return 301 $1$2;
}
💬 Support request
Status

Postponed: needs info

Version

1.0

Component

Code

Created by

🇷🇴Romania idflorin

Live updates comments and jobs are added and updated live.
Sign in to follow issues

Comments & Activities

  • Issue created by @idflorin
  • 🇫🇷France fgm Paris, France

    Hi @Idflorin : I'm not ignoring you but Nginx is not (yet ?) an officially supported server for Drupal, although it is widely used. As mentioned on https://www.drupal.org/docs/getting-started/system-requirements/web-serv... → some security features are only provided for Apache, which is why I never use it even for huge sites, so cannot help you myself.

    You might want to track ✨ Provide documentation/default server block for Nginx server. Needs work which aims at providing a reference Nginx configuration, and possibly ask people discussing in that issue.

  • 🇷🇴Romania idflorin

    @fgm
    My websites depend heavily on statistics and statistics_counter ( https://www.drupal.org/project/statistics_counter → ).
    So, Until statistics_counter doesn't get updated I can't test it.

    Anyway, thank you for your time.

  • 🇫🇷France fgm Paris, France

    IF you look at the project page of Statistics Counter, it says "No further development No longer developed by its maintainers.", so it looks like you might want to reconsider your use of that module, or apply to take over maintainership: it's a very small, very simple module, so it might be something both doable and useful for you to do. Would that be of interest ?

  • 🇷🇴Romania idflorin

    @fgm
    Unfortunately, my developer knowledge it's not so advanced.
    I can clone a small module like https://www.drupal.org/project/node_title_validation/issues/3191677 ✨ Create a sister module Node Body Validator Active ,
    I can apply/read a patch and some other things but to take over maintainership it's a little too much for me.
    Last time when I needed to use the statistics_counter d.8 version I think, I searched and asked until a great guy forwarded me a compatible d.8 zip file.

  • Status changed to Postponed: needs info 6 months ago
  • 🇫🇷France fgm Paris, France

    OK, so I took a look at your nginx configuration and, although I'm not familiar with it, it looks like it might work.

    What happens when you specifically navigate to https://(yoursite)/core/modules/statistics/statistics.php if you are using Drupal 10.3 or earlier with core statistics, or https://(yoursite)/web/modules/contrib/statistics/statistics.php if you are using Drupal 10.4 or later with the 1.0.0 version of Statistics, installed in (docroot)/web/modules/contrib/statistics.

    Specifically, use curl or httpie to perform that command and provide the headers and body of the response (truncated if it's a html page).

  • 🇷🇴Romania idflorin

    on Drupal core 10.3.5 and a regular node refresh.
    I get

    2024/09/16 20:44:02 [error] 105309#0: *144624 FastCGI sent in stderr: "PHP message: PHP Warning:  require_once(autoload.php): Failed to open stream: No such file or directory in /www/wwwroot/idbip.com/web/modules/statistics/statistics.php on line 25; PHP message: PHP Fatal error:  Uncaught Error: Failed opening required 'autoload.php' (include_path='.:') in /www/wwwroot/idbip.com/web/modules/statistics/statistics.php:25
    Stack trace:
    #0 {main}
      thrown in /www/wwwroot/idbip.com/web/modules/statistics/statistics.php on line 25" while reading response header from upstream, client: 84.17.46.53, server: idbip.com, request: "POST /modules/statistics/statistics.php HTTP/1.1", upstream: "fastcgi://unix:/tmp/php-cgi-83.sock:", host: "www.idbip.com", referrer: "https://www.idbip.com/peugeot/peugeot-2008-review-design-features-performance-and-price"
    

    If I access https://www.idbip.com/web/modules/statistics/statistics.php I get 404 Not Found,
    After I change the config with

    # Protect files and directories from prying eyes.
    location ~* \.(engine|inc|install|make|module|profile|po|sh|.*sql|theme|twig|tpl(\.php)?|xtmpl|yml)(~|\.sw[op]|\.bak|\.orig|\.save)?$|composer\.(lock|json)$|web\.config$|^(\.(?!well-known).*|Entries.*|Repository|Root|Tag|Template|/modules/statistics/statistics.php)$|^#.*#$|\.php(~|\.sw[op]|\.bak|\.orig|\.save)$ {
    	deny all;
    	return 404;
    }
    

    the 404 Not Found is gone, the error log is still there

    2024/09/16 20:53:59 [error] 107395#0: *15 FastCGI sent in stderr: "PHP message: PHP Warning:  require_once(autoload.php): Failed to open stream: No such file or directory in /www/wwwroot/idbip.com/web/modules/statistics/statistics.php on line 25; PHP message: PHP Fatal error:  Uncaught Error: Failed opening required 'autoload.php' (include_path='.:') in /www/wwwroot/idbip.com/web/modules/statistics/statistics.php:25
    Stack trace:
    #0 {main}
      thrown in /www/wwwroot/idbip.com/web/modules/statistics/statistics.php on line 25" while reading response header from upstream, client: 84.17.46.53, server: idbip.com, request: "POST /modules/statistics/statistics.php HTTP/1.1", upstream: "fastcgi://unix:/tmp/php-cgi-83.sock:", host: "www.idbip.com", referrer: "https://www.idbip.com/peugeot/peugeot-2008-review-design-features-performance-and-price"
    2024/09/16 20:54:01 [error] 107395#0: *15 FastCGI sent in stderr: "PHP message: PHP Warning:  require_once(autoload.php): Failed to open stream: No such file or directory in /www/wwwroot/idbip.com/web/modules/statistics/statistics.php on line 25; PHP message: PHP Fatal error:  Uncaught Error: Failed opening required 'autoload.php' (include_path='.:') in /www/wwwroot/idbip.com/web/modules/statistics/statistics.php:25
    Stack trace:
    #0 {main}
      thrown in /www/wwwroot/idbip.com/web/modules/statistics/statistics.php on line 25" while reading response header from upstream, client: 84.17.46.53, server: idbip.com, request: "POST /modules/statistics/statistics.php HTTP/1.1", upstream: "fastcgi://unix:/tmp/php-cgi-83.sock:", host: "www.idbip.com", referrer: "https://www.idbip.com/peugeot/peugeot-2008-review-design-features-performance-and-price"
    

    and the day counter is the same.

  • 🇫🇷France fgm Paris, France

    OK. so it looks like that install is missing the autoloader files. Your server is configured to use PHP-FPM on a UNIX socket. Looking at the original page, apparently https://www.idbip.com/peugeot/peugeot-2008-review-design-features-perfor... I see that you put the statistics.php URL behind a CDN, which will you don't want to do, to prevent caching since the goal is to count hits.

    But anyway, the CDN says the upstream response has length 0, which is caused by the error you mention in #7. Anyway, at that URLs, the page tries to load statistics.php from https://www.idbip.com/core/modules/statistics/statistics.php, meaning you are still using core Statistics, not the contrib version, which would load from https://www.idbip.com/modules/contrib/statistics/statistics.php

    Regardless, this errors telles you that you need to ensure your Composer deployment is complete, meaning that there should be a /www/wwwroot/idbip.com/vendor/autoload.php file. Can you see it ? Or do you have /www/wwwroot/idbip.com/core/vendor/autoload.php instead ?

  • 🇷🇴Romania idflorin

    I've made a rollback and updated with composer again.
    My autoload.php is in /www/wwwroot/idbip.com/vendor/autoload.php
    My website runs as index.php is in /www/wwwroot/idbip.com/web
    I have multiple websites running like this ok. I manage my websites with composer, mainly.
    My folder structure looks like this :
    https://prnt.sc/ULVcerDR_R8G
    https://prnt.sc/QVWWz91mHNLO
    I also use https://www.drupal.org/project/statistics_counter → which works fine.
    https://prnt.sc/xLcIaWjDoDHT
    after a refresh
    https://prnt.sc/5aR3WmEDWTw_
    See that statistics don't work and /statistics_counter works.
    My Drupal Version 10.3.5. My status report looks fine (no statistics warnings)

    https://prnt.sc/5fyGC-JFVfvX

    but I still get

    2024/09/18 21:26:37 [error] 315051#0: *1168 FastCGI sent in stderr: "PHP message: PHP Warning:  require_once(autoload.php): Failed to open stream: No such file or directory in /www/wwwroot/idbip.com/web/modules/statistics/statistics.php on line 25; PHP message: PHP Fatal error:  Uncaught Error: Failed opening required 'autoload.php' (include_path='.:') in /www/wwwroot/idbip.com/web/modules/statistics/statistics.php:25
    Stack trace:
    #0 {main}
      thrown in /www/wwwroot/idbip.com/web/modules/statistics/statistics.php on line 25" while reading response header from upstream, client: 143.244.56.51, server: idbip.com, request: "POST /modules/statistics/statistics.php HTTP/1.1", upstream: "fastcgi://unix:/tmp/php-cgi-83.sock:", host: "www.idbip.com", referrer: "https://www.idbip.com/peugeot/peugeot-2008-review-design-features-performance-and-price"
    2024/09/18 21:26:43 [error] 315051#0: *1240 FastCGI sent in stderr: "PHP message: PHP Warning:  require_once(autoload.php): Failed to open stream: No such file or directory in /www/wwwroot/idbip.com/web/modules/statistics/statistics.php on line 25; PHP message: PHP Fatal error:  Uncaught Error: Failed opening required 'autoload.php' (include_path='.:') in /www/wwwroot/idbip.com/web/modules/statistics/statistics.php:25
    Stack trace:
    #0 {main}
      thrown in /www/wwwroot/idbip.com/web/modules/statistics/statistics.php on line 25" while reading response header from upstream, client: 143.244.56.51, server: idbip.com, request: "POST /modules/statistics/statistics.php HTTP/1.1", upstream: "fastcgi://unix:/tmp/php-cgi-83.sock:", host: "www.idbip.com", referrer: "https://www.idbip.com/peugeot/peugeot-2008-review-design-features-performance-and-price"
    
  • 🇫🇷France fgm Paris, France

    OK, now I see the problem in your latest paste. The error message says require_once(autoload.php): Failed to open stream: No such file or directory in /www/wwwroot/idbip.com/web/modules/statistics/statistics.php on line 25; PHP message: PHP Fatal error: Uncaught Error: Failed opening required 'autoload.php' <em>(include_path='.:')</em> in /www/wwwroot/idbip.com/web/modules/statistics/statistics.php:25 (emphasis added)

    This means PHP is only looking for files to include in the current directory, no other one. The statistics.php file starts by a chdir('../../..'). But your module is located in /www/wwwroot/idbip.com/web/modules/statistics/, not /www/wwwroot/idbip.com/web/modules/contrib/statistics/ as it normally should be. So that chdir changes the current directory to /www/wwwroot/idbip.com/, and the next line $autoloader = require_once 'autoload.php'; looks for autoload.php in that directory, although it is actually in /www/wwwroot/idbip.com/www instead.

    I see from your screenshots that you placed all your contrib modules under /www/wwwroot/idbip.com/web/modules/, but they should be under /www/wwwroot/idbip.com/web/modules/contrib/ instead. In most cases, that doesn't matter, but Statistics is using a custom front controller which needs to locate the Composer autoloader itself instead of relying on core settings (for speed reasons, if you want to know).

    So the correct fix is to

    • go to the project root cd /www/wwwroot/idbip.com
    • uninstall at least Statistics so that core does not keep track of where it is drush pmu statistics
    • create the missing directory mkdir web/modules/contrib
    • move statistics there mv web/modules/statistics web/modules/contrib
    • re-enable Statistics drush en statistics

    That should fix your problem.

    More generally, all your contrib modules should be in that web/modules/contrib directory, but it may be complicated to move them and most modules do not really care anyway. Just keep it in mind for the next ones you install. If you install with the standard Drupal composer install process → , your composer.json will include the necessary installer-paths configuration so that any module installed using composer require drupal/somemodule will be properly located, as well as any contrib theme or library.

  • 🇷🇴Romania idflorin

    Thanks.
    I've got it.
    Attempt 1.
    Changing statistics.php
    at line 23 from

     chdir('../../..');
    

    TO

    chdir('../..');
    

    It solves all problems. It works, but I don't recommend Attempt 1.
    Attempt 2.
    Move all drupal contrib modules from /modules/modulename to /modules/contrib/modulename
    Change the composer.json line from
    "module/{$name}": ["type:drupal-module"],
    TO
    "modules/contrib/{$name}": ["type:drupal-module"],

    Add "$settings['rebuild_access'] = TRUE"; to settings.php
    @mainly done by https://www.drupal.org/forum/support/post-installation/2022-04-01/solved... → - with-composer#comment-14466564

    Go to mysite.com/core/rebuild.php
    Restart PHP 8.3
    Go to mysite.com/update.php

    Remove "$settings['rebuild_access'] = TRUE"; from settings.php

    And it works.

    *Restart PHP 8.3 might be too much but I did it anyway.

  • 🇫🇷France fgm Paris, France

    Cool. It seems that solved your issue ? If so, set the issue status to "Fixed" (not "Closed").

Production build 0.71.5 2024