Community Documentation

Creating multiple sites on the same domain without using symlinks with Apache

Last updated November 19, 2010. Created by ajessup on January 28, 2009.
Edited by Frits1980, LeeHunter, chx. Log in to edit this page.

We were searching for a way to support multi-site installations (subsites) on the same domain, that is, to have:

www.example.com/
www.example.com/sitea
www.example.com/siteb
www.example.com/sitec
etc.

with different content/themes/modules etc. but on the same Drupal 5.x installation. The normal way to do this is to create the appropriate

/sites/www.example.com.sitea/settings.php
etc...

files and then to create recursive symlinks for each subsite, eg.

ln -s drupal/. drupal/sitea
etc..

The problem with this approach is that for multiple sites, it permits for recursive urls (http://www.example.com/sitea/siteb/sitea/siteb/content) which can play havoc with Google PageRank. For us a secondary problem was that is caused our IDE (eclipse) to loose it frequently, presumably since it wasn't able to distinguish the symlinks from real directories and so was recursively parsing the entire drupal directory until it eventually ran out of memory. And finally symlinks don't often seem to translate well in our versioning system, which means we needed to create a script to build the symlinks across different dev environments.

What we wanted to do was achieve multisites on the same domain, but without using recursive symlinks. Instead our solution was to use an Apache RewriteRule for each site. eg.

RewriteRule ^sitea(.*)$ $1 [PT]

This sits neatly in the .htaccess file (before the final 'RewriteRule ^(.*)$ index.php?q=$1 [L,QSA,PT]'), and can be versioned easily.

The problem with this approach is that Drupal uses the SCRIPT_NAME environment variable (normally /index.php) from the server to figure out which site config file to use. With symlinks the server is 'tricked' into thinking it's actually accessing index.php at a different location (/sitea/index.php) than it actually is, so the SCRIPT_NAME is valid and the correct site file is found.

RewriteRules don't affect SCRIPT_NAME though. In fact we weren't able to find any way to reliably modify SCRIPT_NAME just through Apache, so instead we patched bootstrap.inc to look at REQUEST_URI instead of SCRIPT_NAME (see attached patch file). This seems to work quite well, assuming you've set $base_url correctly for each site in it's settings.php file. (Editor's note: mod_rewrite has an 'env|E=VAR:VAL' (set environment variable) flag, add that to [L,QSA,PT] as appropriate)

This solution is easilly versionable, requires no symlinks and doesn't lead to recursive URLS.

Before you use this be aware of some known caveats of this approach:

  • We've tried it this morning, it's hardly a tried and tested approach. There may well be issues we haven't uncovered.
  • There are doubtless more elegant ways of doing this, and we'd love to hear from anyone who has done so. Solutions from the community seems rather sparse on this issue right now though, hence this post.
  • This will only work on servers that set REQUEST_URI, as far as I know only Apache actually does this
  • You'll need to make sure all links in your subsites add the appropriate $base_path to them.
AttachmentSize
bootstrap.inc_.patch1.3 KB

Comments

I do this with aliases in

I do this with aliases in Apache

Alias /sitea "/var/www/html/drupal"
Alias /siteb "/var/www/html/drupal"
etc...

And the rewrite has this:

RewriteCond %{THE_REQUEST} /sitea/
RewriteRule ^(.*)$ /sitea/?q=$1 [L,QSA]

RewriteCond %{THE_REQUEST} /
RewriteRule ^(.*)$ index?q=$1 [L,QSA]

The key here is using THE_REQUEST which contains the original request before going through the alias. Doing this, I haven't needed any symlinks, and don't have to modify any drupal files. Adding another subsite just requires adding another alias line and rewrite.

I can't solve the question with your suggestion.

Hi, davidhernandez,

I've tried your suggestion.
And try below:
RewriteCond %{THE_REQUEST} /sitea/
RewriteRule ^(.*)$ /siatea/?q=$1 [L,QSA]
RewriteCond %{THE_REQUEST} /siteb/
RewriteRule ^(.*)$ /siteb/?q=$1 [L,QSA]

Or
RewriteCond %{THE_REQUEST} ^/sitea/*
RewriteRule ^/sitea(.*)$ /siatea/index.php?q=$1 [L,QSA]
RewriteCond %{THE_REQUEST} ^/siteb/*
RewriteRule ^/siteb(.*)$ /siteb/index.php?q=$1 [L,QSA]

Alias added.
But bad luck.
Can you give me any more information?

I suspect that approach will

I suspect that approach will work - and is more elegant in that it doesn't require a patch to core, but has the disadvantage (for us, at least) in that you need to hard code the path to drupal in your .htaccess file.

Page status

Needs updating

Log in to edit this page

About this page

Drupal version
Drupal 5.x

Installation guide

Drupal’s online documentation is © 2000-2012 by the individual contributors and can be used in accordance with the Creative Commons License, Attribution-ShareAlike 2.0. PHP code is distributed under the GNU General Public License.