Automated Drupal SaaS with Aegir3

Cookie-cutter site services, or Drupal SaaS as we like to call them (for software-as-a-service), have been the object of much discussion recently.

The basic idea is that you create a cool site or web application using a well-supported or custom-made Drupal distribution. After a bit of configuration, you can then copy this site for each client and charge on a per-site basis. (This is in contrast to same-site Drupal SaaS systems which require a very rigid and complex permissions and domain name system.)

As libre software, Aegir is particularly well suited to creating these commercial services because you can extend it as you wish, unlike proprietary Drupal management systems.

We've been doing automated SaaS with Aegir for a while, but in light of my recent promotion to official Aegir maintainership, I've developed and improved a number of modules to upgrade this SaaS workflow to Aegir 3. You can see this in action on GetOpenOutreach.

This service runs entirely with free, non-proprietary code. You can replicate it on your own server like so:

  1. Install Aegir 3. See the official site for quick Debian intructions. (Note: There is an install bug on Jessie at the time of writing.)
  2. Point your *.example.com subdomains to the server.
  3. Create a platform using your favorite distribution. Let's call it dx-1.0.
  4. Create a site on that platform. This is the template site, we'll call it skeleton (skeleton.example.com).
  5. Download and activate the following modules:

    Heres some code to do this in /var/aegir/hostmaster-3.[x]/[yourfrontendurl]/modules:

    drush dl hosting_variables hosting_saas
    git clone https://github.com/PraxisLabs/hosting_saas_utils.git
    git clone --branch no-specifics https://github.com/PraxisLabs/hosting_restapi.git
    drush en hosting_variables hosting_saas hosting_saas_utils hosting_restapi

  6. Configure hosting_saas (hosting -> SaaS) to use skeleton and dx-1.0. At the time of writing, there is no autocomplete so you'll have to find the node Nid in the Edit path of the site and platform. Don't forget to set an API key.
  7. Configure hosting_saas_utils (hosting -> SaaS Utilities) with the argument names for the user's email and name. (Any arbitrary name will do, you can use the same argument for both.) This will be used later in the API call. In our case, we also bridge the site name (just write site_name and site_name in the first pair of fields).

At this point, your Aegir SaaS backend should pretty much work. You can test the web API on the command line:
curl --data "key=yourkey&url=test1.example.com&invoice=1&site_name=MyTestSite" http://aegir.example.com/hosting/api/site

Note that you'll need to increment the url and invoice on each test.

Now you'll need a public-facing site to sell the sites. This can be an e-commerce site but it doesn't really need to be if you offer free trials. In any case, you'll need this site to do the same POST request. You can easily do this with Drupal and webform; here's an example from GetOpenOutreach:

// This is done when the client's email is confirmed
// see https://www.drupal.org/project/webform_confirm_email
$bootstrap_library = $submission->data[11]['value'][0];


  $theme_settings = array (
  [...]
    'bootstrap_library' => $bootstrap_library,
  [...]
  );


  $post_options = array(
    'key' => 'Your API key here', // Probably take this from a file
    'invoice' => $submission->sid, // Use the webform submission ID as invoice ID
    'url' => "example.com",
    'email' => $submission->data[2]['value'][0],
    'username' => $submission->data[2]['value'][0],
    'site_name' => $submission->data[4]['value'][0],
    'theme_kalatheme_settings' => $theme_settings,
  );


  // Do the curl thing
  $ch = curl_init();
  curl_setopt($ch, CURLOPT_URL,"http://aegir.example.com/hosting/api/site");
  curl_setopt($ch, CURLOPT_POST, 1);


  $build_query = http_build_query($post_options, NULL, '&');


  // Must specify '&' because default is dumb
  curl_setopt($ch, CURLOPT_POSTFIELDS, $build_query);
  // receive server response ...
  curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);


  $raw_so = curl_exec($ch);
  $server_output = json_decode($raw_so);
  curl_close ($ch);


  // You can detect if there's an error
  if (empty($server_output) || $server_output->status == 'error') {
    // Error, you can probably display $server_output if you feel like it
    drupal_set_message(t("There was an error with your submission!"), 'error');
    mail("myemail@example.com", "Error processing site", $prefix);
  }
  else {
    // It worked
    drupal_set_message(t("Your request has been queued! You will receive an email."));
  }

Anyway, that's the basic idea. Drop us a line if you need help with this, it's what we do for a living :)

We also have an AegirVPS service and an incoming SaaSVPS to do this very thing. Email us to know more.