Changing install profiles in Drupal 8

Aaron Bauman
Behind the Scenes

As we put some polish on our Drupal 8 install profile, we're already in a position of technical debt: we've already launched Drupal 8 sites using the Drupal "standard" profile. Unless we update those sites to use our new D8 profile, they'll miss out on the benefits of our continuous deployment stack. There are plenty of resources for switching Drupal 7 site profiles, but what's the analogous process in Drupal 8?

The solution boils down to a relatively simple hook_update and a tweak in settings.php:

function message_agency_update_8001() {
$profile_name = "message_agency";
Drupal::keyValue('system.schema')->set($profile_name, 8000);
$extension_config = \Drupal::configFactory()->getEditable('core.extension');
$modules = $extension_config->get('module');
$modules[$profile_name] = 1;
$extension_config->set('module', $modules);
$extension_config->save(); drupal_flush_all_caches();

And appending a line to our settings.php, so that Drupal can find the modules and themes in our profile:

['install_profile'] = 'message_agency';

Investigating this question also gave us a chance to explore how some of Drupal's core assumptions have changed.

Drupal 8 does away with "system" database tables. Module status is now split between config variables (Configuration Management Initiative or CMI), core.extension, and key-value stores (State API), system.schema.


This config maintains a list of enabled modules—previously "status" column in system table—in a giant array.


This key store, as its name implied, keeps track of module schema versions. Each key-value entry is a module name, and its value is the schema version.

Why go through all this trouble? The more important component here is purging modules from our Drupal 8 site installs, where those modules are included in our profile. To accomplish this, we use diff's ability to compare directory listings to generate our comparison:

    > diff modules/contrib/ profiles/message_agency/modules/contrib/ | sort
    Common subdirectories: modules/contrib/menu_block and profiles/message_agency/modules/contrib/menu_block
    Common subdirectories: modules/contrib/responsive_tables_filter and profiles/message_agency/modules/contrib/responsive_tables_filter
    Only in modules/contrib/: gathercontent Only in modules/contrib/: view_unpublished
    Only in profiles/message_agency/modules/contrib/: admin_toolbar
    Only in profiles/message_agency/modules/contrib/: block_access

For each line beginning "Common subdirectories", we string together some command line tools to to remove the now-duplicate version:

diff modules/contrib/ profiles/message_agency/modules/contrib/ | grep "Common subdirectories:" | awk {'print $3'} | xargs git rm -r

Running our update hook with drush updb will address the final, critical piece of the puzzle. State key store system.module.files caches file paths for module info.yml files, which will be rebuilt by drupal_flush_all_caches(). It's important to note that we (probably) can't simply use drush cr, since drush will fail to perform a full bootstrap. Instead, drush updb will attempt a minimal bootstrap, preventing errors related to missing module files. (If this bootstrap is too much for your modules, you'll have to resort to a drush script to manually edit file paths in system.module.files.)

More Blog Posts

  • Design Basics


    Discovery is the phase of the project that takes place before design. Discovery means different things to different agencies and is often misunderstood by clients. So what is it good for?

  • Behind the Scenes

    After several months, hundreds of commits, and lots of new thinking, we’re happy to announce that a release candidate is now available for the Salesforce Suite in Drupal 8. It’s big news for adoption.

  • In the Community
    Watch Aaron Bauman's presentation "Updating Your Modules to Drupal 8: Salesforce Suite," delivered at DrupalCamp NJ 2017!