Photo of a variety of elaborate drawer pulls; Photo by Cobro via Unsplash; unsplash.com/@cobro
Photo by Cobro on Unsplash

So you’ve got a multisite platform in Drupal, WordPress, or another CMS? And you want to use Tugboat? Great news—Tugboat has support for that!

What is Multisite and why use it?

There are a few different CMS platforms out there that have multisite capabilities, most notably, Drupal and WordPress. While the name and technology may be different under the hood it’s mostly the same: you have different websites that all use the same code and the same server infrastructure.

Like Tugboat, using multisite can drastically reduce infrastructure costs for large organizations with multiple departments or agencies, such as schools and universities, medical and healthcare institutions, government organizations, and the like. This is because multisite only needs a single large server stack to host hundreds, even thousands of sites.

How Tugboat multisite works

Adding Tugboat to that mix results in deeper cost savings by further reducing infrastructure expenses, and giving your team loads of time back in development and testing. If you’re an engineer setting up Tugboat for your multisite project, you’re in the right place. The remainder of this article will describe how Tugboat’s aliases configuration works with multisite.

The imaginary Hogwarts.edu

Let’s enter the land of make-believe to a school named Hogwarts that has many websites for different departments, using Drupal multisite on a single shared codebase. Maybe a few of those sites are:

  1. arithmancy.hogwarts.edu
  2. dark-arts.hogwarts.edu
  3. herbology.hogwarts.edu
  4. potions.hogwarts.edu

You are an engineer working on these sites, and have been tasked with bringing Tugboat on at Hogwarts so that you can further reduce hosting costs and squash bugs—or should we say pixies? After first getting Tugboat set up, your Tugboat dashboard might look like this:

Screenshot of Tugboat Dashboard showing Preview button with no aliases

You can see we have a single Preview for a pull request that updates the Defense Against the Dark Arts. Especially of note, the Preview button itself is a single button. You have one Preview, you get one Preview URL. When you click the Preview button, you are taken to https://pr18-eqwhq9aa9sfvf0abqu2m0zduuzrjy92l.tugboat.qa.

Let’s change that so that for every Tugboat Preview, you get multiple URLs, one for each site in your Drupal multisite.

Adding URL aliases to your Tugboat config

To make this change, we need to pop open the Tugboat config. Maybe your Tugboat config looks something like this:

services:
  php:
    image: tugboatqa/php:7-apache
    default: true
    ...

The php service is the default service, which means it’s where the Tugboat Preview URL will direct requests to. To add new URLs, we will use the aliases configuration, like so:

services:
  php:
    image: tugboatqa/php:7-apache
    default: true
    aliases:
      - arithmancy
      - dark-arts
      - herbology
      - potions
    ...

Here, we’ve added 4 aliases to the PHP service, one for each of the sites. I’ve named each alias after the subdomain of each one; for example, arithmancy is the alias to correlate with the arithmancy.hogwarts.edu site. Let’s see what happens in Tugboat when I rebuild that Preview with this new configuration.

Screenshot of Tugboat Dashboard showing dropdown arrow on Preview button

After the rebuild is complete, Tugboat now presents a drop-down inside of the Preview button. Clicking that little drop-down arrow reveals the different URLs Tugboat has used:

Screenshot of Tugboat Dashboard showing dropdown arrow with expanded options

Before I added aliases, I just had a single Preview button with a single URL (https://pr18-eqwhq9aa9sfvf0abqu2m0zduuzrjy92l.tugboat.qa/). Now that I’ve added 4 aliases, I get 4 more URLs, one for each alias. Brilliant. Each alias is placed in front of the Preview’s unique URL token and separated by a hyphen. That means each aliased URL will be in the form of https://[alias]-[token].tugboat.qa.

Mapping aliased Tugboat URLs to each site in Drupal multisite

Note: the following instructions assume you already have some understanding of how Drupal multisite works, and will just be making changes to recognize the Tugboat URLs. Make sure to consult the Drupal multisite documentation for your version of Drupal.

At this point, we have Tugboat providing additional URLs for each of the sites in your Hogwarts.edu Drupal multisite installation. But, if you click on any of these links, Drupal doesn’t really know what to do with them yet. So, we have to make some changes in the Drupal CMS itself in order for it to know that, for example, https://arithmancy-eqwhq9aa9sfvf0abqu2m0zduuzrjy92l.tugboat.qa should map to the arithmancy.hogwarts.edu website in Drupal.

Here is the current folder structure of our Drupal site:

.
└── sites
    ├── arithmancy.hogwarts.edu
    │   └── settings.php
    ├── dark-arts.hogwarts.edu
    │   └── settings.php
    ├── herbology.hogwarts.edu
    │   └── settings.php
    ├── potions.hogwarts.edu
    │   └── settings.php
    └── sites.php

And inside of sites.php, we have this:

$sites['arithmancy.hogwarts.edu'] = 'arithmancy.hogwarts.edu';
$sites['dark-arts.hogwarts.edu'] = 'dark-arts.hogwarts.edu';
$sites['herbology.hogwarts.edu'] = 'herbology.hogwarts.edu';
$sites['potions.hogwarts.edu'] = 'potions.hogwarts.edu';

On the left (the array keys) we have the incoming URLs and on the right (the array values) we have the directory inside of ./sites that corresponds with that site.

We need to add the new Tugboat URLs to this list. Recall our format for these URLs : https://[alias]-[token].tugboat.qa. In our example, the token there is that long, unique string of characters that you see in the URL, eqwhq9aa9sfvf0abqu2m0zduuzrjy92l . Since that token changes for every Tugboat preview, we need to use a variable for it. Good news: it’s available in all Tugboat Previews as an environment variable called TUGBOAT_DEFAULT_SERVICE_TOKEN. So, to add mappings in sites.php for each of these Tugboat URLs, you might add something like this to your sites.php:

// If we're on Tugboat, use the unique URL token that Tugboat provides to also
// map Tugboat's aliased URLs to the correct site.
if ($tugboat_token = getenv('TUGBOAT_DEFAULT_SERVICE_TOKEN')) {
  $sites["arithmancy-{$tugboat_token}.tugboat.qa"] = 'arithmancy.hogwarts.edu';
  $sites["dark-arts-{$tugboat_token}.tugboat.qa"] = 'dark-arts.hogwarts.edu';
  $sites["herbology-{$tugboat_token}.tugboat.qa"] = 'herbology.hogwarts.edu';
  $sites["potions-{$tugboat_token}.tugboat.qa"] = 'potions.hogwarts.edu';
}

If you’re feeling fancy, instead of listing them explicitly like this, you could also loop over the existing $sites array and perform a string replacement to generate the Tugboat URLs.

You can also map the main preview URL (the one that the big Preview button links to if you don’t use the drop-down) to one of the sites. There’s an environment variable called TUGBOAT_DEFAULT_SERVICE_URL_HOST that works perfectly for that. Then any users that click the Preview button without using the drop-down are taken to the site you’ve mapped it to.

      ...
      // Map the main Preview URL to arithmancy.
      $sites[getenv('TUGBOAT_DEFAULT_SERVICE_URL_HOST')] = 'arithmancy.hogwarts.edu';
    }

That’s it! You’ve now configured your Drupal site to be able to use the Tugboat aliases and map each of them to the correct site in your Drupal multisite.

Importing multisite databases

Now that we have the URL mapping complete, we will also need to import the databases for those sites. The Tugboat starter config documentation for Drupal 8 has this example configuration for importing a database.

services:
  ...
  mysql:
    image: tugboatqa/mysql:5
    commands:
      update:
        - scp user@example.com:database.sql.gz /tmp/database.sql.gz
        - zcat /tmp/database.sql.gz | mysql tugboat
        - rm /tmp/database.sql.gz

This works fine when you have a single site, but when you have multiple databases you need to import, you’ll need to expand on that some. We’ll need to create the databases for each site, set appropriate permissions, download databases dumps for each, and import those database dumps into the appropriate database. That might look something like this:

services:
  ...
  mysql:
    image: tugboatqa/mysql:5
    commands:
      update:
        # Delete and recreate the database for each site.
        - mysql -e "DROP DATABASE IF EXISTS arithmancy; CREATE DATABASE arithmancy;"
        - mysql -e "DROP DATABASE IF EXISTS dark_arts; CREATE DATABASE dark_arts;"
        - mysql -e "DROP DATABASE IF EXISTS herbology; CREATE DATABASE herbology;"
        - mysql -e "DROP DATABASE IF EXISTS potions; CREATE DATABASE potions;"

        # Give the tugboat user access to the new databases.
        - mysql -e "GRANT ALL PRIVILEGES ON *.* TO 'tugboat'; FLUSH PRIVILEGES;"

        # Download each database dump.
        - scp user@example.com:arithmancy.sql.gz /tmp/arithmancy.sql.gz
        - scp user@example.com:dark_arts.sql.gz /tmp/dark_arts.sql.gz
        - scp user@example.com:herbology.sql.gz /tmp/herbology.sql.gz
        - scp user@example.com:potions.sql.gz /tmp/potions.sql.gz

        # Import each database dump into the associated table.
        - zcat /tmp/arithmancy.sql.gz | mysql arithmancy
        - zcat /tmp/dark_arts.sql.gz | mysql dark_arts
        - zcat /tmp/herbology.sql.gz | mysql herbology
        - zcat /tmp/potions.sql.gz | mysql potions

        # Clean up after ourselves to keep the Preview size small.
        - rm /tmp/*.sql.gz

Our Tugboat configuration for the MySQL service now creates each database, downloads the database dumps, imports them, and then cleans up the downloaded files to keep the disk usage down. We now have 4 different databases available for our 4 separate sites to make use of.

Tugboat Aliases: Multisite and More

If you’re using Drupal or WordPress multisite functionality, Tugboat’s aliases configuration is a great way to be able to test each of your sites. With it, you can get any number of unique URLs for a single preview. Combining that with a few additional database imports and configuration changes, and your Tugboat previews can test all the sites in your Drupal or WordPress multisite. What’s more, with Tugboat Enterprise, you can even run automated accessibility and SEO audits of different sites, by specifying different URLs for different aliases. Just think: every pull request testing every one of your sites. Contact us to learn more about the magic of Tugboat Enterprise. ✨🧙‍♂️