3

I noticed the following behavior or PHP-FPM:

Take a look at these two Nginx configs:

server {
    listen         80;
    server_name    example.com;
    location / {
        fastcgi_pass 127.0.0.1:9000;
        fastcgi_param SCRIPT_FILENAME  /srv/www/i.php;
        fastcgi_param PHP_VALUE "display_errors=1";
        include fastcgi_params;
    }
}
server { 
    listen         80;
    server_name    example.net;
    location / {
        fastcgi_pass 127.0.0.1:9000;
        fastcgi_param SCRIPT_FILENAME  /srv/www/i.php;
        include fastcgi_params;
    }
}

and /srv/www/i.php file:

<?php phpinfo();

As you can see the only difference is fastcgi_param PHP_VALUE "display_errors=1";.

Now if you kill all FPM workers, and open example.net first, you will see display_errors is Off as expected. And at example.com you will see display_errors is On.

But if you visit example.net again and this request is proceeded by the same worker, you will get display_errors as On.

All FPM workers are working in the same pool.

Question: how to make example.net always work with default settings?

Possible solutions:

  • Define PHP_VALUE with the desired settings in example.net config as well.
  • Seems to be a "right" solution - create separate pools of workers for each site.

But we have a lot of websites on our server, and both solutions mean a lot of routine work to set up. I was wondering if there is an easier way.

Update:

display_errors setting in my example was chosen just to demonstrate the problem. The same situation takes place with any php.ini setting. As per comments, it is a bad idea to mix production and development sites on a single server.

  • Another option is to put your non-production sites on an entirely different server. – Michael Hampton Nov 25 '16 at 17:56
  • Side note: As of PHP 5.2.4 display_error expects a string value and should be set to either stdout (default) or stderr. – Daniel Nov 30 '16 at 13:18
  • @Daniel I will keep it in mind, thanks) This directive was chosen for example. In the real life I faced this problem when I set error_log=/some/file.txt for the only site and noticed that there were errors of other sites there as well – Oleg Nov 30 '16 at 13:22
7
+50

The reason this happens is most likely that "PHP settings passed with php_value or php_flag will overwrite their previous value", as described PHP-FPM documentation.

I assume that in your PHP configuration display_errors is disabled. Then you visit the .net-page, in which your phpinfo() confirms that it is disabled.

Then you visit the .com-page and Nginx passes display_errors=1 to your PHP-FPM worker in that same pool. That overwrites the previous value of 0 with the new value 1. You can confirm that with phpinfo().

Now the PHP-FPM pool settings is set to display_errors=1.

When you visit the .net-page again, phpinfo() indeed confirms that display_errors=1 because it was overwritten when Nginx passed the value of 1 to the same pool that now handles another of your websites.

The solution is either to move development to another server, as suggested in the comments. Or to create a dedicated PHP-FPM pool for your site, which is the least you should do.

Bonus:

And please don't do this in your Nginx configuration: fastcgi_param PHP_VALUE "display_errors=1";

That ought to be in the php configuration file, preferably in the site's own fpm pool configuration.

But we have a lot of websites on our server, and both solutions mean a lot of routine work to set up. I was wondering if there is an easier way.

You can use the per pool prefix for a quick fix. In any case, putting multiple sites on a single worker pool is a bad idea because I only need to get one of your sites to execute a malicious php script of mine to compromise ALL other sites that use the same worker, without any effort.

  • Thanks! It looks like I have to revise my approach of using PHP-FPM – Oleg Dec 5 '16 at 8:08

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.