Drupal 9

Wondering how to configure Tugboat for a typical Drupal 9 repository? Every Drupal site tends to have slightly different requirements, so you may need to do more customizing, but this should get you started.

The following documentation assumes you are using Composer to manage your Drupal 9 project (typically with either the drupal/recommended-project or the drupal-composer/drupal-project projects).

Configure Drupal

A common practice for managing Drupal’s settings.php is to leave sensitive information, such as database credentials, out of it and commit it to git. Then, the sensitive information is loaded from a settings.local.php file that exists only on the Drupal installation location.

This pattern works very well with Tugboat. It lets you keep a Tugboat-specific set of configurations in your repository, where you can copy it into place with a configuration file command.

Add or uncomment the following at the end of settings.php

if (file_exists($app_root . '/' . $site_path . '/settings.local.php')) {
  include $app_root . '/' . $site_path . '/settings.local.php';
}

Add a file to the git repository at .tugboat/settings.local.php with the following content:

<?php
$databases['default']['default'] = array (
  'database' => 'tugboat',
  'username' => 'tugboat',
  'password' => 'tugboat',
  'prefix' => '',
  'host' => 'mysql',
  'port' => '3306',
  'namespace' => 'Drupal\\Core\\Database\\Driver\\mysql',
  'driver' => 'mysql',
);

// Use the TUGBOAT_REPO_ID to generate a hash salt for Tugboat sites.
$settings['hash_salt'] = hash('sha256', getenv('TUGBOAT_REPO_ID'));

// If your Drupal config directory is outside of the Drupal web root, it's
// recommended to uncomment and adapt the following. Note: the TUGBOAT_ROOT
// environment variable is equivalent to the git repo root.
# $settings['config_sync_directory'] = getenv('TUGBOAT_ROOT') . '/config';

// If you are using private files, and that directory is outside of the Drupal
// web root, it's recommended to uncomment and adapt the following. Note: the
// TUGBOAT_ROOT environment variable is equivalent to the git repo root.
# $settings['file_private_path'] = getenv('TUGBOAT_ROOT') . '/files-private';

Configure Tugboat

The Tugboat configuration is managed by a YAML file at .tugboat/config.yml in the git repository. Here’s a basic Drupal 9 configuration you can use as a starting point, with comments to explain what’s going on:

services:
  # What to call the service hosting the site.
  php:
    # This uses PHP 8.1.x with Apache: update to match your version of PHP
    image: tugboatqa/php:8.1-apache

    # Set this as the default service. This does a few things
    #   1. Clones the git repository into the service container
    #   2. Exposes port 80 to the Tugboat HTTP proxy
    #   3. Routes requests to the preview URL to this service
    default: true

    # Wait until the mysql service is done building
    depends: mysql

    # A set of commands to run while building this service
    commands:
      # Commands that set up the basic preview infrastructure
      init:
        # Install opcache and mod-rewrite.
        - docker-php-ext-install opcache
        - a2enmod headers rewrite

        # Link the document root to the expected path. This example links /web
        # to the docroot.
        - ln -snf "${TUGBOAT_ROOT}/web" "${DOCROOT}"

        # Create the Drupal private and public files directories if they aren't
        # already present.
        - mkdir -p "${TUGBOAT_ROOT}/files-private" "${DOCROOT}/sites/default/files"

      # Commands that import files, databases,  or other assets. When an
      # existing preview is refreshed, the build workflow starts here,
      # skipping the init step, because the results of that step will
      # already be present.
      update:
        # Use the tugboat-specific Drupal settings.
        - cp "${TUGBOAT_ROOT}/.tugboat/settings.local.php" "${DOCROOT}/sites/default/"

        # Install/update packages managed by composer, including drush.
        - composer install --optimize-autoloader

        # Copy Drupal's public files directory from an external server. The
        # public SSH key found in the Tugboat Repository configuration must be
        # copied to the external server in order to use rsync over SSH.
        - rsync -av --delete user@example.com:/path/to/files/ "${DOCROOT}/sites/default/files/"

        # Alternatively, another common practice is to use the
        # stage_file_proxy Drupal module. This module lets Drupal serve
        # files from another publicly-accessible Drupal site instead of
        # syncing the entire files directory into the Tugboat Preview.
        # This results in smaller previews and reduces the build time.
        - composer require --dev drupal/stage_file_proxy
        - vendor/bin/drush pm:enable --yes stage_file_proxy
        - vendor/bin/drush config:set --yes stage_file_proxy.settings origin "http://www.example.com"

        # Set file permissions such that Drupal will not complain.
        - chgrp -R www-data "${DOCROOT}/sites/default/files"
        - find "${DOCROOT}/sites/default/files" -type d -exec chmod 2775 {} \;
        - find "${DOCROOT}/sites/default/files" -type f -exec chmod 0664 {} \;

      # Commands that build the site. This is where you would add things
      # like feature reverts or any other drush commands required to
      # set up or configure the site. When a preview is built from a
      # base preview, the build workflow starts here, skipping the init
      # and update steps, because the results of those are inherited
      # from the base preview.
      build:
        - composer install --optimize-autoloader
        - vendor/bin/drush cache:rebuild
        - vendor/bin/drush config:import -y
        - vendor/bin/drush updatedb -y
        - vendor/bin/drush cache:rebuild

  # This 'mysql' key acts as the hostname to access the service by from the php service.
  mysql:
    # Use the latest available 5.x version of MySQL
    image: tugboatqa/mariadb:10.5

    # A set of commands to run while building this service
    commands:
      # Commands that import files, databases,  or other assets. When an
      # existing preview is refreshed, the build workflow starts here,
      # skipping the init step, because the results of that step will
      # already be present.
      update:
        # Copy a database dump from an external server. The public
        # SSH key found in the Tugboat Repository configuration must be
        # copied to the external server in order to use scp.
        - scp user@example.com:database.sql.gz /tmp/database.sql.gz
        - zcat /tmp/database.sql.gz | mysql tugboat
        - rm /tmp/database.sql.gz

Want to know more about something mentioned in the comments of this config file? Check out these topics:

Start Building Previews!

Once the Tugboat configuration file is committed to your git repository, you can start building previews!