How to migrate a WordPress Network back to a standard WordPress

Some time ago one of my clients, who was running a WordPress Network, decided to close all the blogs to leave only the main one active. All the articles in the network were to be imported into the main blog. I used the WordPress import/export tools and put in place a series of HTTP redirects. Everything was fine. However, the installation was still a network and there was some overhead at the database level and at the administration level. So I though I should be reverting it to a standard WordPress.

I couldn’t find any detailed information about how to do that – sounds like it’s not a common thing to do. Especially, I couldn’t find any information about the level of difficulty or risk that implied. It turns out it’s a simple thing to do (provided you know what you are doing, of course) and here are the steps I undertook to acheive it.

Please note that this network was activated pre-3.0; if your network was activated post-3.0 there will be some differences, but nothing tremendous.

Preparation

First things first, backup everything, database and files, and put the site under maintenance (needless to say, also make sure you are able to restore your backups). I recommend you don’t use a plugin or WP native maintenance mode but instead use .htaccess directives to do so.

For example, here is what I use:

RewriteEngine On
RewriteCond {5f676304cfd4ae2259631a2f5a3ea815e87ae216a7b910a3d060a7b08502a4b2}{REMOTE_ADDR} !=XXX.XXX.XXX.XXX
RewriteCond {5f676304cfd4ae2259631a2f5a3ea815e87ae216a7b910a3d060a7b08502a4b2}{REQUEST_URI} !^/maintenance\.html$
RewriteRule ^(.*)$ /maintenance.html [L]

Where maintenance.html is a static HTML file and I get my public IP from Google (just ask “what is my ip“). This ensures that only I have access to the site, everybody else being redirected to the static maintenance page.

Once the change is done I also make sure it’s active by using a proxy like HideMyAss.com.

Finally, deactivate all your plugins.

Change your wp-config.php file

Make sure to remove any extra defines you’ve setup for the network so you get a standard config file (you can compare with the wp-config-sample.php file).

Then, decide which blog is going to be the main blog and find its ID. In my case it was the main blog so the ID was 1. Change the $table_prefix to “wp_1_” (or whatever was your table prefix, followed by “1_”). I do that because I don’t want to rename all the database tables, just a couple of them.

If you are doing that on a post-3.0 install and want to use the main blog then I understand you won’t need to do that because the database tables for the main blog don’t have the blog ID in their name.

Migrate your database

Now we need to rename some tables (actually we are going to clone them, since we cannot really rename tables in MySQL, but this is even better). There are only two tables to clone,  wp_users and wp_usermeta. Here are the SQL commands to use:

CREATE TABLE wp_1_users LIKE wp_users;
CREATE TABLE wp_1_usermeta LIKE wp_usermeta;
INSERT INTO wp_1_users SELECT * FROM wp_users;
INSERT INTO wp_1_usermeta SELECT * FROM wp_usermeta;

If you have a post-3.0 install and want to use the main blog you won’t need to do anything.

Migrating media files

Copy all the files from /wp-content/blogs.dir/1/files/ to the /wp-content/uploads/ folder.

If you have a post-3.0 install and want to use the main blog you’ll have nothing to do. If you want to use another blog as the main blog (say blog ID 2) then you will have to copy all the files from wp-content/uploads/sites/2/ to the /wp-content/uploads/ folder.

Actually, because I had imported all the posts from the other blogs into the main one, I also merged all the other media folders into the /wp-content/uploads folder.

Change the .htaccess file

A typical WordPress .htaccess should look something like this:

# BEGIN WordPress
RewriteEngine On
RewriteBase /
RewriteCond {5f676304cfd4ae2259631a2f5a3ea815e87ae216a7b910a3d060a7b08502a4b2}{REQUEST_FILENAME} !-f
RewriteCond {5f676304cfd4ae2259631a2f5a3ea815e87ae216a7b910a3d060a7b08502a4b2}{REQUEST_FILENAME} !-d
RewriteRule . /index.php [L]
# END WordPress

Since we copied the media files into the wp-content/uploads folder here are the directives we need to add so that old URLs are still valid:

RewriteRule ^([_0-9a-zA-Z-]+/)?files/(.+) http://{5f676304cfd4ae2259631a2f5a3ea815e87ae216a7b910a3d060a7b08502a4b2}{HTTP_HOST}/wp-content/uploads/$2 [R=301,L]
RewriteRule ^wp-content/blogs.dir/[0-9]+/files/(.+) http://{5f676304cfd4ae2259631a2f5a3ea815e87ae216a7b910a3d060a7b08502a4b2}{HTTP_HOST}/wp-content/uploads/$1 [R=301,L]

If it’s a post-3.0 install it should look something like this:

RewriteRule ^wp-content/uploads/sites/[0-9]+/(.+) http://{5f676304cfd4ae2259631a2f5a3ea815e87ae216a7b910a3d060a7b08502a4b2}{HTTP_HOST}/wp-content/uploads/$1 [R=301,L]

Unless you keep the /blog/ prefix in your permalink structure, you will also need to redirect the main blog’s URL:

RewriteRule ^blog(/.*)?$ http://{5f676304cfd4ae2259631a2f5a3ea815e87ae216a7b910a3d060a7b08502a4b2}{HTTP_HOST}$1 [R=301,L]

Last bits

  • Search and replace any occurrence of /blogs.dir/1/files into the wp_1_options table and replace with /uploads
  • Do the same thing for your plugins tables (I cannot help you here as it depends on your plugins)
  • Check and regenerate the permalinks structure
  • Reactivate your plugins
  • Reset the users’ roles and capabilities (see the answer to that StackExchange question)
  • Disable the maintenance mode

Cleanup

I recommend you wait for a while before doing that last part – until you are completely sure everything is ok.

  • Remove all tables except those starting with wp_1_
  • Remove the wp-content/blogs.dir folder

And here you are – you successfully migrated a WordPress Network back into a standard installation.

If you have further experience or questions about the procedure feel free to share them in the comments.

Image Credits: Antonio Ruiz García

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.