Set Up a Single Drupal Installation for Supporting Multiple Virtual Hosts

Blog Topics:

Do you hate redundancy? So do I! Rather than installing and maintaining Drupal and its modules separately for each virtual host, it's much better to install it once and link each domain to the shared copy. Of course, we still want to maintain high security. This blog entry will walk you through installing Drupal 5.1 on a SuSE 10.0 box.

Let's get right to it:

groupadd drupal
groupmod drupal -A wwwrun
groupmod drupal -A psaftp
groupmod drupal -A psaadm

Create a temporary directory for file uploads:

mkdir /tmp/.drupal
chgrp drupal /tmp/.drupal
chmod 2775 /tmp/.drupal

Owner must be root and group drupal, otherwise image uploading will fail!

Set Up the Shared Installation

Download and store the Drupal distribution to the shared directory, set up proper owner, group, access, and create a link which will always point to the current Drupal installation:

cd /srv/www
mkdir apps
cd apps
mkdir drupal
cd drupal
wget http://ftp.osuosl.org/pub/drupal/files/projects/drupal-5.x.tar.gz
tar -xzvf drupal-5.x.tar.gz
chown root.drupal -R drupal-5.x
chmod 2775 drupal-5.x/sites
ln -s drupal-5.x drupal

Create a short shell script that will set up the required links and file copies in a virtual host:

cat - >drupal_setup_in_httpdocs_dir.sh <<EOF
#!/bin/bash
#
#  Install a shared Drupal hosting
#
#  Copy this script to the httpdocs directory of the new site and run it!
#
#

ln -s  ../../../apps/drupal/drupal/includes    includes
ln -s  ../../../apps/drupal/drupal/misc        misc
ln -s  ../../../apps/drupal/drupal/modules     modules
cp -pr ../../../apps/drupal/drupal/profiles    profiles
cp -pr ../../../apps/drupal/drupal/sites       sites
ln -s  ../../../apps/drupal/drupal/themes      themes
ln -s  ../../../apps/drupal/drupal/cron.php    cron.php
ln -s  ../../../apps/drupal/drupal/index.php   index.php
ln -s  ../../../apps/drupal/drupal/install.php install.php
ln -s  ../../../apps/drupal/drupal/update.php  iupdate.php
cp -p  ../../../apps/drupal/drupal/.htaccess   .htaccess
cp -p  ../../../apps/drupal/drupal/robots.txt  robots.txt

chmod 660 sites/default/settings.php
chmod 660 .htaccess

mkdir        files
chgrp drupal files
chmod 2775   files
mkdir        files/temp
chmod g+w    files/temp
EOF
chmod 700 drupal_setup_in_httpdocs_dir.sh

The strategy here is to use the /srv/www/apps/drupal/drupal symbolic link to point to the currently installed Drupal version. This implies that all of your virtual hosts will use the same version, and that you will upgrade all of them simultaneously. It might be a good idea to build in additional flexibility and create multiple symbolic links, such as /srv/www/apps/drupal/drupal_example.com, so that you can upgrade each host separately; obviously, you'll have to adjust the drupal_setup_in_httpdocs_dir.sh script accordingly.

Set Up a VHost

For each VHost, you need to do the following:

Copy drupal_setup_in_httpdocs_dir.sh (above) to the httpdocs directory and run it to create the necessary links, directories, and files.

Follow the instructions in the Drupal INSTALL.txt file. The names of your databases and your database users are global, so if your domain is called example.com, I recommend calling your database example_com_drupal_db and your database user example_com_drupal. I also recommend to create a sites/example.com directory and to put settings.php there.

Create and activate vhost.conf to allow PHP to access the required files in a safe manner:

cat - >/srv/www/vhosts/example.com/conf/vhost.conf <<EOF
#
# allow all documents below this dir access to drupal core
#
<DirectoryMatch "^/srv/www/vhosts/example.com/httpdocs">
<IfModule sapi_apache2.c>
php_admin_flag safe_mode on
php_admin_flag safe_mode_gid on
php_admin_value open_basedir "/srv/www/apps/drupal:/srv/www/vhosts/example.com/httpdocs:/tmp"
</IfModule>
<IfModule mod_php5.c>
php_admin_flag safe_mode on
php_admin_flag safe_mode_gid on
php_admin_value open_basedir "/srv/www/apps/drupal:/srv/www/vhosts/example.com/httpdocs:/tmp"
</IfModule>
</DirectoryMatch>

#
# now limit for all directories below root that are not includes or modules
# users want other apps installed too... so no access to drupal
#
<DirectoryMatch "^(/srv/www/vhosts/example.com/httpdocs/)(?!includes/|modules/).*/">
<IfModule sapi_apache2.c>
php_admin_flag safe_mode on
php_admin_flag safe_mode_gid on
php_admin_value open_basedir "/srv/www/vhosts/example.com/httpdocs:/tmp"
</IfModule>
<IfModule mod_php5.c>
php_admin_flag safe_mode on
php_admin_flag safe_mode_gid on
php_admin_value open_basedir "/srv/www/vhosts/example.com/httpdocs:/tmp"
</IfModule>
</DirectoryMatch>
EOF

/usr/local/psa/admin/sbin/websrvmng --reconfigure-vhost --vhost-name=example.com
/etc/init.d/apache2 restart

You may also want to enable "clean URLs."

Remember to set the temporary directory to /tmp/.drupal in each Drupal installation!

Conclusion

This procedure should allow you to install Drupal in a safe and shared manner.

See also Create Subthemes to Keep Garland Customizations Separate on a Shared Installation.