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.