6

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.

3
  • Another option is to put your non-production sites on an entirely different server. Nov 25, 2016 at 17:56
  • 1
    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, 2016 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, 2016 at 13:22

1 Answer 1

10
+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.

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

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .