Skip to main content

Drupal 7 to Drupal 10 Migration: Your 2025 Step-by-Step DIY Guide

Denys Kravchenko profile picture
by
Macro picture of drop on a green leaf

Drupal 7's end-of-life has finally arrived, and if you're among those who've delayed the upgrade due to resource constraints or a complex codebase, this guide is here to help. Here's how you can navigate the transition to Drupal 10, ensuring your site remains secure and operational.

Define Clear Achievable Goals

As a business owner or developer, you're intimately familiar with your site's strengths and weaknesses. Start by listing what features are essential, those you can discard, and those that might need rethinking or simplification. Custom solutions from Drupal 7 might now be achievable with modern contrib modules, potentially simplifying your migration.

Audit of Content and Modules

If your site has evolved since Drupal 7's launch back in 2011, chances are you've accumulated some clutter. Take a good look at your Content Structure – think content types, blocks, entities – and spot any inefficiencies. You might want to consider restructuring your content in Drupal 10, taking advantage of the new features or just simplifying things. Use tools like Excalidraw to visually map out and streamline your content.


drush pm-list --type=Module --status=enabled --format=table
drush pm-list --type=Theme --status=enabled --format=table
    

Now having a list of all your modules and themes, you can check their status on Drupal Modules and Drupal Themes. If a module or theme isn't supported, identify its role in your site and look for modern alternatives in Drupal 10's contrib section.

Create Your Local Drupal 10 Environment

Here we're setting up a fresh Drupal 10 site. For this step, you'll need DDEV, Docker, or OrbStack and Composer installed on your local machine.

Setting Up the Project


# Create a new Drupal project using DDEV
ddev composer create drupal/recommended-project

# Configure DDEV for the Drupal project
ddev config --project-type=drupal --php-version=8.4 --docroot=web
ddev config --update
ddev start
    

Checking Installation Status

# Include Drush to your project
ddev composer require drush/drush

# Run drush status to see if the environment is installed correctly
ddev drush status    

This command will output something like:


Drupal version : 11.1.1
Site URI       : https://new-tobedeleted.ddev.site
DB driver      : mysql
DB hostname    : db
DB port        : 3306
DB username    : db
DB name        : db
PHP binary     : /usr/bin/php8.3
PHP config     : /etc/php/8.3/cli/php.ini
PHP OS         : Linux
PHP version    : 8.3.12
Drush script   : /var/www/html/vendor/bin/drush.php
Drush version  : 13.3.3.0
Drush temp     : /tmp
Drush configs  : /var/www/html/vendor/drush/drush/drush.yml
Drupal root    : /var/www/html/web
Site path      : sites/default
    

Installing Drupal


# Install your Drupal site
ddev drush site:install -y
    

Adding Contrib Modules and Themes: Now, we can install contrib modules and themes. Here's how:

  • First, check if the module or theme is compatible with Drupal 10 by visiting its project page on Drupal.org. Look for compatibility in the download section, for example, Works with Drupal: ^9.4 || ^10 || ^11.
  • Then, use Composer to add these to your project:

# Example of how to include contrib modules/themes
ddev composer require 'drupal/pathauto:^1.13'
ddev composer require 'drupal/webform:^6.2'
ddev composer require 'drupal/gin'
    

After installation, these modules should appear in the web/modules/contrib directory. To enable them:

# Enable pathauto and webform Modules
ddev drush pm:install pathauto webform
ddev drush theme:install gin -y

# Optional set admin theme with drush
ddev drush config-set system.theme admin gin
    

Now you can start creating your content structure through Drupal 10 UI. To access your local environment you will need to:


# Open Site in browser
ddev launch
# Login to Admin UI
ddev drush user:login
    

Custom Theme Setup

Once you've nailed down your content structure, the next step is customizing your site's functionality to fit your needs. Let's dive into setting up a new theme. When you decide to create a theme with support for Single-Directory Components (SDC), you'll first need to pick your base theme. If you're going with a child theme, ensure it's already installed on your system.


# Generate fresh theme
mkdir web/themes/custom
ddev drush generate theme
# Enable your new theme
ddev drush config-set system.theme default [your_theme_name]
# Using Single-Directory Components
ddev drush en sdc
ddev drush generate sdc
# if you follow the steps correctly
# new component should be generated
# in web/themes/custom/[your_theme_name]/components
    

With SDC, components are easily included or embedded in Twig templates using include or embed functions:


{% embed 'your_theme_name:your_component_name' with {
title: node.label,
subtitle: node.field_subtitle.value,
image: node.field_image.entity.uri.value|file_url
} %}
    

For those of you wrestling with HTML layouts, consider using Display Suite or Layout Builder. These modules simplify layout management within Drupal, reducing the need for custom coding:

  • Display Suite allows for complex layouts with minimal coding, offering direct control over display settings in Drupal.
  • Layout Builder provides a drag-and-drop interface to craft custom layouts for entities without writing code.
  • Single-Directory Components (SDC), when paired with tools like Storybook, offer a unique approach:
    • Component Isolation: You can work on components independently of the full Drupal setup, which is a game-changer for development.
    • Design Library: Maintain a living design system outside of Drupal, which is invaluable for consistency across different platforms or for design teams to reference.

I've been experimenting with this setup, and I must say, the process of iterating between design in Storybook and implementation in Drupal has been incredibly smooth.

Custom Module Setup

Now we are ready to migrate your custom functionalities. You can scaffold your module with the necessary structure and boilerplate code, adapting to Drupal 10's conventions by using these commands:

mkdir web/modules/custom
ddev drush generate module
## Scaffold your module with the necessary structure
## remember to include your custom module name
## Generate a Controller
ddev drush generate controller
## Generate a Configuration Form
ddev drush generate form:config
## Generate a Custom Service
ddev drush generate service
    

Transition actual custom code from Drupal 7 to Drupal 10. This might involve rewriting code due to changes in API and structure.

Migrating Drupal 7 to Drupal 10

Drupal 7

  1. Create a complete backup of your Drupal 7 site

ddev drush sql-dump > d7_database_backup.sql
tar -czf files_backup.tar.gz /path/to/d7/sites/default/files
    
  1. Install Required Migration Modules

ddev composer require drupal/migrate_plus drupal/migrate_tools drupal/migrate_upgrade
ddev drush pm:install migrate_plus migrate_tools migrate_upgrade -y
    
  1. Import to new database to the same MYSQL environment with the Drupal 10 database

# Import your Drupal 7 database into a new database that Drupal 10 can access
mysql -u root -p d7_source < d7_database_backup.sql
# Use Drush to set up the migration process.
ddev drush migrate:upgrade --configure-only --db-url=mysql://db_user:db_pass@db_host/d7_source
# Check the available migrations and their statuses
ddev drush migrate:status
# Run the migration for all configured groups
ddev drush migrate:import --all
# Run the migration for specific id
ddev drush migrate:import [migration-id]
# Run the migration for specific Group
ddev drush migrate:import --group=[group-name]
# Reverses the changes made by a specific migration. This will remove the content or data imported by the migration.
ddev drush migrate:rollback [migration-id]
# Resets the status of a migration to idle. Use this when a migration is stuck in an "in-progress" or "failed" state
ddev drush migrate:reset-status [migration-id]
# Stops an ongoing migration process. This is useful if a migration is taking too long or causing server issues.

Your Drupal 10

If everything went smoothly, you should now have a new Drupal 10 website ready to go live. When working in a team, using Git with specific branches for features and main code is crucial to avoid workflow blockages. Here's how to manage this

Content Structure & Style

  • Main Branch: This should be your stable, production-ready code. Only merge well-tested features here.
  • Feature Branches: Use these for new features or bug fixes. Name them descriptively, like feature/new-login-system or bugfix/fix-login-issue.
  • Syncing Config Files: Regularly syncing your configuration files can help prevent merge conflicts. Here’s how:

# Export Drupal configuration to a directory.
ddev drush config:export
# Import config from the config directory. 
ddev drush config:import

To successfully install and import configurations, ensure your settings.php includes the config directory


$settings['config_sync_directory'] = dirname(DRUPAL_ROOT) . '/config/sync';
    

# create config directory in you project root
mkdir -p config/sync 

Performance Tuning Post-Migration

After migration, performance tuning might be necessary, especially with complex configurations. Here are some tools that can help


ddev composer require drupal/devel drupal/webprofiler 
ddev drush pm:install devel webprofiler

Need Help with Your Drupal Project?

Navigating Drupal's complexities can be challenging, whether you're setting up new branches, syncing configurations, or optimizing performance. If you're looking for expert guidance or need a team to take your Drupal 10 project to the next level, we're here to help.