Lately, I’ve noticed more and more shared web hosts making the switch to running PHP under suExec. The benefits of this are:
- PHP scripts run as the owning user
- No more file system permission juggling
- Scripts are generally sandboxed to the owner’s home directory
Unfortunately, this poses a problem for any custom PHP configuration changes as the usual
php_value properties are no longer supported. The recommended method of setting a custom configuration is to place a
php.ini file under each directory where required.
This method works fine for any properties set in the custom
php.ini file however there appears to be one devastating omission. Server configuration properties do not cascade into the custom file. What this means is that for any property not set in your custom file, PHP will revert to the PHP default.
For example, say your host has enabled PDO (as any decent host should). The instant you introduce a custom
php.ini file, PDO will be lost. Sure, you could just include the relevant
extension properties but consider this example (from my host)
extension_dir = "/usr/local/lib/php/extensions/no-debug-non-zts-20060613"
That property is awfully specific and your custom entry wouldn’t fare too well in the event of an upgrade.
In a perfect world, the host would have compiled PHP with the
--with-config-file-scan-dir=/some/dir option that allows an environmentally settable directory to be scanned for additional config files. Unfortunately, this is rarely the case.
My solution is a little hacky and hardly perfect but it certainly gets the job done for me.
1. Create your custom.ini file with the options you want. Mine is
/home/user/etc/php.d/custom.ini and looks like this
register_globals = Off magic_quotes_gpc = Off
Do not name this file php.ini.
2. Locate your host’s
php.ini file. This information is available from
phpinfo(). In the below examples it is
3. Add a cron job to create a full
php.ini file in a location of your choosing (
/home/user/etc/php.d) that is the concatenation of the server
php.ini file and your
custom.ini file. The below example is set to run hourly with any errors displayed on stdout which should be mailed to the crontab owner.
0 * * * * /usr/bin/test -f /usr/local/lib/php.ini && /bin/cat /usr/local/lib/php.ini /home/user/etc/php.d/custom.ini > /home/user/etc/php.d/php.ini || echo '/usr/local/lib/php.ini NOT FOUND'
The reason for the cron job is to keep your full, custom
php.ini file in sync with any server changes. The job will also inform you in the unlikely event that the host
php.ini file is moved.
If you’ve got shell access, you can create this file immediately by running
cat /usr/local/lib/php.ini /home/user/etc/php.d/custom.ini > /home/user/etc/php.d/php.ini
otherwise, wait for the hour to come around in which case your cron job should have done the work for you.
4. Add the following to your web application’s
SetEnv PHPRC /home/user/etc/php.d
PHPRC environment variable informs any PHP scripts of the location of the preferred