PHP-FPM with chroot: "File not found"

The web page shows: “File not found” and the error log shows:
AH01071: Got error ‘Primary script unknown’

pool config:


[mydomain.se]
user = www-data
group = www-data
listen = /var/run/php/php8.2-fpm-mydomain.se.sock
listen.owner = www-data
listen.group = www-data
php_admin_flag[allow_url_fopen] = off
pm = dynamic
pm.max_children = 5
pm.start_servers = 2
pm.min_spare_servers = 1
pm.max_spare_servers = 3
chroot = /rootfolder

vhost:

<VirtualHost *:80>

    DocumentRoot "/rootfolder"
    ServerName mydomain.se
    ServerAlias www.mydomain.se

    <FilesMatch ".php$"> 
        SetHandler "proxy:unix:/var/run/php/php8.2-fpm-mydomain.se.sock|fcgi://localhost/"          
    </FilesMatch>

</VirtualHost>

It works without chroot, but I want to be able to use chroot in the config.

I guess when I include chroot the “listen” path becomes incorrect, but I dont know.

Can someone please help?

When you use chroot, you’re essentially changing the root directory of the PHP-FPM process to the specified directory. Therefore, all paths within that process are relative to that new root.

Try these steps to correct the issue:

  1. Update the listen directive:
    Your PHP-FPM pool is currently set to listen on a Unix socket located at /var/run/php/php8.2-fpm-mydomain.se.sock. When you use chroot, this path changes in the context of the PHP-FPM process. Therefore, you must change this to a location within your chrooted environment.

    Update your pool config to something like:

    listen = /rootfolder/tmp/php8.2-fpm-mydomain.se.sock
    

    Make sure the /rootfolder/tmp/ directory exists and is writable by the PHP-FPM process.

  2. Update Apache vhost:
    You need to change the SetHandler directive to point to the new socket location relative to the system’s root (not the chrooted root):

    <FilesMatch ".php$"> 
        SetHandler "proxy:unix:/rootfolder/tmp/php8.2-fpm-mydomain.se.sock|fcgi://localhost/"          
    </FilesMatch>
    
  3. Ensure all required libraries are within the chrooted environment:
    If your PHP scripts rely on external libraries or files, you need to ensure they are available within the chroot environment. This can include system libraries, font files for image processing, or any other resources. You might need to copy them into the corresponding directories inside /rootfolder.

  4. DocumentRoot & SCRIPT_FILENAME:
    Since you’re using chroot, you need to be aware that the PHP process will interpret paths differently. For instance, if you request a file /index.php, Apache might see it as /rootfolder/index.php, but the chrooted PHP-FPM process will see it as /index.php.

    Ensure that SCRIPT_FILENAME passed to PHP-FPM reflects the path as seen by the PHP-FPM process, not the absolute path on the system.

  5. Restart Services:
    After making these changes, make sure you restart both Apache and PHP-FPM to ensure they pick up the changes.

If you continue to face issues, check both the Apache error logs and PHP-FPM logs for clues.

Good luck.

Note: Using chroot can be a bit tricky, especially when it comes to managing dependencies and paths. Make sure you test thoroughly to ensure that all features of your application work as expected. :sunny:

1 Like

Super thanks, your post was golden.

It was resolved after I changed the script_filename as you mentioned.

I did it with the following code. Is there a more appropriate way to do it?

ProxyFCGISetEnvIf "true" SCRIPT_FILENAME "/%{reqenv:SCRIPT_NAME}"

I’m glad to hear the solution helped!

The approach you’ve used with ProxyFCGISetEnvIf to set SCRIPT_FILENAME is certainly one way to adjust the SCRIPT_FILENAME variable when using chrooted PHP-FPM with Apache’s mod_proxy_fcgi. This method allows you to derive the script filename from the requested script’s name, stripping the chrooted path.

However, keep in mind that using ProxyFCGISetEnvIf "true" means that this condition will always evaluate to true, so the SCRIPT_FILENAME will always be set this way for every request. This is fine if it’s the intended behavior for your setup.

If you want to ensure this directive only applies to .php files (to mimic the behavior of the FilesMatch block you used earlier), you can be more specific:

<FilesMatch "\.php$">
    ProxyFCGISetEnvIf "true" SCRIPT_FILENAME "/%{reqenv:SCRIPT_NAME}"
</FilesMatch>

But if you find that your current configuration works for your use case and doesn’t introduce any unexpected behaviors or bugs, it’s generally okay to keep it.

Good luck

1 Like

This topic was automatically closed 91 days after the last reply. New replies are no longer allowed.