Using independent PHP for different services

Ideally, you want to run each PHP-based service within the boundaries of it's own PHP instance. The advantages of such a solution would be that each PHP instance can run as the service user which guarantee service isolation and more protection in data access.

Gentoo does not provide a simple way to do so for more than two instances (see here) but even in that case the solution relies in one service running with Apache and one service running with PHP-FPM, which does not scale to more than two services.

The solution i am proposing here requires to duplicate your PHP configuration files and init scripts, but albeit requiring a bit more maintenance in the long run, it provides a much more scalable approach.

The approach

The basic idea is to leverage the Gentoo PHP-FPM init script that already support running more than one instance but with different PHP versions.

The idea is to symlink the /etc/init.d/php-fpm script to /etc/init.d/php-fpm-service1:

ln -s /etc/init.d/php-fpm /etc/init.d/php-fpm-service1

the script will assume you want to run PHP-FPM with a version of PHP called service1, so the only thing you need to do is to copy the configuration files under /etc/php and doing a minor editing to the original script. You are basically “creating” a specific version of PHP which does not exist.

So, copy (don't link, as you will need to edit that per service) the configs:

cp -a /etc/php/fpm-php8.2 /etc/php/fpm-service1
rm /etc/php/fpm-service1/php.ini

Choose your preferred (or required) PHP version for service1. Your PHP FPM will still use the php.ini from the original setup folder, so delete the copied one or you will get confused!

Then, you need the following edit to your /etc/init.d/php-fpm script because, by default, your service1 will be used as it was a PHP version but there is no PHP version numbered service1, so you need to separate the two things. The edit is simple, you need to split the PHP_SLOT variable to a PHP_SLOT_EXEC one that you can change. This approach will alow the original way to still work while supporting also our new way. Find the row:

command="/usr/lib64/${PHP_SLOT}/bin/php-fpm"

and replace it with the following lines:

if [ -e "/etc/php/fpm-${PHP_SLOT}/php-version" ]; then
        PHP_SLOT_EXEC="$(cat /etc/php/fpm-${PHP_SLOT}/php-version)"
else
        PHP_SLOT_EXEC="${PHP_SLOT}"
fi
command="/usr/lib64/${PHP_SLOT_EXEC}/bin/php-fpm"

PHP configuration for specific service

Ok, it's time to adapt the PHP configuration for our service. You need to configure three things:

  • Setup the desired PHP version manually
  • Change username and group under which PHP will run
  • change the port used by PHP FPM
  • Replace the include path for the confiiguration

First of all, create the file /etc/php/fpm-service1/php-version with the required PHP version in it:

php-version
php8.2

Then edit the file /etc/php/fpm-service1/php-fpm.conf and fix the following path:

include=/etc/php/fpm-service1/fpm.d/*.conf

Last, edit the file /etc/php/fpm-service1/fpm.d/www.conf to match the following lines (also replace the port with an available one!):

user = service1
group = service1
listen = 127.0.0.1:9000

Remeber the port number as you will need to use it in NGINX configuration.

and then you can start it and add to boot:

rc-update add php-fpm-service1 default
/etc/init.d/php-fpm-service1 start

done!

NGINX configuration

See The Reverse Proxy concept for more datails on NGINX.

A generic NGINX configuration for PHP-FPM is the following:

        location ~ /.*\.php$ {
                try_files $uri =404;
                fastcgi_split_path_info ^(.+\.php)(/.+)$;
                include fastcgi_params;
                fastcgi_param SCRIPT_FILENAME $request_filename;
                fastcgi_pass 127.0.0.1:9000;
        }

where you need to adapt the port (9000) and the location, of course.

Updating php

When you perform emerge updates PHP will be updated sooner or later.

You can, and should, migrate to the newer version when possible. In this case all you need to do it to update the value into php-version and probably also update the specific php.ini values.