...
👉 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, you can follow the WordPress Codex guide.
Prerequisites
DDEV installed on your local machine
Drush (Optional, for Pantheon integration), to get it, run
ddev composer require drush/drush
Ability to endure pain if things go wrong 😅 (believe me they will)
...
Create a .htaccess
file in the root of your project and add it to .gitignore
. Paste the following content into the file:
Code Block | ||
---|---|---|
| ||
# 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 WordPress |
I have directly copied the content of .htaccess
file from the WordPress MultiSite Netword Network Administration docs for WordPRess WordPress version 3.5 and higher.
⚠️ Important: Note line 7 in .htaccess
where it adds a trailing slash to the wp-admin. If we don’t do this, the subdirectories as well as their wp admin will not load!
Configure WordPress
Since we're using Pantheon, we'll use wp-config-local.php
instead of wp-config.php
:
Add
wp-config-ddev.php
to.gitignore
.Remove any database connection settings from
wp-config-local.php
.Add the following to the bottom of
wp-config-local.php
:
Code Block | ||
---|---|---|
| ||
// 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):
Code Block | ||
---|---|---|
| ||
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:447' );
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
:
Code Block | ||
---|---|---|
| ||
define( 'ADMIN_COOKIE_PATH', '/' );
define( 'COOKIEPATH', '' );
define( 'SITECOOKIEPATH', '' ); |
Optional Pantheon Integration
...
⚠️ Important: Make sure that you follow pantheon guide for Drush and the machine token otherwise non none of this is going to work.
...
Pull the database from Pantheon ( I am skipping files and only pull pulling the database because I am not interested in the files, but you can pull the files them as well if you want):
Code Block | ||
---|---|---|
| ||
ddev wp pull pantheon --skip-files -y |
but if you insist on pulling If you want to pull the files as well, you can run the following command:
Code Block | ||
---|---|---|
| ||
ddev pull pantheon -y |
Note: 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:
...
Code Block | ||
---|---|---|
| ||
ddev import-db --file=path_to_dumpfile.sql.gz |
DDEV has a pretty straightforward documentation about this.
...
Using the command line tools, sftp client, or any other method, copy the files from your live site to the wp-content/uploads directory in your local environment.
for files, 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. The plugin is a real gem!
...
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:
Code Block | ||
---|---|---|
| ||
ddev wp search-replace 'live-yoursite.pantheonsite.io' 'yoursite.ddev.site' |
Replace '<live-yoursite.pantheonsite.io
>' with your actual Pantheon live URL, and '<yoursiteyoursite.ddev.
site>'site
with your local DDEV URL. Note that you may sometimes need to run this command multiple times to ensure that all URLs and paths are updated correctly. 🤞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:
Code Block |
---|
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
...
Code Block | ||
---|---|---|
| ||
ddev wp user create your_username_here your_email_here --role=administrator --user_pass=yourpassword |
Update a wordpress user the new WordPress user’s role:
Code Block | ||
---|---|---|
| ||
ddev wp user update the_id_of_the_user_here --role=administrator |
...
Make your user a super admin, because if you are not already, otherwise you will not be able to access the network admin area:
...
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.