Drupal's multi-site hosting capability is built in with any installation. This is great news for users who run numerous web sites from a single hosting account. A single Drupal installation can be used to run multiple domains, which makes it much easier to manage and maintain the code base. Even if you are dealing with only one domain, the multi-site capability may be valuable by providing the ability to run a separate domain or sub-domain for a development version.

This page describes the set-up of the /sites directory for multi-sites.

With version 5.x, the intended location for all non-core elements of a Drupal installation is in a separate /sites directory inside the Drupal installation.

Directory Contents
/drupal/sites/all

(used by all sites)
/modules
/themes
/drupal/sites/default

(used when there is no /sites/example.com directory)
/files
settings.php
/drupal/sites/example1.com    /files
/modules
/themes
/tmp
settings.php
/drupal/sites/example2.com    /files
/modules
/themes
/tmp
settings.php

The intended best practice configuration is to create a /sites/example.com directory for each domain. It should contain a site-specific settings.php file and /files directory. Configure Drupal site settings to specify 'File System Directory' of 'sites/example.com/files' instead of the default 'files'. It's possible to do this with an existing web site, but moving file uploads around can cause a lot of confusion if there are already URLs pointing to the old locations.

Domain specific modules and themes should also be placed in /sites/example.com/modules and /sites/example.com/themes respectively.

Contributed modules and additional themes which are for use by all domains in a multi-site installation should be placed in /sites/all/modules and /sites/all/themes. Note that there shouldn't be a /sites/all/files or /sites/all/settings.php.

The /sites/default directory should contain /files and settings.php, for use if the /sites/example.com directory doesn't exist for a domain.

In addition to multiple sites, such as example1.com and example2.com, sub domains are also easily set up. Adding sub3.example2.com and sub3.example2.com/site4, the directory structure for these four sites would be:

/drupal/sites/all/modules
/drupal/sites/all/themes
/drupal/sites/default/files
/drupal/sites/default/settings.php
/drupal/sites/example1.com/files
/drupal/sites/example1.com/modules
/drupal/sites/example1.com/settings.php
/drupal/sites/example1.com/themes
/drupal/sites/example1.com/tmp
/drupal/sites/example2.com/files
/drupal/sites/example2.com/modules
/drupal/sites/example2.com/themes
/drupal/sites/example2.com/tmp
/drupal/sites/example2.com/settings.php
/drupal/sites/sub3.example2.com/files
/drupal/sites/sub3.example2.com/modules
/drupal/sites/sub3.example2.com/settings.php
/drupal/sites/sub3.example2.com/themes
/drupal/sites/sub3.example2.com/tmp
/drupal/sites/sub3.example2.com.site4/files
/drupal/sites/sub3.example2.com.site4/modules
/drupal/sites/sub3.example2.com.site4/settings.php
/drupal/sites/sub3.example2.com.site4/themes
/drupal/sites/sub3.example2.com.site4/tmp

Note that Drupal reconizes www.example.com as a sub-domain of example.com.
If you wish to point both of them to the same site, use /drupal/sites/example.com/ as your directory, and uncomment the corresponding option in your .htaccess

Once you've done this, the file structure of your site will be cleanly organized:

  • The main Drupal directory will contain only the standard 'core' files.
  • Themes and modules that are shared among all sites are properly placed in /sites/all
  • Site-specific themes, modules, and files are compartmentalized and properly placed in /sites/example.com, /sites/example1.com, /sites/sub3.example2.com and /sites/sub3.example2.com.site4 .
  • /sites/default/settings.php and /sites/default/files will be used if /sites/example.com directory does not exist.
  • Backing up the /sites directory and your Drupal database will give you everything you need to restore the site in the event of a crash, or to move to a new server.
  • Adding a domain is easy: just copy the /sites/default directory to /sites/example5.com

To help keep files organized you may choose to use shortcuts to point relevant files and directories that are stored elsewhere in your Drupal installation. These short-cuts (like a desktop "alias") are referred to as "symbolic links" on a Web server. Symbolic links can be used for several purposes:

  • Even if using default settings, a good option is to use links from /sites/example.com directory to point to the /sites/default directory. That way, if the settings and /files are ever changed from the default and actually placed in /sites/example.com, their location does not 'move' and no links are broken.
  • Links could also be used to point the /sites/default directory to your primary site.
  • A /files directory could easily be shared across two domains without being shared across the remaining domains.
  • A non-domain-name path for /files can be setup. If it is possible that the domain name might change (say, from a development name), then you can set up a link from /drupal/sites/moniker to /drupal/sites/example.com, where 'moniker' is a short version of the site name that will remain constant even if /example.com changes.

If you are working from the command line on a Linux, Unix or OSX server you can create a symbolic link using the following command:
$ ln -s /path/to/actual/file/or/directory name_of_shortcut

Although the /sites/default directory could contain a /modules and /themes directory, these elements should usually be placed in /sites/all or /sites/example.com. Similarly, although contributed modules could be placed in /drupal/modules as was the practice in version 4.7, this is not recommended.

Multi-site directory setup for sub-domains, including non-standard ports, is described in the installation instructions found in INSTALL.txt.

See multidomain for a contributed module that allows spanning one site across multiple domains, so that specific content types appear on specific domains or sub-domains.

Version 4.6 and 4.7: Best practice for multi-site set-up under version 4.6 and 4.7 is similar to 5.x. The primary difference is that there is no /sites/all directory. Instead, /modules and /themes that are available for all domains are kept in /drupal/modules and /drupal/themes.

Files Directory
The following user-submitted code may be useful in redirecting URLs for the /files directory to the /sites/example.com/files directory. The following code is added to the [drupal_root]/files/.htaccess file:

<IfModule mod_rewrite.c>
  RewriteEngine on

  # Note: this will redirect to the /sites subfolder which is identical to 
  # the domain accessed by the browser.  If you use partial domain names as 
  # the /sites subfolder (e.g. /sites/domain.com vs /sites/www.domain.com)
  # you will need to modify the Drupal root .htaccess to remove the leading www
  # or modify the following to use the portion of %{HTTP_HOST} that mirrors
  # your /sites subfolders 

  RewriteCond %{REQUEST_FILENAME} !-f
  RewriteCond %{REQUEST_FILENAME} !-d
  RewriteCond %{REQUEST_FILENAME} ^(.*)\/files\/
  RewriteCond %1/sites/%{HTTP_HOST}/files -d 
  # To redirect the URI to the actual location of the file /sites/<domain>/files/<filesname>
  # change the [L] to [L,R]
  RewriteRule ^(.*)$ /sites/%{HTTP_HOST}/files/$1 [L]

  # If the domain does not have a dedicated /sites/<domain>/files folder allow the
  # default folder to catch it.
  RewriteCond %{REQUEST_FILENAME} !-f
  RewriteCond %{REQUEST_FILENAME} !-d
  # To redirect the URI to the actual location of the file /sites/default/files/<filename>
  # change the [L] to [L,R]
  RewriteRule ^(.*)$ /sites/default/files/$1 [L]

</IfModule>

If the .htaccess method doesn't work, try this user-contributed code for use in settings.php, instead of .htaccess.

In settings.php, put this code:

$conf['file_directory_temp'] = 'sites/' .substr(strrchr(dirname(__FILE__), '/'), 1) .'tmp';
$conf['file_directory_path'] = 'sites/' .substr(strrchr(dirname(__FILE__), '/'), 1) .'/files';

Comments

rebafc’s picture

I'm using Drupal 6. To implement multisite I parked a secondary domain over the primary domain and so don't need or use symlinks or aliases (which are always an issue on shared hosting). It's all run out of a single database with a prefix for each set of tables. The basic setup was easy. Congratulations Drupal developers.

The issue I faced was the ability to provide separate upload directories for each domain.

RewriteEngine On

RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ /sites/%{HTTP_HOST}/files/$1 [L]

This Mod Rewrite code sounded about right but I struggled to get it working. I eventually discovered if I accessed the domain without including www. in the URL the Mod Rewrite worked as predicted. With the benefit of hindsight this makes sense as the domain name in the /sites directory doesn't include the www. prefix. So now I have changed the .htaccess in the root directory to rewrite the URL and eliminate the www. prefix. [There was sample code in the supplied .htaccess, so again this was pretty easy.]

The limitation I see with this solution is the need to add a new rewrite condition and rule for each domain hosted with a requirement for an upload directory.

I hope my experience can help someone else struggling with this.

Lk2’s picture

If you have more than 2 sites on your Drupal installation, you may want to have modules/themes installed only in a group of sites (not only in one and not in all of them). Is there any way to do this in Drupal?

I would do it using symlinks, for example:

$DRUPAL_DIR/sites/common/modules/ .... (directory where modules are)

$DRUPAL_DIR/sites/site1.com/modules/the_module (symlink to the module in the other directory)

karolrybak’s picture

This is quite simple you can set path in /admin/settings/file-system

However there might be some files in your db, so you might need to update the db too. Check your files table...

iantresman’s picture

I'd also like to see simpler URLs for accessing site/directory content. eg.
To access an image I have <img src="sites/domain1.com/files/images/picture.jpg">
It would be neater to have <img src="files/images/picture.jpg"> which automatically looks in sites/domain1.com

gilsbert’s picture

Hello all.

On my company we use drupal with multisite installation using at same time subdomains and subfolders.

We used the rewrite rules below for the files directory (tested with apache).

--> begin
RewriteEngine on

# Lembtre: para redirecionar a requisição para a localização física do arquivo mude [L] para [L,R]
# Remember: to redirect the URI to the actual location of the file change the [L] to [L,R]

# Drupal7 múltiplos sites utilizando subdomínios e/ou subpastas!
# Redireciona a pasta "files" para que seja possível utilizar urls curtas.
# Drupal7 multiplesites using subdomain and/or subfolders.
# Redirect the folder "files" allowing the use of short urls.

# Redirecionamento para sites em subpastas.
# Redirecting for subfolder sites.
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME}<>%{REQUEST_URI} ^(.*)\/files\/(.*)<>\/(.*)\/files\/(.*)
RewriteCond %1\/sites\/%{HTTP_HOST}.%3\/files -d
RewriteCond %{REQUEST_URI} ^\/(.*)\/files\/(.*)
RewriteRule ^(.*)$ \/%1\/sites\/%{HTTP_HOST}\.%1\/files\/$1 [L]

#Redirecionamento para sites em subdomínios.
#Redirecting for subdomain sites.
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} ^(.*)\/files\/(.*)
RewriteCond %1/sites/%{HTTP_HOST}/files -d
RewriteRule ^(.*)$ \/sites\/%{HTTP_HOST}\/files\/$1 [L]
--> end

When the site is a subfolder (host/subfolder) the first part of the rule is used.
When the site is a subdomain (subdomain.host) the second part of the rule is used.
You must note we removed the part about redirection for "default site" when the "files" folder is not found. If you want it back you must adapt the rules!

With this rewrite rule setting it was possible to use a simple "files" as the public filesystem root on each site. But this was not a dream, see below.

About the relative paths!

We got the best results from subdomain sites (all relative links to media content were simplified to /files/name-of-file.extension instead of /sites/www.subdomain.domain/files/name-of-file.extension).

But for subdirectories we could not find how to change the default behavior of drupal.
In fact we dont know it it was possible: we tried to setup drupal to complete the relative links using the subdirectory information with no success. If drupal can do that then the solution will be perfect for both conditions and sites can be safely migrated from subdomain to subdirectory system (as far we could note drupal uses the subdirectory information on the relative link... not good for migration).

Well, pathologic could be used but this module works perfectly in case the same site is used in subdomain and/or subdirectory in different servers, but not when the site is used in subdirectory and subdomain in the same server - at least I could not make it work (yes, kind "freak" setup but it is necessary for my company).

With no good solution, we are now using only subdomain and hoping for good news in the next releases of drupal!

Later we found another limitation on rewrite solution: the imce module (file browser integration to drupal)! We dont know why but imce just doesn't work with rewrite rules (we believe it requires direct access to the file system and dont use apache rules to decide how to solve an url... at least it makes some sense).

The imce limitation forced us to abandon the rewrite solution!

For imce integration now we are using the symbolic link solution (each site has a symbolic link at drupal root pointing to the correct "/files" directory, for example a symbolic link "files-site1" pointing to sites/www.domain/site1 or "files-site2" pointing to sites/www.site2.domain). The public file system of each site is different but relative paths produced by drupal (filefield for example), ckeditor and imce are all equal and working.

So this comment is just a sharing experience, hoping to be useful for someone!