8

I'm struggling with the final step in implementing a chroot on php-fpm with Apache 2.4 running on CentOS 7.

I've successfully setup and tested the php-fpm connection without the chroot. But as soon as I add the chroot directive into my conf file in /etc/php-fpm.d/file.conf, I get a "File Not Found" as many other people have experienced.

Here's my php-fpm conf file:

[site1.com]
user = user1
group = user1
listen = /var/run/php-fpm/site1.com.sock
listen.owner = user1
listen.group = user1
php_admin_value[disable_functions] = exec,passthru,shell_exec,system
php_admin_flag[allow_url_fopen] = on
php_admin_value[short_open_tag] = On
php_admin_value[doc_root] = /
php_admin_value[error_log] = /logs/php-errors
php_admin_flag[log_errors] = on
pm = ondemand
pm.max_children = 5
pm.start_servers = 2
pm.min_spare_servers = 1
pm.max_spare_servers = 3
chroot = /home/www/site1.com
chdir = /www
catch_workers_output = yes

As you can see, after I set the chroot, I changed the chdir directive so that it is relative to the PHP root. (The system path would be /home/www/site1.com/www, and that's what chdir was set to before enabling the chroot directive).

Here's my relevant http.d/site1.conf file:

<VirtualHost *:80>
        ServerAdmin [email protected]
        ServerName site1.com
        ServerAlias www.site1.com
        DocumentRoot /home/www/site1.com/www
        <Directory "/home/www/site1.com/www">
                Options Includes FollowSymLinks
                DirectoryIndex index.php
                AllowOverride All
                Order allow,deny
                Allow from all
        </Directory>
ErrorLog /home/www/site1.com/logs/errors
CustomLog /home/www/site1.com/logs/access_log common
        <FilesMatch "\.php$">
                SetHandler "proxy:unix:///var/run/php-fpm/site1.com.sock|fcgi://site1.com"
        </FilesMatch>
LogLevel trace3
</VirtualHost>

I've turned up the LogLevel in my httpd.d/site.conf file, and here's some of that interesting output:

  [Mon Nov 02 10:42:52.665284 2015] [proxy:trace2] [pid 14286] proxy_util.c(2007): [client 74.221.189.99:16486] *: found reverse proxy worker for unix:///var/run/php-fpm/site1.com.sock|fcgi://site1.com/home/www/site1.com/www/index.php
    [Mon Nov 02 10:42:52.665292 2015] [proxy:trace2] [pid 14286] proxy_util.c(2041): [client 74.221.189.99:16486] *: rewrite of url due to UDS(/var/run/php-fpm/site1.com.sock): fcgi://site1.com/home/www/site1.com/www/index.php (proxy:fcgi://site1.com/home/www/site1.com/www/index.php)
    [Mon Nov 02 10:42:52.665295 2015] [proxy:debug] [pid 14286] mod_proxy.c(1117): [client 74.221.189.99:16486] AH01143: Running scheme unix handler (attempt 0)
    [Mon Nov 02 10:42:52.665300 2015] [proxy_ajp:debug] [pid 14286] mod_proxy_ajp.c(713): [client 74.221.189.99:16486] AH00894: declining URL fcgi://site1.com/home/www/site1.com/www/index.php
    [Mon Nov 02 10:42:52.665304 2015] [proxy_fcgi:debug] [pid 14286] mod_proxy_fcgi.c(948): [client 74.221.189.99:16486] AH01076: url: fcgi://site1.com/home/www/site1.com/www/index.php proxyname: (null) proxyport: 0
    [Mon Nov 02 10:42:52.665307 2015] [proxy_fcgi:debug] [pid 14286] mod_proxy_fcgi.c(955): [client 74.221.189.99:16486] AH01078: serving URL fcgi://site1.com/home/www/site1.com/www/index.php
    [Mon Nov 02 10:42:52.665311 2015] [proxy:debug] [pid 14286] proxy_util.c(2200): AH00942: FCGI: has acquired connection for (*)
    [Mon Nov 02 10:42:52.665316 2015] [proxy:debug] [pid 14286] proxy_util.c(2253): [client 74.221.189.99:16486] AH00944: connecting fcgi://site1.com/home/www/site1.com/www/index.php to site1.com:8000
    [Mon Nov 02 10:42:52.665320 2015] [proxy:debug] [pid 14286] proxy_util.c(2286): [client 74.221.189.99:16486] AH02545: fcgi: has determined UDS as /var/run/php-fpm/site1.com.sock
    [Mon Nov 02 10:42:52.665420 2015] [proxy:debug] [pid 14286] proxy_util.c(2419): [client 74.221.189.99:16486] AH00947: connected /home/www/site1.com/www/index.php to httpd-UDS:0
    [Mon Nov 02 10:42:52.668135 2015] [proxy_fcgi:error] [pid 14286] [client 74.221.189.99:16486] AH01071: Got error 'Primary script unknown\n'
    [Mon Nov 02 10:42:52.668179 2015] [proxy_fcgi:trace1] [pid 14286] util_script.c(599): [client 74.221.189.99:16486] Status line from script 'index.php': 404 Not Found
    [Mon Nov 02 10:42:52.668237 2015] [http:trace3] [pid 14286] http_filters.c(992): [client 74.221.189.99:16486] Response sent with status 404
    [Mon Nov 02 10:42:52.668284 2015] [proxy:debug] [pid 14286] proxy_util.c(2215): AH00943: FCGI: has released connection for (*)

Nothing is showing up in the php error log file.

So, after all this,

  • Why am I still getting a "File not found" error message?
  • Better yet, how do I fix it, or at the very least, how do I better troubleshoot my issue?

5 Answers 5

6

This is resolved. There were two issues with my above code.

Issue #1 - Only Apache 2.4.10 and above can support sockets

The default version of Apache that comes in the base CentOS repositories (Apache 2.4.6) only support TCP ports. The above code is therefore incorrect, and the listen directive in the php-fpm config file needed to be changed to something like this:

listen = 127.0.0.1:9001

I also made the appropriate change in my http.d conf file, but in addition, I also switched to using the ProxyPassMatch directive instead of using the FilesMatch directive. So my code then became:

ProxyPassMatch "^/(.*\.php)$" "fcgi://127.0.0.1:9001/site1.com"

Note that this code is still wrong... see below

Moving on...

Issue #2 - Relevant Paths

The path in the ProxyPassMatch directive (or, in the case of my older code using the FilesMatch directive) inside my http.d conf file becomes relative to the chroot. It is not relative to the www document root (if different).

So my code in my http.d conf file became:

ProxyPassMatch "^/(.*\.php)$" "fcgi://127.0.0.1:9001/www/$1"

And voila! I have a php-fpm chroot.

3
  • 1
    I've asked a similar question, and if you have any input on that I would be interested - thanks!
    – trey-jones
    Apr 5, 2016 at 22:11
  • What version of Apache are you using? The /$1 at the end causes 503 errors in my setup which uses version 2.4.25. If you remove this bit, it works.
    – jcharaoui
    Apr 13, 2018 at 1:57
  • Point #1 is not true, or at least isn't now. Unix sockets work fine with the stock Apache 2.4.6 packages, Red Hat apparently back ported the support.
    – bodgit
    Aug 31, 2018 at 7:45
4

php-fpm has a bug with chroot and path.

for example with index.php in www

chroot = /home/www/site1.com
chdir = /www

with this config php-fpm write this path :

/home/www/site1.com/home/www/site1.com/www

one solution is to create a symbolic link in shell :

cd /home/www/site1.com
mkdir -p home/www
cd home/www
ln -s /home/www/site1.com site1.com

but it is not clean.

https://bugs.php.net/bug.php?id=55322

https://bugs.php.net/bug.php?id=62279

2
  • I've actually read that elsewhere - you're absolutely right. Unfortunately, this particular answer didn't fix my particular need. To be fair, I didn't specify I had already tried that. Anyway, my issue is fixed, and I'll be following up shortly with my own detailed answer on a couple of different errors in my above code.
    – David W
    Nov 9, 2015 at 20:26
  • Although this answer points to a useful solution, I consider it important to note that the php-fpm behaviour in question is not a bug but actually done that way by design. The php-fpm worker process is started inside the chroot which makes it restrained to that environment and this is desired. Jul 19, 2018 at 4:08
4

Some people might receive this error because of 2 things.

  • Wrong relative paths in php.ini
    In case you specify open_basedir, doc_root, user_dir, session.save_path, upload_tmp_dir (and others) in your PHP-FPM.conf, then these paths must be relative to chroot.
    For example:

chroot = /var/www
php_admin_value[doc_root] = /htdocs
;All paths must be relative to chroot since after chrooting PHP does not know about the absolute path

  • cgi.fix_pathinfo = 1 in php.ini
    TL;DR just change it to 0.
    For some reasons this value affects your PHP-FPM even though this parameter is ment to be for CGI only.
    You should read more about this parameter since it may break other things too, more here
1

Do you have SElinux enabled? getenforce should be able to tell you this. If that's the case, setenforce 0 would disable it and then you'd need to edit /etc/sysconfig/selinux and set SELINUX to disabled so it's persistent after rebooting.

1
  • Nope, SElinux is not enabled.
    – David W
    Nov 2, 2015 at 12:48
0

After a day of strugling with php-fpm and chroot, I managed to fix PHP-FPM with chroot, under Apache based on this answer

  1. Added these values in /etc/php/8.2/fpm/pool.d/my-pool-conf.conf

    chroot = /home/my-user-home-dir
    chdir = /public_html
    php_admin_value[doc_root] = /public_html
    php_admin_value[open_base_dir] = /public_html:/tmp
    php_admin_value[doc_root] = /public_html
    
  2. In /etc/php/8.2/fpm/php.ini I changed this:

    cgi.fix_pathinfo=0
    

I found several answers which advised to change the Apache directive SetHandler with ProxyPassMatch, but at the moment it does not make a difference, both seem to be working

You must log in to answer this question.

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