WHM/Cpanel per-user php.ini under Apache 2.x and suPHP

Print Friendly, PDF & Email

OK, time for another delve into the underbelly of WHM, and a short lesson in how to achieve something which seems so poorly covered (although Cpanel, to their credit have started to explain things a little more clearly) elsewhere, especially for folks who may not be uber-geeks (I make no such claim!).

Very often we want to tighten php.ini up to make our servers as secure as possible – but then there is always going to be a few accounts where for various reasons, you want to bend the rules. Well, now you can set up your WHM/Cpanel server with a central php.ni and yet allow selected users the ability to use a customised php.ini, managed and controlled by YOU!

About the mighty PHP.INI

First of all, a little about php.ini – this file contains all of the directives that determine how PHP (not necessarily Apache) will behave. You can see your active php.ini settings by using the phpinfo() function from within a php script.

Now, php.ini contains some pretty powerful stuff – not really the kind of stuff you want to allow any Tom, Dick, or Harry to alter (for example you can override the maximum file upload size). PHP, despite being reasonably secure these days, still has exploits so in a shared environment (where you are hosting multiple customers on a single logical server) it’s wise to be strict.

The default (as of today) in WHM, means that in order to customise PHP’s behaviour, all you need do is put a php.ini file in the same directory as your php script (you have to put a php.ini file in every directory where you want the custom changes to have effect, it doesn’t have recursive effects, like htaccess can do.) This is a bad idea for the reasons already explained.

Plus, most people who do this don’t prevent the php.ini file from being read by hackers, who can determine the structure of your code more easily. Also, it would appear many people don’t realise that php.ini files aren’t merged, but rather the local php.ini file you place on your website totally overwrites the core/default one, being that any settings carefully crafted by the administrator are totally scrubbed back to php’s defaults.

Caveats

OK, first things first. You should really be running PHP with the suPHP mod enabled. If you are running PHP in DSO mode this won’t work. This can be checked in  Main >> Service Configuration >> Apache Configuration >> PHP and SuExec Configuration. I make NO WARRANTY that the following will just work – always carry out thorough testing to ensure your environment is safe before releasing it to production status! I have to say that, as there’s always someone out there who doesn’t want to take responsibility for themselves!

The simple answer – a fixed PHP.INI for all

OK, let’s get the sledge hammer out. You run the server and you want to law down the law. It’s pretty simple, on the current version of Cpanel, just SSH into a shell and go to

/opt/suphp/etc/suphp.conf

Somewhere towards the bottom you will find a section that looks like this:

[phprc_paths]
;Uncommenting these will force all requests to that handler to use the php.ini
;in the specified directory regardless of suPHP_ConfigPath settings.
;application/x-httpd-php=/usr/local/lib/
;application/x-httpd-php4=/usr/local/php4/lib/
;application/x-httpd-php5=/usr/local/lib/

Just remove the comment markers (semi-colons) from the bottom three lines. SIMPLES! This will force every page in every account to use your central php.ini files. Anything in .htaccess files or httpd.conf that tried to redirect to a different php.ini will be ignored. To make this take effect, you will need to restart Apache.

PHP.INI on a per user basis

OK, this one is a little more complicated. We could, of course, start hacking away at the httpd.conf file putting in global php.ini settings at the top, and then entering individual php.ini directives for each virtual hosting account. This would be pretty pointless because a.) it’s hard work, and b.) it would get overwritten the minute you changed any hosting settings in WHM.

Instead, we will leverage the preferential include system that is part of Apache 2.x

The first job is to set a global php.ini file to be used by default.

We can do this by placing a *.conf file in /usr/local/apache/conf/userdata/ for example:

/usr/local/apache/conf/userdata/suphp.conf

It should be empty or not exist at all on a standard install of WHM, so we just need to add:

<IfModule mod_suphp.c>
   suPHP_ConfigPath /usr/local/lib/
</IfModule>

OK, so now we have put that there, we have effectively achieved the same thing as before – forcing everyone to use the core php.ini file. However, this won’t take immediate effect unless we run:

/scripts/ensure_vhost_includes --all-users

It also won’t take effect for NEW accounts or subdomains which we add. In order for that to happen we must also edit (if using apache 2.2):

/usr/local/cpanel/etc/httptemplates/apache2_2/default

around line 24 to read:

<IfModule mod_suphp.c>

   suPHP_UserGroup %user% %user%

   suPHP_ConfigPath /usr/local/lib/

</IfModule>

note added 18 March 2010: You should monitor this file. As it will get overwritten when /scripts/upcp runs overnight (if automatic updates are selected) or whenever you perform a manual update. If you use CSF firewall, you can add the directory to the watch-for-changes list. Annoying, but no way to make it truly permanent until Cpanel add improvements.

Now for the fun bit – adding a custom php.ini file for just a single user. OK. First we have to take a copy of our original php.ini file (in /usr/local/lib/) and place it somewhere safe, and out of reach of our users. So

mkdir -p /etc/phpconf/username
cp /usr/local/lib/php.ini /etc/phpconf/username/

Feel free to customise your new /etc/phpconf/username/php.ini file. Remember this file is not merged with the core php.ini – it entirely replaces it.

Then we have to make sure that the virtual host picks up the new php.ini file. Again we can use Apache 2.x’s include system.

mkdir -p /usr/local/apache/conf/userdata/std/2/username/mainaccountdomain.com

The std bit could also say ‘ssl’ if you wanted also to enjoy the custom php.ini on an ssl virtual host. Once you have created the directory, then place a file in it called suphp.conf, and edit the file as follows:

<IfModule mod_suphp.c>
suPHP_ConfigPath /etc/phpconf/username/
</IfModule>

That’s it! All we need to do now, is rebuild the httpd.conf file and restart Apache. The eaiest way to do all this is:

/scripts/ensure_vhost_includes --all-users
or if you have zillions of accounts:
/scripts/ensure_vhost_includes --user=username

Go and try it out. Any php.ini files placed in your users’ accounts should now be ignored, but you can still provide tweaks for valued customers by giving them what they want (within reason of course!) 🙂 Enjoy.

SPECIAL NOTES

Many thanks to Mike who commented below… after communicating with Mike by email and after much gnashing of teeth, this article was amended to the current edit above.

The only problem remaining is that modifying the cpanel templates put’s us back in the situation we were in originally in that the next Cpanel update could very well overwrite any modified templates. So we really need a final script to run on a cron to tell us if the core Cpanel templates have changed and email us to remind us to edit the mod back in again!

Tags: , ,

11 Responses to “WHM/Cpanel per-user php.ini under Apache 2.x and suPHP”