Setup an existing WordPress multisite locally with DDEV (with Bonus Pantheon support!)
Share
Creating a local WordPress multisite environment can be complex, especially when handling subdirectory configurations. This guide provides a step-by-step process for setting up a local multisite installation using DDEV, a popular tool that simplifies development by offering a containerized environment. By focusing on subdirectory installations, DDEV’s Apache configuration optimizes handling of local multisite environments, making it easier to manage complex setups. Additionally, Pantheon integration is covered, allowing developers to pull production data and files seamlessly, ensuring a streamlined workflow from live production to local development.
This guide is intended for an intermediate to advanced WordPress developer hoping to improve their workflow for local development.
The power of DDEV for multisite development
DDEV simplifies the complexities of WordPress multisite development by providing a containerized environment that's easy to set up and maintain. Its Apache configuration handles subdirectory installations smoothly, and built-in tools make database management and file synchronization straightforward. With DDEV's Pantheon integration, developers can efficiently pull production data and files, making local development and testing seamless.
Understanding WordPress multisite installation types
A WordPress multisite can be configured in two distinct ways:
- Subdirectories
- Subdomains
In a subdirectory setup, additional sites appear as extensions of your main URL (e.g., example.com/site2), making it ideal for closely-related content or internal organizational networks. Subdomain installations, on the other hand, create separate subdomains for each site (e.g., site2.example.com), which can be better for distinct branded experiences or separate user communities.
This guide focuses on the subdirectory approach.
⚠️ Important: The installation type must be configured during the initial network setup and cannot be changed later without manual database modifications and potential content updates.
Setting up a local WordPress multisite with subdirectories using DDEV
Setting up a local WordPress multisite environment can be challenging, especially when dealing with subdirectory installs. In this guide, we'll walk through the process of setting up a full local multisite installation supporting subdirectories using DDEV, with a focus on Pantheon integration.
👉 This guide assumes that you already have a WordPress multisite project set up on live and are looking to create a local development environment for it. If you need to set up a new WordPress multisite project, follow the WordPress Codex guide.
Prerequisites
- DDEV installed on your local machine
- Git
- Drush (Optional, for Pantheon integration). To get it, run
ddev composer require drush/drush - Most importantly, the ability to endure pain if things go wrong 😅
Let's get started!
Configure DDEV
Clone the repository
First, clone your project repository to your local machine:
git clone [your-repo-url]
cd [your-project-directory]Run the DDEV configuration command:
ddev configand answer the prompts.
Modify DDEV configuration
In the .ddev/config.yaml file, change the webserver type to Apache:
webserver_type: apache-fpmWe are moving to Apache because handling subdirectory installs is much easier with .htaccess compared to Nginx; at least, I did not have a good time with it when I was playing with the nginx-site.conf file auto-generated by DDEV. 🤦♂️
A similar issue was logged on DDEV’s repo. I just had a better time with Apache in this instance, and since we are not mimicking any production server environment that is purely Nginx-based, Apache sounds fine here.
Create .htaccess File
Create a .htaccess file in the root of your project and add it to .gitignore. Paste the following content into the file:
# BEGIN WordPress
RewriteEngine On
RewriteBase /
RewriteRule ^index\.php$ - [L]
# add a trailing slash to /wp-admin
RewriteRule ^([_0-9a-zA-Z-]+/)?wp-admin$ $1wp-admin/ [R=301,L]
RewriteCond %{REQUEST_FILENAME} -f [OR]
RewriteCond %{REQUEST_FILENAME} -d
RewriteRule ^ - [L]
RewriteRule ^([_0-9a-zA-Z-]+/)?(wp-(content|admin|includes).*) $2 [L]
RewriteRule ^([_0-9a-zA-Z-]+/)?(.*\.php)$ $2 [L]
RewriteRule . index.php [L]
# END WordPressI have directly copied the content of the .htaccess file from the WordPress MultiSite Network Administration docs for WordPress version 3.5 and higher.
⚠️ Important: Note where it adds a trailing slash to the wp-admin in .htaccess. If we don’t do this, the subdirectories as well as their wp admin will not load!
Configure WordPress
Since we're using Pantheon and it already supports a wp-config-local.php, we'll use it to reserve wp-config.php for Pantheon-specific settings. It is possible to add our edits directly and conditionally to that part, but it is more comfortable to use wp-config-local.php for clarity.
- Add
wp-config-ddev.phpto.gitignore. - Remove any database connection settings from
wp-config-local.php. - Add the following to the bottom of
wp-config-local.php:
// Include for ddev-managed settings in wp-config-ddev.php.
$ddev_settings = dirname(__FILE__) . '/wp-config-ddev.php';
if (is_readable($ddev_settings) && !defined('DB_USER')) {
require_once($ddev_settings);
}If we were not using Pantheon wordpress_network upstream and the default wp-config.php that comes with it, or if we were setting up the multisite from scratch, we would have added the following to the bottom of wp-config-local.php (since the wp-config-ddv.php file is auto-generated by DDEV and we have less control over it):
define('WP_ALLOW_MULTISITE', true);
define('MULTISITE', true);
define('SUBDOMAIN_INSTALL', false);
define('DOMAIN_CURRENT_SITE', 'yoursite.ddev.site');
define('PATH_CURRENT_SITE', '/');
define('SITE_ID_CURRENT_SITE', 1);
define('BLOG_ID_CURRENT_SITE', 1);⚠️ Important: Most of the time (if not all the time!) you would be experiencing login problems, such as the inability to log in due to the cookie issues. From here, you need to play with the cookie settings in wp-config-local.php, for example trying to set define( 'COOKIE_DOMAIN', 'your-local-ddev-site.ddev.site' ), which in most cases you would see the warning about the constant being already defined in wp-config.php. Then simply set these in wp-config-local.php:
define( 'ADMIN_COOKIE_PATH', '/' );
define( 'COOKIEPATH', '' );
define( 'SITECOOKIEPATH', '' );Optional Pantheon integration
If you don't need Pantheon integration, you can skip this section and move to the Pull database and files section.
Follow the Pantheon integration guide for DDEV:
⚠️ Important: Make sure that you follow the Pantheon guide for Drush and the machine token, otherwise none of this is going to work.
Pull Pantheon data
Pull the database from Pantheon (I am skipping files and only pulling the database because I am not interested in the files, but you can pull them as well if you want):
ddev pull pantheon --skip-files -yIf you want to pull the files as well, you can run the following command:
ddev pull pantheon -yNote: See the section below for an alternative method to pull the files.
Terminus
If you are using Terminus, you can use the following command to pull the database:
terminus backup:create [site].[env] --element=db
terminus backup:get [site].[env] --element=db --to=database.sql.gzSee the Terminus documentation for more information.
Database and files
Export the database from live site
Export your database with whatever tool that your hosting provider provides, or if you use a plugin like WP Migrate DB, you can use that as well.
Import database
Import the database into your local environment:
ddev import-db --file=path_to_dumpfile.sql.gzDDEV has pretty straightforward documentation about this.
Files
Using command line tools, sftp client, or any other method you prefer, copy the files from your live site to the wp-content/uploads directory in your local environment.
I usually use Bill Erickson's Media From Production to read media files from the live site and save myself a couple of GBs of storage. This plugin is a real gem!
Update URLs and paths
After pulling the database from Pantheon, you need to update the URLs and paths to match your local environment. Use the wp search-replace command:
ddev wp search-replace 'live-yoursite.pantheonsite.io' 'yoursite.ddev.site'Replace live-yoursite.pantheonsite.io with your actual Pantheon live URL, and yoursite.ddev.site with your local DDEV URL. Note that you may also need to specifically target the wp_options table, wp_blogs, and wp_sites as well, otherwise, you may be seeing redirections from your local to the live site when you attempt to browse your network sites locally. So:
ddev wp search-replace 'live-yoursite.pantheonsite.io' 'yoursite.ddev.site' 'wp_*options' wp_blogs wp_site --network⚠️ Important: Note the * before wp_options which means the options tables for all the sites in the network.
Create/edit WordPress user
Create a new WordPress user:
ddev wp user create your_username_here your_email_here --role=administrator --user_pass=yourpasswordUpdate the new WordPress user’s role:
ddev wp user update the_id_of_the_user_here --role=administratorAdd super admin
Make your user a super admin, because otherwise you will not be able to access the network admin area:
ddev wp super-admin add your_username_hereConclusion
By following these steps, you'll have a fully functional local WordPress multisite environment set up with DDEV, supporting subdirectory installs and integrated with Pantheon. This setup provides a robust development environment for working on WordPress multisite projects.
The wp search-replace command is crucial for ensuring that your local site works correctly with the database pulled from the live version.