There have been a number of forum and mailing list discussions about
how to run multiple Drupal sites from a common codebase, and/or how to
install Drupal in a subdirectory rather than in the document root.
Here are a couple: http://drupal.org/node/22269
http://drupal.org/node/10843
A lot of people seem really frustrated trying to get it to work. But
it can be done! My personal interest is in setting up Drupal on a
dedicated server in a manner that makes it easy for multiple vhosts to
share a common codebase, while still allowing site-by-site
customization if necessary. With that in mind, here's a blueprint for
several different ways of installing Drupal, and the mod_rewrite
.htaccess RewriteRule implications for each.
Different places that Drupal can be installed and accessed, and how
the rewrite rules need to be changed for each case:
1) Installed in root, accessed as root
The usual current installation method. Drop the files off in the
top of htdocs, and let it happen. Direct access to existing files
and directories works (minus some path info problems), but name
conflicts are a real possibility. Done as a symlink, allows access
to common code base for multiple sites, but this makes it hard for
these sites to have outside files and scripts. The .htaccess file
works out of the box. Personally, though, I find this approach
really messy and think it would be a good idea for Drupal to move
away from it.
2) Installed in subdirectory, accessed as subdirectory
This is straightforward, and might be useful if you have a single
site but want to make it easy to switch between different versions
of Drupal. Put drupal in htdocs/drupal (or make a symlink) and
then have "http://host/drupal" set as the base in
"site/host/settings.php". The drupal .htaccess file stays
unchanged: since no Alias statement is involved you do not need to
change the RewriteBase statement.
The symlink version of this is easy for common codebase, but all
Drupal links need to include string '/drupal'. Not terrible, but
makes migrating to such a system difficult if one has an existing
web-indexed or outside-linked system.
3) Installed in subdirectory, but accessed as root.
Starts to get more interesting. Put drupal in a subdirectory (or
more likely make a symlink), then add a .htaccess file in the root
directory that redirects non-existing URL's to '/drupal'. Easy to
upgrade, allows migration from existing installation.
------------------------------------
RewriteEngine on
# Redirect root page to drupal home (if desired)
# NOTE: without trailing slash, external redirect to /drupal will
# be used and it will show up in browser. With slash, hidden.
RewriteRule ^$ drupal/ [L]
# Rewrite non-file/directory URL's to be under drupal
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ drupal/$1 [L]
-------------------------------------
The problem with this approach for a shared hosting setup is that it
requires symlinks that the user probably does not have the
permissions to create. But if you have control of the whole box,
this might not be a bad approach.
4) Installed globally (no symlink), accessed as subdirectory.
or
5) Installed globally (no symlink), accessed as root.
Finally we reach the case of having multiple sites with separate
document roots running from a common Drupal codebase. These two are
very similar. The rewrite rules in the common drupal .htaccess are
the same for both. Presuming a common Drupal codebase installed in
/var/www/shared/drupal and 'Alias /shared/ /var/www/shared/':
(in common drupal/.htaccess)
------------------------------------------
RewriteEngine on
RewriteBase /shared/drupal
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ index.php?q=$1 [L,QSA]
-------------------------------------------
Or if you have Drupal aliased directly ('Alias /drupal/
/var/www/drupal/'), set 'RewriteBase /drupal/'.
The rewrite rules in the root of the site will be slightly different:
(in site root .htaccess for Drupal access at root)
----------------------------------------------
RewriteEngine on
RewriteRule ^$ /shared/drupal/ [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ /shared/drupal/$1 [L]
-----------------------------------------------
(in site root .htaccess for Drupal access as subdir /drupal)
-----------------------------------------------
RewriteEngine on
RewriteRule ^drupal/(.*)$ /shared/drupal/$1 [L]
-----------------------------------------------
If you want access to look like a subdirectory, you'll want to set
$base_url in 'settings.php' to be equal to whatever your locally
aliased subdirectory is (http://host/drupal in this case). Possibly
usefully, these two rulesets can be combined if necessary to allow for
legacy links if you move from one style to another.
Stray notes:
The checks for -f and -d uses full path information when checking: so
if you have a subdir node but are looking for /node/1, -d is false.
But a search for /node/index.html will match and will be served (if
that file indeed exists). But this might cause a problem when using
other programs that require path_info.
Seems like symlinks are matched by check for "-f file". For example,
if 'file.html' is a symlink to 'real.html', "-f file.html" will be
true, contrary to what the manual says about 'regular files'.
Note that you will need to have "AllowOverride FileInfo" (or greater)
turned of for some directory above where your symlink or alias exists.
Otherwise, the symlink will be followed and the root page will be
accessible, but the RewriteRule's in the .htaccess file in the symlink
will be ignored so the rewrite rules won't work. If you are getting
'page not found' errors, you might put an intentional error in your
.htaccess file just to check that it is actualy being read.
RewriteBase is really hard to understand. When per-directory
(.htaccess) rewrite rules are used, the per-directory portion of the
URL is stripped off before the rule is applied, and then put back
after the rule. When RewriteBase is used, the per-directory portion
is still stripped, but then RewriteBase is put back afterwards.
When does one need this? Whenever one is is running out of an
Alias'ed directory, where the file path no longer matches the URL
path. It's not needed when in a subdirectory (or symlinked
subdirectory), only when dealing with aliases. In this case, one
needs to set RewriteBase to be equal to the current subdirectory but
treating the alias as root. For example, if you have "Alias /shared/
/var/www/shared', and have Drupal installed under
'/var/www/shared/drupal', the .htaccess in that directory would need
to have 'RewriteBase /shared/drupal' to work correctly.
Moving the site-specific configuration files to live in the
virtual-hosts directory instead of in the common Drupal source base is
a separate matter. It should be easy to solve with some judicious
symlinks, though, or with a very simple patch to change where the
site-specific settings.php files are searched for.
Apologies if there are errors in this. I've tested a bit, but only a
bit. As I move beyond the initial testing phase, I'm sure I'll come up with
some modifications. Probably I've missed some edge cases, or worse giant gaps.
If you see any, please add appropriate comments.
Hope this helps,
Nathan Kurz
nate@verse.com
Comments
Helpful Page - this topic is needs to be in the Handbook
In the process of upgrading from a root level 4.6 to a 4.7 based sites, I wanted to move the drupal code to a subdirectory.
This is on a shared host at pair.com.
I tried your item 3 above and found that to get clean URL's to work I needed to add index.php to your suggestion.
Only later, when my browser cache had expired, did I see that I was no longer getting the theme stylesheets and graphics.
This required using some of your notes from 3, 4 and 5.
In the top level .htaccess, I use
and add a .htaccess file to the subdir_drupal directory as follows:
Perhaps there is a more simple appraoch, but this does work for me at the moment. I may have to revisit this as I move the document root of some sites into subdirectories.
As an additional note, I also have other sites and applications (perl based) on this server. While I've seen some .htaccess recommendations to explicitly exclude such directories from the matching rules, at the moment, I add a .htaccess files to each of these directories
This allows one to browse the other directories, but does send 404's back to the drupal system.
Rewriting semi-working, what am I missing?
Hi,
Thank you very much for this helpful article. I am trying to simplify my future upgrading needs as well as making my life easier maintenance-wise by following this information. I have to admit that it is a steep learning curve. But, here is my setup and my question:
I have a .htaccess file configured as gregoryo describes above. However, what I am is a main page - www.chaoselbows.com/ - is equal to www.chaoselbows.com/d51/. d51 is the drupal directory where everything drupal lives. If I click on the link (a standard home "nodes" page) the uri is actually in the form of http://www.chaoselbows.com/d51/node/1603. taking out the /d51 part also works, but the default includes it. how do I get rid of this extra subdirectory showing here?
and in the subdirectory,
are the "relevant" portions of the .htaccess files. actually, the one in the /d51 subdir is the "default" folder with rewritebase changed.
can you offer any thoughts as to why or how to get rid of the uri showing the subdirectory?
Thank you!
Cannot Enable Clean URLs for Drupal Multisite
(1) I have drupal common codebase at /var/www/share/drupal/drupal-4.6.6/
(2) I have drupal common .htaccess as such:
(3) I have vhost.conf file for adobeinspections.com as such:
Yet, I cannot enable clean urls for the site. (It appears your host is not configured correctly for Clean URLs. Please check for ModRewrite support with your administrator.)
Any help is appreciated. Thanks in advance.
Regards,
-Steve
Additional resource for .htaccess rewrite rules & multi-site
I've posted a helpful tip on my web site:
http://exodusdev.com/multi-site-compatible-apache-rewrite-rules
The default .htaccess examples for rewrite rules were causing problems for me, too, so I found a solution and discuss it on the above-referenced page.
If someone wants to try this on their site and add their experience here (and perhaps write up a more detailed, easier-to-understand explanation) I'd be grateful.
Michael Curry - http://exodusdev.com