1

I'm running Debian Jessie with Apache 2.4.10. I have been through the "File not found" problem, and ended up referencing this question. The only difference between my setup and his is that I would REALLY (for various reasons) prefer to use UDS instead of TCP sockets, and using the ProxyPassMatch solution isn't quite doing the trick, though I'm not sure why.

Here is my line in the config:

ProxyPassMatch "^/(.*\.php)$" "unix:/var/run/myappname.sock|fcgi://localhost/webroot/$1"

And here is the debug output:

AH00944: connecting fcgi://localhost/webroot/index.php to localhost:8000, referer: http://myapp.com
AH00947: connected /webroot/index.php to localhost:8000, referer: http://myapp.com
(111)Connection refused: AH00957: FCGI: attempt to connect to 127.0.0.1:8000 (*) failed

If I try to use an address other than eg. localhost I get a DNS failure, however when using SetHandler, I am able to use an arbitrary string as the address successfully. I don't understand the difference. Here is a working example (without chroot) using SetHandler and FilesMatch instead of ProxyPassMatch.

<FilesMatch "\.php$">
    SetHandler "proxy:unix:/var/run/myappname.sock|fcgi://myappname/"
</FilesMatch>
0

2 Answers 2

1

Fix

There is a better solution than building a symlink tree inside your chroot jail.

Instead of this:

ProxyPassMatch "^/(.*\.php)$" "unix:/var/run/myappname.sock|fcgi://localhost/webroot/$1"

Use this:

ProxyPassMatch "^/(.*\.php)$" "unix:/var/run/myappname.sock|fcgi://localhost/webroot"

In short, remove the /$1 at the end, it's not needed. This might be required for another version of Apache, but for 2.4.25 at least, that bit will cause the 503 errors you describe.

ProxyPassMatch vs FilesMatch

The difference between FilesMatch and ProxyPassMatch is that the latter passes a relative script path to the fcgi process, while the former sends the full path as seen by Apache, which includes the path up to where the chroot is located.

Debugging

Using the strace command was helpful in debugging this problem. When the PHP worker process attempts to read a file, the trace will show you the full path of the file it's trying to read.

Using FilesMatch:

lstat("/srv/jail/var/www/index.php", 0x7ffeb3069390) = -1 ENOENT (No such file or directory

Since the PHP worker process is jailed inside /srv/jail, the command fails.

Using ProxyPassMatch:

lstat("/var/www/index.php") {st_mode=S_IFREG|0644, st_size=96, ...}) = 0

The process succeeds in reading the file.

You can launch strace in the following manner and it will output a trace of php-fpm and its child/worker processes:

strace -f $(pgrep -f php-fpm | sed 's/\([0-9]*\)/\-p \1/g')
1
  • Thank you for this answer. One might also point out that all the include and require_once calls have to be set up propperly! I had some occasions where it was not propperly set to __DIR__ but was $_SERVER['DOCUMENT_ROOT'], which worked outside the chroot but not inside!
    – Daywalker
    Oct 31, 2019 at 21:55
0

I tried a lot of different ways to make this work, mostly trying to avoid falling back to this known method. In the end, it's the only way that succeeded for me.

cd /full/path/to/chrootdir
mkdir -p full/path/to
cd full/path/to
# only as many dots as your setup requires
ln -s ../../.. chrootdir

Using SetHandler works best for me:

<FilesMatch ".*\.php$">
    SetHandler "proxy:unix:/var/run/php-fpm-myapp.sock|fcgi://myapp"
</FilesMatch>

In the end, that's not too bad, and the payoff is worth it to me.

Explanation: mod_proxy_fcgi passes the full path of the php script. php-fpm therefore receives the instruction to interpret the file at /full/path/to/chrootdir/script.php, but it can't find it because it's in a chroot jail. The relative symlink links the full path back to the root of the chroot jail.

You must log in to answer this question.

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