Apache: "Service Not Available" after setting up php-fpm chroot
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>
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')