Manage your Aegir system from the command-line
As you probably know if you've been using it for a while, Aegir is generally considered to have two hemispheres: one is Hostmaster / Hosting, the install profile and module set that make up the web-based Aegir frontend control panel.
Hostmaster installs your site and provides the dispatcher to run the queues on your system. Hosting and its submodules provide all the functionality that lets you add site and platform nodes and kick off tasks on them (such as Migrate, Clone etc), from a web browser.
The other hemisphere is Provision, which is the 'backend' and guts of the Aegir system. It's essentially a large extension module to Drush that actually performs all the tasks sent into the queue. This component is what installs sites, moves them around, deletes them, creates the VirtualHost configurations and databases and so on.
So really, the Hosting frontend exists simply to provide a convenient method of placing tasks (say, 'hosting-task install @site' into the queue, which hostmaster 'dispatches' and hands to Provision in the form of a Drush command (drush @site provision-install').
In the old Drush 2.x days, we used to have pass a whole bunch of arguments for tasks so that Provision knew what site to operate on and its various components (what platform it was on, etc). These days thanks to Drush 3, we make heavy use of Drush Aliases, which are essentially little registry configs per each object, such as a site, platform or server, that can be loaded in one go with all attributes on-hand ready to use by Drush.
You can see these Drush aliases in your /var/aegir/.drush/ directory. They are the files that end in .alias.drushrc.php
Drush provides you with the command 'drush site-alias' or 'drush sa' to also view what aliases are able to be loaded in the system.
The presence of a Drush alias per object makes things really interesting in Aegir if you want to drive this whole system from the command-line as opposed to use the frontend.
Now, why would you want to do that? Well, think like a sysadmin: by being able to drive a system from a command line, that means you ought to be able to go some ways to automating that system, resulting in less effort, faster turnaround, automated turn-key services.. giving birth to Skynet.. well, the list goes on and on :)
In this tutorial, I'm going to show you how to create two separate Drupal platforms (codebases), install a site on one platform, and migrate (upgrade) that site between the two platforms - all from the command line.
Users who want to skip ahead and learn how to automate processes like this using fancy tools like Jenkins, Fabric or Capistrano: I highly recommend you read my article and watch my screencast on Zero-touch Drupal deployment with Jenkins, Aegir, Git, Fabric and Drush.
Step 1: Build your platforms
Sites in Aegir have to exist on top of (or within, whatever analogy you prefer) a platform. A platform is simply a Drupal codebase - this can be vanilla Drupal, Pressflow, or a custom packaged Distribution such as OpenAtrium or your own awesome forked version of Drupal that has no bugs (right?).
I'll be assuming you have got Aegir already installed but haven't set up any platforms. Let's add some platforms now from the command line, using a Drush Makefile.
Become the aegir user if you haven't already: su -s /bin/bash aegir
Create a directory called 'makefiles'
mkdir ~/makefiles
Create a file in this directory called 'drupal-6.22.make' that contains this:
api = 2 core = 6.x projects[drupal][type] = "core" projects[drupal][download][type] = "get" projects[drupal][download][url] = "http://ftp.drupal.org/files/projects/drupal-6.22.tar.gz"
Make another makefile for Drupal 7 called 'drupal-7.9.make':
api = 2 core = 7.x projects[drupal][type] = "core" projects[drupal][download][type] = "get" projects[drupal][download][url] = "http://ftp.drupal.org/files/projects/drupal-7.9.tar.gz"
Step 2: Generate Drush Aliases for your platforms
The next thing we can do is generate a Drush alias that defines each platform. To do that, you use the Drush (Provision) command 'provision-save', with appropriate arguments likeso:
drush --root='/var/aegir/platforms/drupal-6.22' provision-save '@platform_drupal622' --context_type='platform' --makefile='/var/aegir/makefiles/drupal-6.22.make'
Now you should see a new file in /var/aegir/.drush/ called platform_drupal622.alias.drushrc.php. It should look like this:
$aliases['platform_drupal622'] = array ( 'context_type' => 'platform', 'server' => '@server_master', 'web_server' => '@server_master', 'root' => '/var/aegir/platforms/drupal-6.22', 'makefile' => '/var/aegir/makefiles/drupal-6.22.make', );
Repeat the procedure to save an alias for your Drupal 7.9 platform.
drush --root='/var/aegir/platforms/drupal-7.9' provision-save '@platform_drupal79' --context_type='platform' --makefile='/var/aegir/makefiles/drupal-7.9.make'
Step 3: Verify (and build) your platforms
Now, obviously this has not built the platform - we haven't executed Drush make or ended up with actual codebases on our filesystem yet. But because we made makefiles and referenced them in our Drush aliases, Aegir is smart enough to go right ahead and build the platforms for us when we Verify these platforms.
drush @platform_drupal622 provision-verify
Because this invokes Drush Make as the codebase doesn't exist, you should see something like
drupal downloaded from http://ftp.drupal.org/files/projects/drupal-6.22.tar.gz. [ok]
Rinse and repeat for Drupal 7!
drush @platform_drupal79 provision-verify
Step 4: (Optional) - Import the changes into the Hostmaster frontend
You have a choice now: if you *do* expect that you want to use the frontend web interface to manage this platform and sites on it, in future, then you probably want to import this new platform into the Aegir frontend. It's important to remember that so far, we have operated entirely from the command line: if you visit your Aegir web interface, no Drupal 6 or Drupal 7 platforms exist there yet.
If you ever want to install or manage sites on these platforms from the web interface, you will need to import this platform into Aegir. Fortunately, Aegir provides a magic command that lets you 'refresh' the frontend with information gleaned from the backend. This includes importing new platforms and sites as nodes, if the Drush alias exists for those objects.
drush @hostmaster hosting-import @platform_drupal622
There'll be no output here. If you watch your Aegir frontend, you'll see a new 'Verify drupal622' task added to the queue, and your Platform node will now exist too. Magic!
As always: if you're doing this, repeat with the Drupal 7 platform:
drush @hostmaster hosting-import @platform_drupal79
Step 5: Save a Drush alias for a new site
We have our platforms now, but no sites. Let's repeat the pattern of this process but for a site. Because a site is an object in Aegir, just like a Platform, we need to define a Drush alias for it before we can do anything clever with it.
drush provision-save '@test.example.com' --context_type='site' --uri='test.example.com' --platform='@platform_drupal622' --server='@server_master' --db_server='@server_localhost' --profile='default' --client_name='admin'
Note these options: we define the *type* of alias as a site (as opposed to a platform). We also link this site to the Drupal 6.22 platform using its alias name. We then go ahead and define the 'server' (this is the HTTP component, by default '@server_master' on a standalone Aegir system), the db_server (the MySQL component, which by default is '@server_localhost' on a standalone Aegir system), the install profile and so on.
Your Drush alias in /var/aegir/.drush/ should look something like this:
$aliases['test.example.com'] = array ( 'context_type' => 'site', 'platform' => '@platform_drupal622', 'server' => '@server_master', 'db_server' => '@server_localhost', 'uri' => 'test.example.com', 'root' => '/var/aegir/platforms/drupal-6.22', 'site_path' => '/var/aegir/platforms/drupal-6.22/sites/test.example.com', 'site_enabled' => true, 'language' => 'en', 'client_name' => 'admin', 'aliases' => array ( ), 'redirection' => false, 'cron_key' => '', 'profile' => 'default', );
Note the various other options for saving Drush aliases in Aegir. You can see all options by running 'drush help provision-save' too.
Step 6: Install your site
In just the same fashion that we saved an alias for our platform, then ran 'provision-verify' to build it, we'll do the same with our site; except that we use 'provision-install' for sites.
drush @test.example.com provision-install
Step 7: (Optional) - import your site in to the frontend
Again, if you elected to maintain management of the site and platforms in the Aegir frontend for later, you will want to import this site into the frontend now.
Importing the site is a bit different: Aegir will think it needs to 'install' the site even though we've already installed it. To work around this, simply execute a 'Verify' of the platform this site sits on, via the frontend. This will invoke a proper import of the site. (This probably needs to be improved in a future version of Aegir itself so we don't have to jump through such a hoop)
drush @hostmaster hosting-task @platform_drupal622 verify
This will automatically discover the site and spawn an 'Import' task for the frontend to import this site.
Step 8: Migrate (upgrade) your site between Drupal 6 to Drupal 7
I'm going to presume you've saved your Drupal 7 alias, ran provision-verify to build the actual codebase, and optionally imported that platform into the frontend with hosting-import.
Now let's migrate our site from the command-line, from the Drupal 6 to Drupal 7 platform. This is analogous to 'upgrading' the site between releases, because the migration process in Aegir puts the site on the new codebase and then runs drush updatedb (equivalent of running update.php) to apply database updates.
drush @test.example.com provision-migrate @platform_drupal79
Because this example is a rather dramatic one (a jump between core versions!) you'll see a lot of activity eventually occur, whilst a lot of database updates take place. You can, obviously, use this procedure simply to apply small module upgrades within the one version of Drupal core.
It is highly recommended, in fact, to use this 'migrate between platforms' workflow for applying *any* code/database changes to your site, because you can take advantage of the Aegir ability to detect a failed update and 'roll back' automatically to the original version. See other articles on best practices for Aegir site update workflows.
Your site is now a Drupal 7 site!
Step 9: (Optional) - refresh the frontend with the migration change
Once again: the frontend doesn't know that you migrated the site between the two platforms directly from the commandline. If you want the frontend to be notified of this change, run the following:
drush @hostmaster hosting-import @test.example.com
You'll note that the site's 'platform' in the frontend is now drupal79 instead of drupal622.
Step 10: Fix the site's alias to use default profile
Now, we incidentally have an obscure bug here which resets the profile to 'N/A' in the frontend: this is because the migration retained the 'default' profile in the alias instead of switching it to 'standard', the new default profile in Drupal 7. To fix this, we need to re-save the Drush alias with the updated details:
drush provision-save '@test.example.com' --context_type='site' --uri='test.example.com' --platform='@platform_drupal79' --server='@server_master' --db_server='@server_localhost' --profile='standard' --client_name='admin'
Now re-verify the site (updates the defined profile in the site's settings.php:
drush @test.example.com provision-verify
And if you are keeping the frontend up to date, run:
drush @hostmaster hosting-task @test.example.com verify
... and you should see the profile is now 'Standard' in the site listing in the frontend.
This should not be necessary if you are simply migrating between point releases within the same version of core, or even migrating between the same version of core but applying upgrades of specific contrib or custom modules.
Deleting sites
Note that you can run drush @test.example.com provision-delete to delete the site from the system. Currently, however, we don't have a mechanism in place for reflecting that change in the frontend via hosting-import - but hopefully we will soon. See this ticket
Programatically add aliases
This is an edit 24 hours after I posted this: someone on IRC asked 'can you programatically add URL aliases to a site'? And the answer is, yes you can :)
Make sure you have the Site Aliasing feature enabled in /admin/hosting/features, then, (in this example, assuming your site already existed and was in the Aegir frontend) simply re-save your Drush alias for the site, passing a comma-delimited list of aliases as an argument:
drush provision-save '@mig3.test.dev' --context_type='site' --uri='mig3.test.dev' --platform='@platform_drupal622' --server='@server_master' --db_server='@server_localhost' --profile='default' --client_name='admin' --aliases='www.mig3.test.dev, test.dev'
Check your alias file in ~/.drush/ and you should see an array of aliases listed now:
$aliases['mig3.test.dev'] = array ( 'context_type' => 'site', (snip for readability) 'aliases' => array ( 0 => 'www.mig3.test.dev', 1 => ' test.dev', ),
Now run
drush @mig3.test.dev provision-verify
, which will rewrite your Apache vhost to include these aliases as ServerAlias parameters and will restart Apache to make those aliases active.
Finally: your site node in the frontend still doesn't show any aliases, as discussed several times in this post. To refresh the frontend and see those aliases listed, run the magic hosting-import command:
drush @hostmaster hosting-import @mig3.test.dev
And now your aliases will be visible in the site node!
Other commands
There are other commands available in Provision, including the ability to reset the one-time login URL for an administrator on a site, cloning sites, and so on. Use 'drush help' as the aegir user to view the various provision commands, and use 'drush help provision-(command)' to get more detailed instructions on syntax.