Recently for a fun project, I decided to set up an automated shared web host to test my coding abilities. I decided to go with a simple name, similar to one of my other domains. I ended up with Chris Host It. Sure its cheesy and not very professional, but this is just a test project after all. The problem was the back end I went with didn’t secure PHP as well as I wanted it to by default, so I had to fix that up. So here is a quick guide on securing PHP when using Virtualmin.
But before I jump ahead to that part, Let me explain why I went with the Back End I did. With so many options like CPanel and ISPConfig, it can be hard to pick the best for your configuration. Well in my case, I ended up going with Virtualmin. My reasons are as follows:
- Its Free!
- It works perfectly on Debian with little configuration.
- It is similar to Webmin, which is what I use to manage some of my servers.
- There is a active community support forum, and paid support if you want a subscription.
- Plugin support for new features and items.
- Easy to use API.
So after setting up my server and getting it how I wanted, I decided to load up a PHP Shell script in a virtual host. Im glad I did, because I realized everything by default was enabled! No directory jailing, functions like exec() and passthru() were enabled, and this was a huge red flag to me! If I didn’t fix this, any virtual site could browse around other users websites and worse, my servers file system! Thankfully Virtualmin creates separate php.ini files for every virtual host, so I can easily jail every user to there own home folders.
So, lets get started with how I did this. The first thing you need is a server with Debian and Virtualmin installed (I will put up a Vitualmin install post later, with screenshots). After this is done, you should lock down your default php.ini that is copied to every virtual host that gets set up.
So, after some research I found the Virtualmin template php.ini to be at
So I just did some tweaks, and changed the following:
open_basedir = /home/
disable_functions = show_source, system, shell_exec, passthru, exec, popen, proc_open
expose_php = Off
max_execution_time = 30
memory_limit = 32M
Here is why I changed what I did:
- Open_Basedir = Tells PHP this is the ONLY folder it can run from and access. It locks down that users PHP to that folder. Great way to jail people to a folder.
- Disable_Functions = Turn off PHP Functions so people can’t call them. I turned off everything I thought was appropriate. Google each function to see its use, but most are only used for evil. Worst case scenario you can later modify a users php.ini to re-enable the features as needed.
- Expose_PHP = Just to prevent PHP from showing its existence, more preventive then anything.
- max_execution_time = This is here to limit long running scripts that can take up CPU time and Memory.
- memory_limit = Similar to above, except this just sets a physical max. Another way to conserve resources.
Now you will have Virtual Hosts that are a bit more secured, but still not fully Jailed to there homes. Time to fix this with a little scripting, and thanks to Virtualmin, its very easy! When ever Virtualmin calls a script to run it has the ability to automatically define variables for the script, so creating this script took me about 5 minutes. Here is what I came up with:
# we use this to jail PHP right in the users folder, so security stuff
if [ "$VIRTUALSERVER_ACTION" = "CREATE_DOMAIN" ]; then
sed -i "s|open_basedir = .*|open_basedir = $USER_HOME|g" $USER_HOME/etc/php5/php.ini
So what this script does is once a new virtual site is created, it takes the username of the account, and then jails there PHP to that folder locking down that users PHP to there folder only. A perfect, easy way to keep things secured and locked up tight. I uploaded this script to my site so you can easily set up your server the same way if you please.
So lets create a file, I personally put it in /usr/share/virtualmin-scripts/ In this example we name it php_opendir_jail.sh, but you can put it and name it whatever you want.
root:~# mkdir /usr/share/virtualmin-scripts/
root:~# cd /usr/share/virtualmin-scripts/
root:# wget http://servernetworktech.com/uploads/scripts/php_opendir_jail.sh
root:# chmod +x php_opendir_jail.sh
Now that the script is there, time to edit Virtualmin. Go to, and login in to your virtualmin panel as root then go to the following menu:
System Settings > Virtualmin Configuration > Actions upon server and user creation
From here, enter the script and its location into “Command to run after making changes to a server”
Click Save, and that’s it! From now on every host added will be jailed to there home folder, and PHP will have those dangerous functions locked out. You can now sleep soundly again!