Migrating from Drupal 6 to Drupal 8

Migrating from Drupal 6 to Drupal 8

Photo by Phil Roeder

Photo by Phil Roeder and used under Creative Common 2.0 Attribution license.

Drupal 6 has reached the end of its life (EOL), leaving many Drupal 6 site owners wondering what to do with their sites.  "Upgrade to Drupal 8" is the most obvious choice, but upgrading from Drupal 6 to Drupal 8 can still be a bit tricky.

At the very least, the changes in technology and data structure made between Drupal 6 and Drupal 8 mean an upgrade requires rebuilding much of the front end of the site, which can be a big undertaking. That said, given the changes in the way people use the web between 2008, when Drupal 6 was released, and today, an overhaul making your site more social media and mobile friendly is often worthwhile in and of itself.

Migrate Drupal

Drupal 6 sites cannot directly be upgraded to Drupal 8, so what does the path forward look like? Drupal 8 includes support for migrating content from Drupal 6 to Drupal 8. It doesn't migrate everything, but it'll get you a long way down that path.

What gets migrated?

Content (nodes), users, taxonomy terms, files, image styles, input formats, url_aliases, and quite a bit of additional Drupal core configuation. The full list is here.

What doesn't get migrated?

Node references, term references, user references, locations, geofields, and other non-CCK custom fields, flags, views, block placements, and themes, among other things. Most anything non-standard. So it depends on the complexity of the Drupal 6 site in question and which of the available modules your previous site builder used as to how much of your content is likely to come over. 

The Migration Scenario

Here is a common Drupal 6 to Drupal 8 migration scenario, from the site owner's perspective:

I have a Drupal 6 site. I like it and generally want to keep it, but over the 7 years we've had it we've noticed a few things we'd like to fix. We have a few fields on a few content types we'd like to remove, another content type we'd like to split into multiple content types based on a taxonomy term, and we're tired of the slideshow on the homepage.

The Migration Process

I'm speaking with my developer hat on now, so this gets pretty technical. The approach I use here is based on what is described in this post about the nitty gritty details of migration and in other blog posts and documentation.

Assuming you've downloaded Drupal 8 and have drush 8 and Drupal Console installed, the general migration process looks like this:

  1. Set up the migration source site, including files, code, and database.
  2. Download and install the migrate_tools and migrate_plus modules in the new Drupal 8 target site modules directory.
  3. Enable the necessary migration modules. 

    $ drush en migrate migrate_tools migrate_plus migrate_drupal

  4. Add the migration source database to the sites/default/settings.php file of the target site.

    $databases['default']['default'] = array (
      'database' => 'mysite_d8',
      'username' => 'db_user',
      'password' => 'XXXXXX',
      'prefix' => '',
      'host' => 'localhost',
      'port' => '3306',
      'namespace' => 'Drupal\\Core\\Database\\Driver\\mysql',
      'driver' => 'mysql',
    $databases['migrate']['default'] = array (
      'database' => 'mysite_d6',
      'username' => 'db_user',
      'password' => 'XXXXXX',
      'prefix' => '',
      'host' => 'localhost',
      'port' => '3306',
      'namespace' => 'Drupal\\Core\\Database\\Driver\\mysql',
      'driver' => 'mysql',

  5. Initialize the migration with Drupal Console.

    $ drupal migrate:setup

    Note that when it asks for a file path, it is asking for the path to the root of the D6 site, not including sites/default/files. This path gets written into a couple of the migration YML files, migrate.migration.d6_file.yml and migrate.migration.d6_user_picture_file.yml. If you end up wanting to run the migration on a different machine with different pathing, you'll need to change the path there.

  6. Export your site's configuration to YML files.

    $ drush cex

  7. Create a custom module.

    $ drupal generate:module

  8. Move all of the exported YML files that begin with migrate.migration into a config/install directory inside of your new module.

  9. Edit the migration YML files to remove the database state key and add a migration group.

    Remove the line database_state_key: migrate_upgrade_6

    Add a line:  migration_group: mysite

  10. Add a YML file defining the migration group and named appropriately, like migrate_plus.migration_group.mysite.yml where "mysite" is replaced with the name of your migration group.

    id: mysite
    label: The MySite Migration
    description: Migrations from the Drupal 6 MySite site
    source_type: Drupal 6
        key: migrate

  11. Re-install the database for the Drupal 8 target site, enable all the modules that you'll need, and run the migration. Something like:

    $ drush site-install
    $ drush en migrate migrate_drupal migrate_plus migrate_tools redirect pathauto token ctools devel field_group field_group_migrate mysite_migration geolocation -y
    $ drush mi --all

If everything goes smoothly, at the end of this process you'll have a shiny new Drupal 8 site containing your old site's content.

Hey, wait! What about the fields I wanted to drop? Or the other changes I wanted make during the migration?

Remember all of those YML files you copied to your module?  Those describe what happens in the migration. You should see one YML file for each of the content types, as well as others for the terms, files, and fields.  

I'm not going to go into too much detail about customizing the migration; I'll save that for a follow up post. But I can point out a few things.

  • The Migrate API documentation is the place to get started. You need to kinda understand how Source, Process, and Destination plugins work before you'll be able to get too far in here.
  • Open up one of those YML files. Find the section that identifies the source plugin, which will looks something like:

      plugin: d6_term_node_revision

    You can then grep in the core directory for that plugin name, which will find you the source plugin that implements that particular migration.  You can modify the source plugin name in the YML file, change it to something like d6_my_custom_term_node_revision, then subclass the original source plugin, annotate it with your new ID, and then override whatever logic you need to.
  • You can remove a migration by removing the associated YML files. In my case, the site being migrated had disabled comments years ago but the database still contained over 2,000 spam comments. Removing the comments related YML files from the migration prevented all that garbage from being migrated unnecessarily. 

Neat! This approach will work in Drupal 8.1, right? I hear it is coming out soon.

Funny story about that.  Yes, Drupal 8.1 comes out in about two weeks. No, this approach won't work in 8.1.  Why? Those migration entity YML config files are gone. The documentation on this change is a bit light right now, but presumably a method of customizing Drupal 6 to Drupal 8 migrations will become available before too long.  

Stay tuned.