Breaking up the Monolithic Drupal Site with a Subdomain Multisite

hydra1

Breaking up the Monolithic Drupal Site with a Subdomain Multisite

When building a Drupal website, do you ever notice that the site sometimes gets too complex and has too many modules installed? We run into this with clients that want a lot of features in their website such as commerce, forum, blog, knowledge base, and more.

The problem comes from the fact that there are dozens of modules that need to be installed and configured for commerce, forum and every other feature to work right. As more and more modules get installed and configured, they start clashing and adding massive complexity to the site. Sometimes different features will need things to be configured differently.

Since each module is being used on every page, the memory footprint becomes enormous. When doing commerce, it really shouldn't need all the hooks and code for all the forum code and vice versa. We've even seen sites with massive memory footprints that take 768MB to 1GB of ram PER INSTANCE to run.

We've found a better way.

Instead of building out a complex site in a single monolithic install, we're breaking it out into multiple installs using subdomains and Drupal's multisite functionality. This allows us to focus on the specific functionality for a part of the site on a single install. For example, the forum would be installed at forum.example.com, the store at store.example.com and the main marketing website at www.example.com.

The trick to all of this is that we have to make this seamless to the end user and in a maintainable way.

ISSUES WE'VE HAD TO SOLVE SO FAR:

(I'll be writing about the rest of these in later blog posts)

Managing sandbox, dev, test, production for a Subdomain multisite.

First, let's look at how we keep things maintainable.

Each part of the rollout process is going to need a top level domain name. This is important later on as we start setting up settings. For this blog post, we'll pretend to use example.local for our sandbox, example-dev.com for the dev server, example-test.com for the test server and example-prod.com for the production server.

There will be a single repository and code set for all of the subdomains. We don't want to break them out into separate repositories as that would get unmanageable in a hurry.

One of our best practices is to modify the core .gitignore file to add in the main settings.php file but ignore any local.settings.php files.

First edit the .gitignore file and change the settings ignore to:

sites/*/local.settings.php

Then add the following to the end of the sites/*/settings.php file:

if (file_exists(dirname(__FILE__) . '/local.settings.php')) {
  include dirname(__FILE__) . '/local.settings.php';
}

This allows us to override any of the settings.php settings on our sandboxes.

We will also need a "Global" settings file. There are lots of things that will be shared between the sites. Instead of trying to keep those in sync manually, we can just add them to a global settings file. To do this, create a file at sites/global.settings.php and then add

if (file_exists(dirname(__FILE__) . '/../global.settings.php')) {
  include dirname(__FILE__) . '/../global.settings.php';
}

to each of the sites/subdomain/settings.php file. Any $conf settings put in here will be global across all of the sites. We like to put in the Acquia network settings and account settings for a start. Pretty much everything that is global should be put in here though.

The next step is to create the separate subdomain installs. It is actually fairly easy to do this. Start with a basic Drupal repository. We are going to be doing most of the work in the sites directory.

Create a folder under sites for each of the subdomains. Here are some of the ones we've used.
sites/accounts
sites/forum
sites/knowledgebase
sites/marketing
sites/store
There should already be a sites/all and a sites/default.

In each of these sites folders, create a settings.php file with settings for that subdomain. Then create directories for "modules" and "files". These are modules and files specific to that subdomain. Please see below about contrib modules.

Next edit the sites/sites.php file (or create one if it doesn't exist) and add:

// Accounts Site
$sites['accounts.example-dev.com'] = 'accounts';
$sites['accounts.example-test.com'] = 'accounts';
$sites['accounts.example-prod.com'] = 'accounts';
$sites['accounts.example.local'] = 'accounts';

// Marketing Site
$sites['example-dev.com'] = 'marketing';
$sites['example-test.com'] = 'marketing';
$sites['example-prod.com'] = 'marketing';
$sites['example.local'] = 'marketing';

// Knowledgebase Site
$sites['kb.example-dev.com'] = 'knowledgebase';
$sites['kb.example-test.com'] = 'knowledgebase';
$sites['kb.example-prod.com'] = 'knowledgebase';
$sites['kb.example.local'] = 'knowledgebase';

// Forum Site
$sites['forum.example-dev.com'] = 'forum';
$sites['forum.example-test.com'] = 'forum';
$sites['forum.example-prod.com'] = 'forum';
$sites['forum.example.local'] = 'forum';

// Store Site
$sites['store.example-dev.com'] = 'store';
$sites['store.example-test.com'] = 'store';
$sites['store.example-prod.com'] = 'store';
$sites['store.example.local'] = 'store';

One of the issues we came across early on was where to put contrib modules. At first we were putting subdomain specific contrib modules under each subdomain. Then we quickly ran into a problem where we needed to share modules we didn't expect and then either had to move them out of the subdomain modules folder and into sites/all/modules or create an additional copy in the other subdomain (bad). We decided on a policy for a Subdomain Multisite that ALL contrib modules that are needed on any subdomains would be placed in sites/all/modules. This makes for easier sharing between sites when you don't initially expect it and easier maintainability since we will always know where contrib modules are located. So far this has worked out very well for us. Note that the modules don't have to be ENABLED on all of the subdomains but they are AVAILABLE.

So what do we put in the sites/subdomain/modules directory? We put in features and custom modules for the subdirectory. We add basically the content types, views and other pieces that are specific to that subdomain.

Set up this way, we now have a single codebase with a multisite install that will work on sandbox, dev, test and prod. It is also about as maintainable as we can make it.

Sharing the Theme between subdomains

Since the sites should be seamless to the end user, they should all share the same theme. This is actually relatively easy and straightforward. Add the theme to sites/all/themes and ensure the theme is enabled and set to default on each of the subdomains (either manually or in a shared module) and all the sites will look the same.

I'll be blogging more soon about the other issues we've solved when developing subdomain multisites. Have any ideas on how to improve this process?

Please share your comments below!

Related Posts

Subdomain Multisite Part 2

Randall Knutson
Read more

Content Migration From One Drupal 7 Site to Another

Ahmad Kharbat
Read more

Breaking Down the Ad Age Power150

Michael Kasberg
Read more

Breaking News: Android Users Like Apps Too!

Julie Miller
Read more

Socialize Your Drupal Site in 5 Easy Steps

Tom McCracken
Read more

Synchronize one drupal site with another using Drush

Dustin Currie
Read more