Importing a WordPress site into Multisite with WP-CLI

In this tutorial I’m going to show you how to completely import an existing WordPress site into an existing WordPress multisite installation. There are already some great tutorials out there that cover this topic, but I couldn’t find any that covered using the great WP-CLI tool.

We’ll have to use a couple of plugins too, but that’s mostly because WordPress multisite is weird about how it handles users.

If you’re not familiar with WP-CLI, it’s a fantastic tool that lets you perform all kinds of actions with your WordPress site straight from the command line, like updating plugins/themes, exporting/importing database tables, and way more.

Warning!

Always make a backup first! If you don’t know how to both create and restore backups of your WordPress site, you should not be following this tutorial! I am not responsible if these instructions cause any problems with your site! Exclamation points!!!

My Motivation

Feel free to skip this section, because do you really care why I wanted to do this?

I run a few WordPress sites out of a shared hosting account, including the one you’re reading right now. As I’ve added more sites, I’ve found myself setting up the same things over and over again, like creating the same users and installing the same plugins.

For example, I recently set up the fantastic Wordfence security plugin on all of my sites. Wordfence has a ton of settings, and I want them to be the same on all my sites so they’re all equally secure. Even though it has a nice import/export feature, I’d much rather configure it once for my multisite installation and be done with it. If I need to make a change, I can do it in one place.

I’m also a cheapass, and my current cheap hosting plan doesn’t come with much storage. I’ll be able to cut down how much I’m using if I don’t have the same exact plugin files in 10 separate WordPress instances.

I just set up my own multisite installation, and still need to transfer this site into it, so I’ll be writing this tutorial as I perform the process and document everything you need to know.

Prerequisites / Assumptions / Requirements

This tutorial is not for everyone, and won’t even be possible on many hosting accounts because you will need shell access. Here are some requirements:

  • The individual WordPress site you want to import should be publicly accessible (this ensures the media transfer works)
  • An existing WordPress multisite installation
  • Shell access to where both sites are located (in my case it’s the same server), and the ability to install WP-CLI on it
  • Willingness to do work on the command line

Alright Let’s Do It

Copy over any plugins/themes not already in the multisite

It’s important to make sure you have all the same plugins and themes in the multisite that you’re currently using on the site you’re importing. These can be pretty easily installed with WP-CLI or copied over from the command line.

You will need to perform all of these steps on your host where the WordPress site and multisite exist. I’m assuming both are on the same server. I’ll use /path/to/wordpress to mean the absolute path on the server to your single WordPress installation (where wp-config.php lives, and /path/to/multisite to mean the absolute path to the multisite installation.

The first thing I did was check to see which plugins were on this site that weren’t already in the multisite. I’m sure there’s a better way to do it, but I used the diff command:

diff /path/to/wordpress/wp-content/plugins/ /path/to/multisite/wp-content/plugins/ | grep "Only in" | sort

Piping the output into grep and only matching lines that include “Only in” shows me just the plugins that exist in one directory but not the other, for example:


Only in /path/to/wordpress/wp-content/plugins/: jetpack

For each of these, I’ll install it in the multisite using WP-CLI. You could also manually copy them over, like if you need specific versions of the plugins or you’re using a plugin that isn’t available from wordpress.org, but please always use the latest version of plugins. You’ll be happy when your site isn’t hacked.


cd /path/to/multisite
wp plugin install jetpack

or you can copy them manually


cp -r /path/to/wordpress/wp-content/plugins/jetpack /path/to/multisite/wp-content/plugins

Follow these same instructions for the themes by using themes instead of plugins. It should be exactly the same so I won’t bore you with the details.

Create a new multisite

In the Network Admin in your multisite installation, create a new site:

Navigate to Sites > Add New

Then fill out the basic site information. My multisite is using a subfolder setup, but this will eventually be replaced by the actual domain.

After creating the new site, you should see a site ID in the URL that looks something like this:

Remember this id for later.

The new multisite will come with an example post and page. Make sure to trash those before moving on, unless you really want an additional “Sample Page” on the multisite version of the site.

Export your wp_options table

We’re going to be bringing over everything from the wp_options table to the multisite, so let’s export it. We can do this with the wp db export command:


wp db export ~/wordpress_options.sql --tables=wp_options

Note: I’m putting the export in my home directory (~/ is a shortcut to your home directory if you didn’t know) because otherwise it would be possible for anyone to download the file if they knew the filename.

Note2: if you have a different prefix than wp_, you’ll need to use that to specify the table. For example, mine was wp0a_, so I had to specify --tables=wp0a_options. For this tutorial I’ll assume the prefix for both your primary site and multisite are wp_. Your table prefix is defined in wp-config.php as the $table_prefix variable.

Note3: This step assumes you don’t have any non-standard tables in your database (like custom tables from a plugin). If you do, you might want to include them in this export as well, but that’s outside the scope of this tutorial.

Update the export to use the correct prefix

The database export will include a lot of references to wp_, like the names for tables to drop and recreate. We want to import this data into the correct multisite wp_options table, so we’ll need to do some find/replace.

The new table in the multisite uses the format prefix_siteId_ where prefix is the $table_prefix mentioned before (probably wp_, and siteId is the id from earlier (in my case it’s 3).

The find/replace itself can be done using the sed command:


sed -i 's/wp_/wp_3_/g' ~/wordpress_options.sql

This replaces all instances of wp_ with wp_3_. The -i option modifies the file itself (instead of outputting the new file to standard out), and the g at the end is what indicates it should replace all instances and not just the first.

Exporting and importing site content using plugins (boo)

This is where we’ll need to use plugins. If you know of a non-plugin way to do this, please let me know!

First, install the WordPress importer plugin in your multisite. You can install and network activate the plugin in a single WP-CLI command.


cd /path/to/multisite
wp plugin install wordpress-importer --activate-network

Back on your single site, use the exporter tool in the dashboard, and make sure to select All content.

Back in your multisite, in the dashboard of the new site you created, run the importer. Go to Tools > Import, scroll down to WordPress, and click Run Importer.

On the next page, select the XML file you got from your single WordPress instance and click the Upload file and import button.

On the next page you will be asked which user should be assigned the content that’s being imported. You can either use an existing user or create a new one.

Make sure to check the Download and import file attachments checkbox! If you don’t you won’t get any of your images or other uploads. The original site must be publicly accessible for this to work (e.g. this won’t work if your single WordPress install is running locally on MAMP or similar).


Note: if you have even a moderate amount of content on your site, the WordPress importer might fail without giving you any kind of error message. You might just see a grey screen instead of a success message after starting the import. This happened to me when transferring this site. I believe this is due to a PHP timeout (the default setting is usually to time out if a process has been running for more than 30 seconds).

I got around this by transferring the XML file to my host and then using a WP-CLI command to process the import:


wp import /path/to/my/xml/sitebackup.xml --url=http://multisiteurl.com/johnoleksowicz --authors=mapping.csv

Because this is happening on the command line, there’s no UI to select which user should be assigned which content. I told WP-CLI to use a file named mapping.csv. It didn’t exist before, so it created it for me. Learn more about the exact format to use at the WP-CLI documentation for wp import.

My import failed after processing about half of the items, but when I ran the same command again it picked up where it left off and completed the import. Hurray!


If you have any widgets on your original site, which you probably do, you’ll want to transfer those as well. This is also easiest to do with a plugin. You’ll need to install and activate the widget settings importer/exporter on both the single and multisite version of the site:


cd /path/to/wordpress
wp plugin install widget-settings-importexport --activate

cd /path/to/multisite
wp plugin install widget-settings-importexport --activate-network

On the original site, go to Tools > Widget Settings Export and follow the directions. You’ll end up with a widget_data.json file that you should import on the multisite version of the site using Tools > Widget Settings Import.

Import your options

Now it’s finally time to import the options we exported a number of steps ago. It’s best to do this at this point instead of earlier so you can still easily access the multisite version of the site. The options table will have the old URL for your site, so when you try to visit the dashboard or view the site you’ll just get redirected to your standalone WordPress site.

In my case I wanted the URL to remain johnoleksowicz.com, so this was fine for me. Your needs might be different if you wanted to move to something like johnsmultisites.com/johnoleksowicz or johnoleksowicz.johnsmultisites.com.

Importing the database export is very straightforward with WP-CLI:


cd /path/to/multisite
wp db import ~/wordpress_options.sql

Take care of some finding/replacing

When I completed my migration, I noticed there were still some instances of the original multisite URL in my database. WP-CLI gives you a handy way of taking care of this with its search-replace command. My original multisite URL was something like multisite.example.com/johnoleksowicz, so I ran this command:


wp search-replace multisite.example.com/johnoleksowicz johnoleksowicz.com --url=johnoleksowicz.com --verbose

You can add the --dry-run option if you want to see how many changes would be made and where without actually making the changes.

Update your domain mapping

If you’re like me and are using a custom domain like johnoleksowicz.com instead of using subdomains or subdirectories for your multisite, now is the time to head over to your site settings in the Network Admin and update the site you created to have the URL you want, in my case https://johnoleksowicz.com/ (make sure to include the http://).

Then you’ll need to make sure to update the document root for that domain in your hosting. It will need to point to /path/to/multisite instead of /path/to/wordpress. This will be different depending on your hosting so I won’t go into details here.

That Should Be It!

I’m sure this tutorial isn’t exhaustive, but it’s what worked for me!

Let me know in the comments if you have any suggestions for how to make this process better or easier.

Leave a Comment