WordPress multisite migration checklist
The purpose of these instructions is to catalog all of the quarks that come up when manually moving a website in/out of WordPress multisite. For our example we'll be transferring a single subsite from one multisite to another multisite.
Backup
The idea is simple. We need to grab a backup of the database and files. With multisite this gets a bit more involved then a typically single site migration.
Database
Inside a multisite database we'll want to be very selective. If we grab everything we'll end up with a copy of the whole network, not just the single subsite. A subsite will store most of it's information under the tables named wp_[Site ID]_[Table Name]. We'll start by doing an SQL dump of those tables using <a href="http://www.sequelpro.com/">Sequel Pro</a>. Select the tables (shift click for multiple select) which match the site ID of the subsite we wish to move.
Save a dump of the SQL in folder with the name of the website. We'll put the rest of the backup in this folder.
Take note of the current users on the subsite. Login as an admin to your subsite and click on users. I like to take a screenshot for reference sake like so.
Make a selective backup of just those users from the wp_users table. In Sequel Pro select wp_users table then select the proper users while holding the command key. Then right click and select "Copy as SQL Insert"
Open up Sublime Text 2 or your editor of choice and paste the SQL into a new file. Now replace the ID columns with null. This will allow the SQL to auto-generate a new ID wherever we are move the users to. In the first line remove ", spam
, deleted
". These columns are multisite specific and have can cause problems during the restore process. In addtional to the column removals we'll need to remove the data on those columns. Remove ", 0, 0" from each of the user lines. Here is the before:
INSERT INTO `wp_users` (`ID`, `user_login`, `user_pass`, `user_nicename`, `user_email`, `user_url`, `user_registered`, `user_activation_key`, `user_status`, `display_name`, `spam`, `deleted`)
VALUES
(1, 'anchordev', 'PASSWORDHASH', 'anchordev', 'support@anchordev.com', '', '2012-06-16 01:53:01', '', 0, 'anchordev', 0, 0),
(3, 'austinginder', 'PASSWORDHASH', 'austinginder', 'austinginder@gmail.com', '', '2012-07-25 13:57:39', '', 0, 'austinginder', 0, 0);
and after:
INSERT INTO `wp_users` (`ID`, `user_login`, `user_pass`, `user_nicename`, `user_email`, `user_url`, `user_registered`, `user_activation_key`, `user_status`, `display_name`)
VALUES
(null, 'anchordev', 'PASSWORDHASH', 'anchordev', 'support@anchordev.com', '', '2012-06-16 01:53:01', '', 0, 'anchordev'),
(null, 'austinginder', 'PASSWORDHASH', 'austinginder', 'austinginder@gmail.com', '', '2012-07-25 13:57:39', '', 0, 'austinginder');
Name the file users.sql and store it our backup folder.
Files
When moving a subsite I like to take a screenshot of the current theme and active plugins. This allows me to only import the files I'll need instead off everything on the multisite.
Connect to the website over FTP and download the appropriate plugins and themes. Save them in your backup folder.
Download the uploads folder for the subsite. The folder location will vary depending on the setup of the multisite. Typically it's located under "/wp-content/blogs.dir/[site ID]/files/" or "/wp-content/uploads/sites/[site ID]/". If you have problems finding it, check out the wp_[site ID]_options table. The option_name.upload_path should show the custom location.
Copy the contents of the folder into the an uploads folder and put it in the backup folder. Now you have a full backup.
Restore
The restoration process will require a good amount of preparation. It's important you follow along closely or you could damage the multisite network you are restoring into.
Database
Login as a super admin user on the new Multisite. Go ahead and setup a new subsite (Sites > New Site). You can use anything for site address as that will be changing once you import old data. Take note of the new site ID. In my example it will be 87. Now that we have this new site ID open the main sql export from the backup in Sublime Text 2. Do a find and replace for `wp_[old site ID]_ and replace with `wp_[new site ID]_. Click on replace all.
I like to include the leading ` to target only the SQL commands. The comments are not important.
Do a find for _user_roles. Make sure to change the site ID to the new one. This is important or the user roles will be missing on the imported website.
Save and close the SQL file. Open the users.sql file and connect to the new multisite over Sequel Pro. Select the wp_users tables and verify that the users in the users.sql are not already in the new location. It's important that you don't import a duplicate username. We are now ready to import.
In Sequel Pro select File > Import. Select both SQL files in our backup folder.
Login to the multisite and select the subsite under site. Change domain to be the new site url. Make sure the "Update siteurl and home as well" is checked. Then click "Save Changes".
If your running domain mapping go to Settings > Domain. Add a domain map for the new website.
At this point I'll typically point my local HOSTS file to the new multisite so I can finish the rest of the import before the website goes live. For more details read <a href="http://www.howtogeek.com/howto/27350/beginner-geek-how-to-edit-your-hosts-file/">Beginner Geek: How To Edit Your Hosts File</a>. I'll add the following to mine.
205.186.137.35 anchordev.com
205.186.137.35 www.anchordev.com
Now with the HOSTS file configured we should be able to see the website on the new multisite. Lets start off by accessing the backend and assigning the correct users. The users should be in the database we just need to reattach them. Check the "Skip Confirmation Email". As you begin to type they should appear in a dropdown box.
Files
Upload themes and plugins from backup
Next we determine where the multisite is configured to store the files. This is a bit tricky as versions started with a Multisite install older than 3.5 is configured differently. The easiest way I found is to look at the .htaccess file
For a multisite configured with /wp-content/blogs.dir/[site ID]/files/ the .htaccess file will look like:
# BEGIN WordPress
RewriteRule ^index\.php$ - [L]
# uploaded files
RewriteRule ^([_0-9a-zA-Z-]+/)?files/(.+) wp-includes/ms-files.php?file=$2 [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).*) $1 [L]
RewriteRule ^[_0-9a-zA-Z-]+/(.*\.php)$ $1 [L]
RewriteRule . index.php [L]
# END WordPress
For a multisite configured with/wp-content/uploads/sites/[site ID]/ the .htaccess fill will look like:
# BEGIN WordPress
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteBase /
RewriteRule ^index\.php$ - [L]
# add a trailing slash to /wp-admin
RewriteRule ^wp-admin$ wp-admin/ [R=301,L]
RewriteCond %{REQUEST_FILENAME} -f [OR]
RewriteCond %{REQUEST_FILENAME} -d
RewriteRule ^ - [L]
RewriteRule ^(wp-(content|admin|includes).*) $1 [L]
RewriteRule . index.php [L]
</IfModule>
# END WordPress
For newer configurations (/sites/) we'll need to clear out the 'uploadpath' option from the options table. In Sequel Pro remove anything in the uploadpath.
For older configuration (/files/) we'll need to make sure the 'upload_path' option in the options table is in the format of 'wp-content/blogs.dir/[site ID]/files'
Now that the file preparation is complete we can upload the files into the proper folder on the server. Check the website to see if the images are working. If they aren't we'll need to update the image paths. To do that install <a href="http://wordpress.org/plugins/velvet-blues-update-urls/">Velvet Blues Update URLs </a>. Use Google Inspect tool to figure out where the incorrect path is.
Verify images are working.
Verify everything else looks good then switch DNS over to the new server for a seamless transfer.
Written by Austin Ginder
Related protips
2 Responses
Thanks for sharing Austin!
Thanks for the advice! I'm going to attempt this later tonight (locally of course).