Tuesday, March 28, 2017

Setting up your multi-user hosting VPS server (Apache): A secure way to run several Joomla/Worpress/Drupal sites

by / Sunday, 13 October 2013 / Published in Linux, BSD, Unix

Keywords: Apache MPM ITK PHP MySQL VPS CentOS

In this article I'm going to describe a typical configuration for a private web server. I assume you use CentOS 6 as your operating system, in other *nix distributions some paths and commands may vary. However, the idea remains intact:)

Most servers require PHP as scripting language, and MySQL for databases

If you run multiple websites, it is always better to run them as different users. Even if a hacker gets access to one of your sites, there's a high chance that the others will remain intact.

To begin with, first install necessary software.

Setting up web server

For security purproses, we should use Apache MPM-ITK, that allows running PHP scripts as different users for different vhosts. Unfortutately, it is not available in default repositories, so, to install it, first add an alternative repository to yum configuration:

rpm -Uvh http://mirror.webtatic.com/yum/centos/5/latest.rpm

Then install Apache MPM-ITK:

yum install --enablerepo=webtatic httpd-itk

Then edit /etc/sysconfig/httpd and add the following line:


Check /etc/httpd/conf.d/itk.conf and make it look like

<IfModule itk.c>
StartServers 2
MinSpareServers 2
MaxSpareServers 10
ServerLimit 256
MaxClients 256
MaxRequestsPerChild 4000

In the next step we are going to install PHP and MySQL as the most required tools. As well we'll add some PHP extensions, such as bcmath, APC accelerator, GD graphics library. You can also install Ruby, if necessary:

yum install php php-pecl-apc php-mysql php-cli php-gd php-bcmath php-mbstring php-intl mysql mysql-server 

Then edit /etc/httpd/conf.d/php.conf - insert the following lines:

<IfModule itk.c> LoadModule php5_module modules/libphp5.so</IfModule>

After that, create user home directory template. I'm going to use user's home subdirectory as site's www root. We assing a separate user to each website, so this will be consistent.

[[email protected] ~]# cd /etc/skel/
[[email protected] skel]# mkdir logs
[[email protected] skel]# mkdir tmp
[[email protected] skel]# mkdir www

Create a separate directory containing configuration files for VirtualHosts

[[email protected] skel]# mkdir /etc/httpd/conf.vhosts

Then add to the end of /etc/httpd/conf/httpd.conf the following lines:

# Load config files from the config directory "/etc/httpd/conf.vhosts".
Include conf.vhosts/*.conf

Allow MySQL server to start automatically when the system boots:

[[email protected] ~]# chkconfig mysqld on

Start the server and set up password (answer Y to all questions):

[[email protected] ~]# service mysqld start# /usr/bin/mysql_secure_installation

Do not forget to allow incoming connections in firewall. In CentOS, run

[[email protected] ~]# system-config-firewall-tui

You will need to open port 80 (and 443, if you plan to use SSL).

Adding a new website / user

As long as we use 'one site - one user' principle, we should create a new user:

[[email protected] ~]# adduser hosting01

I assume that example.org is your domain in this example. You will also need to set up A record for yor domain, so it will point to your server's IP address. (You can do this at your domain registrar/nameserver)

In the next step we'll add separate VirtualHost to Apache. Create a new file named /etc/httpd/conf.vhosts/hosting01.conf and make it look like:

<VirtualHost *>
	ServerAdmin This email address is being protected from spambots. You need JavaScript enabled to view it.
	<IfModule mpm_itk_module>
		AssignUserId hosting01 hosting01
	DocumentRoot /home/hosting01/www/
	ServerName example.org
	ErrorLog /home/hosting01/logs/error_log
	CustomLog /home/hosting01/logs/access_log "combined"
	LogLevel info 
	DirectoryIndex index.php index.html 
	php_admin_value upload_tmp_dir /home/hosting01/tmp
	php_value session.save_path /home/hosting01/tmp
	php_admin_value open_basedir /home/hosting01/tmp:/home/hosting01/www

Add new MySQL user/database, if necessary:

# mysql -u root -p
CREATE DATABASE hosting01;CREATE USER 'hosting01'@'localhost' IDENTIFIED BY 'password';GRANT ALL PRIVILEGES ON hosting01.* TO 'hosting01'@'localhost';

Then restart Apache:

# apachectl restart

If there are no errors, navigate to http://example.org (I assume that example.org is your domain) and you will see contents of your /home/hosting01/www/index.php or index.html.

PHP scripts will run with privileges of hosting01 user, and will be able to work with files in /home/hosting01/www and /home/hosting01/tmp directories only. You may also set /home/hosting01/tmp as temporary directory in your CMS.

This is much more secure way to run several blog/sites on yor VPS: if a hacker attempts to upload malicious file, it will not be accessible from the web. If he manages to hack your website, he will be only able to change it's contents, not neighbouring site's.

If something goes wrong, first check file permissions:

chown -R hosting01 /home/hosting01/www/*
Read 1168 times Last modified on Saturday, 14 March 2015 17:36

Do you like this? Please share!

Simon Tushev

Simon is IT professional with interests in web design, electronics, photography and astronomy. He writes about PHP, Yii, Joomla!, Arduino and several other topics.


Here I publish articles related to my areas of interest, my brief notes that may save some time to others, as well as some of my works.

This site is a work in progress. I will add more sections in the future, such as

  • More photos to photogallery
  • More Joomla!-related articles
  • ...



New Posts

Using dynamic GeoIP module with nginx (CentOS)

nginx introduced dynamic module support in v. 1.9.11. This brief article provides step-by-step procedure...

13-04-2016 in Linux, BSD, Unix


Visual difference between pseudo and true random data

This is is "random" image generated using PHP rand() function: And this is an image...

20-11-2015 in Blog


Best EEPROM practices

(this article is a work in progress). My own advice will be added later...   Having...

12-10-2015 in Arduino

Scroll to top

We use cookies, just to track visits to our website, we store no personal details Privacy policy