Php – Apache + PHP-FPM + chroot results “File not found.” error

apache-2.2chrootPHPphp-fpm

I want to set chroot to the DocumentRoot using PHP-FPM pools' chroot attribute. With the settings below, whatever I do I get only a "File not found." error:

/etc/php5/fpm/pool.d/example.conf

[example]
user = example
group = example
listen = /var/run/php_fpm_example.sock
pm = dynamic
pm.max_children = 5
pm.start_servers = 2
pm.min_spare_servers = 1
pm.max_spare_servers = 3
chroot = /opt/jail/example/home/example
php_admin_value[open_basedir]=/opt/jail/example/home/example

/etc/apache2/sites-enabled/example

<VirtualHost *:80>
ServerName example.domain.name
ServerAlias www.example.domain.name
DocumentRoot /opt/jail/example/home/example
<Directory /opt/jail/example/home/example>
AllowOverride All
Order Allow,Deny
Allow from all
</Directory>
<IfModule mod_fastcgi.c>
<FilesMatch \.php$>
SetHandler php-script
</FilesMatch>
Action php-script /php5-fpm-handler
Alias /php5-fpm-handler /vhost_example
FastCGIExternalServer /vhost_example -socket /var/run/php_fpm_example.sock
</IfModule>
</VirtualHost>

So the website itself is located in /opt/jail/example/home/example. You may find it strange, but doesn't really matter, it is caused by jailkit.

Thanks for your help.

Best Answer

PHP is running inside the chroot jail. So once you set this:

chroot = /opt/jail/example/home/example

Then the path /opt/jail/example/home/example becomes the path / for PHP. Because of that this is non-sensical:

php_admin_value[open_basedir]=/opt/jail/example/home/example

as PHP no longer has access to /opt/jail/example.... because it's outside of the root path.

You haven't posted it but you also need to make a change to the fastcgi_param config file, where you set the SCRIPT_FILENAME parameter which probably looks like this:

fastcgi_param  SCRIPT_FILENAME    $document_root$fastcgi_script_name;

which needs to be changed to something like:

fastcgi_param  SCRIPT_FILENAME    webroot/$fastcgi_script_name;

where if you combine the values of chroot + webroot + $fastcgi_script_name you get the absolute path of the file on the disk. Because PHP is running in the chroot you don't need to include it in the path.

btw It's a better practice to have the chroot to be set to one level above the webroot, so that your application can write to log files that are within the chroot, but not in the webroot, so that there's no way for them to be accidentally downloaded by a user.

So your directories would be:

/opt/jail/example/home/          <-- chroot
/opt/jail/example/home/example   <-- Read only directory is exposed as webroot (or document root).
/opt/jail/example/home/var/log   <-- Writeable directory that holds log files.