Drupal - Is there any management utility for multi-site deployment?

Take a look at Aegir:

  • http://drupal.org/project/hostmaster
  • http://www.aegirproject.org/

It's probably a bit more than what you are looking for, since it manages your web server vhosts (apache or nginx), which means that it kind of takes over part of the system configuration. It also works much better on Debian (with Debian packages, installation/upgrades are pretty easy.. kind of annoying otherwise).

Once it's installed, you can create your base site and clone it using the Aegir user interface (which is a Drupal site, called the "hostmaster", which is completely autonomous from the other sites you are hosting - it's just that as Drupal developers, they used Drupal for the front-end to their tool). Under the hood, Aegir uses Drush, so it's not re-inventing the wheel.

Anyway, fair disclaimer: there is a learning curve, but it has a pretty good community and it's well worth it when managing farms of small sites. It also has commercial training/support available from a few companies (listed on the project page).


There is no single management utility (maybe some managed cloud solutions) which can easily manage your all Drupal instances, so you have to learn how to mix different tools together (e.g. Puppet + drush). Most of it can be done by drush.


Ansible

Ansible is a flexible and extensible automation tool which definetly can help with multisite deployment.

See:

  • Ansible Role for Drupal (GitHub)
  • Drupal VM is a VM for local Drupal development, built with Vagrant + Ansible.

Puppet

Probably you don't need it, but in case you'd need to set-up whole LAMP configuration each time (e.g. on multiple servers), you should use some configuration management utility.

For example to automatize LAMP environment configuration (Linux, Apache, MySQL and PHP) you can use either Puppet or Chef. Having proper Puppet recipe, you're able to configure whole LAMP configuration in one command. Check some basic recipe example for ADS distribution: ads.dev.pp.

Installing Puppet is easy (sudo apt-get -y install puppet), then you've to install necessary modules (e.g. for Apt, Apache and Pear). In example:

sudo puppet module install puppetlabs/apt; sudo puppet module install rafaelfc/pear; sudo puppet module install puppetlabs-apache

For more advanced recipe (different db per vhost), check: Proper way of importing many manifest files with vhost definitions.


Drush remotes

Once you've LAMP environment ready, you need to define your remote shell aliases, so you can transfer your files and database across your sites. Check example.aliases.drushrc.php how to use it.

You can use different remotes for each multi-site instance, e.g.:

// The site in sites/default/
$aliases['site.default'] = array(
  'uri' => 'default',
  'root' => '/path/to/drupal',
);
// The site in sites/site1/
$aliases['site.site1'] = array(
  'uri' => 'site1',
  'root' => '/path/to/drupal',
);

Make sure that you'll add your SSH key into your authorized_keys, so it won't ask you for the password each time when running remote commands. See: How to add RSA key to authorized_keys file?.


Site installation

If you'd like to install Drupal sites from scratch, consider using Drupal installation profiles or drush make files (writing one or generating from the existing site).

You can simply check how distributions such as Recruiter, Commerce Kickstart or ADS work.

For complex solutions, you may use phing (or ant). Check example of build.xml from ADS or check Template Phing build.xml file for Drupal projects.

See also: What is the easiest way to install clean Drupal from scratch?


Transfering the files to the remote

Once you have your shell aliases set-up, transferring files is easy.

In example:

drush -v rsync drupal/ @remote

Multi-site example:

drush -v rsync drupal/ @remote1,@remote1

Or this can be achieved by defining each e.g. dev alias in separate *.aliases.drushrc.php group alias files, so calling @dev would invoke all defined dev environments.

See also: How to rsync files between two remotes which share the same host?


Synchronising database between sites

Transfering database is easy as well by drush sql-sync, e.g.:

drush sql-sync @self @remote

This will transfer your local Drupal database into remote. You can also use the same command to transfer the database between two remotes.


Managing settings file

You can consider to edit your settings.php and include at the end extra file such as settings.local.php as your instance-specific configuration file (example 1, 2), then it'll be easier to maintain (as it can be ignored by git). So if you have multiple environments, you can use the following simple approach to load the settings based on your current environment:

$conf['environment'] = $env = 'local'; // dev, test, prod)

And use the simple switch statement to invoke different settings per environment.

Here are the example settings files from ADS distribution which you can use.

If you want to automate changes to your settings file, you can define some drush alias to do something like sed s/DB_NAME/real_db_name/ (drush normally accept arguments and pass them to the remote), or check Can you modify the settings.php file using drush?.


Drush shell aliases

If you want your dream to come true, use drush shell aliases to define your commands which you'd like to execute on remotes as part of your deployment script.

Same examples for your remote:

$aliases['dev'] = array(
'shell-aliases' => array(
  'deploy-code' => '!git fetch origin && sudo git stash && sudo git reset origin/dev --hard',
  'deploy-db' => '!drush sql-sync --yes @prod @self',
  'deploy-files' => '!drush --yes rsync @prod:%files @self:%files',
  'deploy-drupal' => "!
    sudo -uwww-data drush -y updb &&
    sudo -uwww-data drush cc all &&
    sudo -uwww-data drush -y fra &&
    sudo -uwww-data drush cron &&
    sudo -uwww-data drush status-report --severity=2 &&
    echo Deployment completed.
  ",
));

And then you can combine them by defining your local aliases in your drushrc.php, e.g.

$options['shell-aliases'] = array(
  'deploy-dev' => '!drush @dev deploy-db && drush @dev deploy-code && drush @dev deploy-files && drush @dev deploy-drupal',
);

So by running simply drush deploy-dev it will transfer the files and database from prod into your testing (dev) environment, run updates, clear cache, run cron, revert all features, etc.


Your use case

Based on above, your use case can be solved by the following commands on local:

  1. Clone the site:

    drush -yv @site exec drush rsync sites/site-1 sites/site-2
    
  2. Upload the settings file and modify the database:

    drush rsync examples/default.settings.local.php @site:sites/site-2/settings.local.php
    drush -vy @site exec sed -i -e s/DB_NAME/real_db_name/ sites/site-2/settings.local.php
    
  3. Transfer the db between sites.

    drush -vy @site sql-sync --create-db site-1 site-2
    
  4. Enable chosen set of modules:

    drush -vy @site en module_1 module_2
    

You can create easily the drush alias for that. E.g.

drush clone-site site-1 site-2 # Last 2 are arguments.

Eventually check how to use policy.drush.inc, so you can add your own pre-process, post-process code for any of your drush command.


Read more:

  • Using drush to synchronize and deploy sites at Drupal.org
  • Use Drush to Sync Your Drupal Installations Between Multiple Environments at Acquia
  • How to Migrate and Sync Drupal Sites with Drush at digitalocean.com
  • Drush Tip: Quickly Sync Files Between Your Environments With Rsync at soundpostmedia.com
  • Drush aliases primer for Live->Dev syncing at emspace

I would install provision.

It's the backend part of Aegir, implemented as a drush extension.

It literally contains the command you are looking for: provision-clone, which will allow you to Clone a site between platforms. In provision language, "platform" is a Drupal install. You could just clone the site within the same platform though.

You also have another option in these two commands:

  1. backup - Generates a tarball containing the sites directory, the site data configuration and the database dump.
    • This allows the tarball to act as a 'site package', which can be redeployed on other installations, or used for an upgrade.
  2. deploy - Accepts a site package (backup) as argument, and redeploys it, running the upgrade processes on it.
    • Uses hook_provision_pre_upgrade(), hook_provision_upgrade() and hook_provision_post_upgrade() hooks, and allows clean roll back if any errors occur. Will include stringent checking of module versions, and allow unit tests to be run.

You can completely skip hostmaster, the UI part of Aegir, and work with provision on it's own. Among commonly known projects, I believe this is the closest you will get to what you want.