Manage multiple Drupal sites efficiently using Drush and "proto-sites"

While the amount of documentation and support surrounding Drupal as a whole is fabulous, there's a surprising dearth of information regarding management paradigms. Lots of people talk about small parts of the puzzle, like using SVN and vendor branching to track custom changes to modules, but there's not a lot of talk about how to efficiently manage large numbers of Drupal sites. So I figured I would share the architecture that I came up with, in the hopes that it'll help other maintainers as well!

My needs

I manage a dedicated server with a number of Drupal installations on it for various individuals and organizations. The sites are generally either "research" sites or "personal" sites (each type has a different set of modules and configurations). My goals are primarily to:
  1. Conserve server resources (i.e. disk space)
  2. Keep the server secure (a real toughie when dealing with PHP)
  3. Minimize administrative overhead
There are a number of tools out there that will help with these tasks, but unfortunately all of the ones that I've found fail at one or two of them.

Drupal's native multi-site handling

This certainly handles goal (1) well, but fails at pretty much everything else. Security becomes a nightmare, as does anything beyond basic maintenance. I don't think I need to elaborate on this point. :)

Aegir

Let me just say that Aegir looks absolutely fabulous, and I can't wait to see it mature, but it still fails on point (2), and to some extent (3) as well. As mentioned in this Aegir group post, there's really no way to set permissions such that Aegir is free to do its thing and their aren't gaping security holes (assuming clients have read/write access to their own files). Additionally, I'd like for all of the clients' files to reside in their home directories, to simplify backups and quota management. There's just no way to do this and use Aegir.

Drush

Drush is another fabulously useful tool that satisfies points (2) and (3), but doesn't deal well with "non-vanilla" setups, such as multiple sites sharing a single module repository. However, I found a way to bend it to my will...

The solution: Proto-sites

Let's say I have four Drupal installs on my server: /home/client1/research-site /home/client2/research-site /home/client3/personal-site /home/client4/personal-site What I did was simply create two new Drupal installs called "Personal proto-site" and "Research proto-site": /var/www/drupal/research /var/www/drupal/personal I then symlinked the sites/all directory of each client site to it's respective proto-site, i.e. /home/client1/research-site/sites/all -> /var/www/drupal/research/sites/all Now, to update modules for ALL of the research sites at once, I simply cd into the research proto-site directory and run sudo drush up I then run a simple shell script* that runs drush updatedb on each client site. And voila - you have no wasted space from duplicated modules, good security (inasmuch as PHP allows), and minimum administrative overhead - just two commands to run per proto-site (which could easily be combined into one with a shell script). What's awesome about this setup is that it's quite extensible. For instance, if a client wants to override the shared version of the module, they can just put their own version in their sites/danepowell.com/modules. You can also use the proto-site to develop and distribute Features. Finally, you can also share copies of Drupal core, e.g. ls -al /home/client1/research-site /home/client1/research-site/cron.php -> /var/www/drupal/research/cron.php /home/client1/research-site/includes -> /var/www/drupal/research/includes etc... I'm really digging this new architecture and how much time it saves me. The only other tough nut that I need to crack is how to maintain stock modules alongside custom/patched ones. I want to use the drush scripts to quickly update stock modules en masse, but I need to use SVN and vendor branching to update the patched ones. Unfortunately, there's no way to discriminate between the two when they're all sitting in the same directory on a proto-site... Update: problem solved - see my post on updating side-by-side stock and hacked modules I'd love to hear how you manage multiple Drupal sites, and any suggestions on improving this workflow - please leave a comment below! * drush-update-all #!/usr/bin/env bash installpath[1]=/var/www/drupal/research installpath[2]=/var/www/drupal/personal installpath[3]=/home/client1/research installpath[4]=/home/client2/research installpath[5]=/home/client3/personal installpath[6]=/home/client4/personal for index in 1 2 3 4 5 6 do filepath=${installpath[index]} printf "Updating %s\n" "$filepath" cd $filepath drush updatedb drush pm-refresh done