Convert a Multisite WordPress install into a Single site

Given a WordPress Multisite network, with a main blog, and assuming all content has been moved on to that blog, how would one collapse the network back down into a standard WordPress non-network non-multisite install?

Related posts

Leave a Reply

5 comments

  1. I’ve gone through the steps to extract a site from a multisite install to a single instance now:

    1. Set up a clean copy of WP but don’t install it
    2. Find the site ID
    3. Copy the files from blogs.dir/ID/files to the new WP uploads folder
    4. Copy the theme the site uses and any plugins it uses to the appropriate folders in the new wp-content folder
    5. Take a back up of the multisite database but only the tables for the target site and the users and usermeta tables using MySQL workbench or equivalent
    6. Restore the backup to a new database and change the table name prefixes so they are all the same eg. ‘wp_SITEID_’ to ‘wp_’
    7. Using MySQL workbench or query browser tidy up the users and usermeta tables like so:
      1. DELETE FROM wp_usermeta WHERE user_id NOT IN( SELECT distinct(user_id) FROM wp_usermeta where meta_key LIKE 'wp_SITEID_%' );
      2. DELETE FROM wp_users WHERE ID NOT IN( SELECT distinct(user_id) FROM wp_usermeta where meta_key LIKE 'wp_SITEID_%' );
      3. UPDATE wp_usermeta SET meta_key = REPLACE( meta_key, 'wp_SITEID_', 'wp_' ) WHERE meta_key LIKE 'wp_SITEID_%';
      4. UPDATE wp_options SET option_name = REPLACE( option_name, 'wp_SITEID_', 'wp_' ) WHERE option_name LIKE 'wp_SITEID_%';
    8. Begin the WP install process to create a wp-config.php but don’t click ‘Run the install’
    9. Create a default .htaccess file if permalinks were in use or just visit the permalinks page in wp-admin
    10. You’ll need to update any old URLs in your database next. Ideally use a safe search/replace tool like the one in wp-cli or its general purpose precursor search/replace db by interconnect/it. Specifically replace blogs.dir/SITE_ID/files with uploads, and if you’re changing your site URL search for oldsite.com and replace with newsite.com.

    A fair bit of effort and you have to be careful with the database edits but that’s the only I can see to extract a single site from an existing multisite with all its settings etc… intact.

    EDIT:

    As spotted by @Jake I forgot to mention the final steps you may need to take eg. search/replace of old URLs. I’ve updated the list accordingly.

  2. It is possible to remove the multisite install without reinstall a new blog. Follow steps.

    1. Create a backup, database dump and file backup of wp-content
    2. Set constant WP_ALLOW_MULTISITE in your wp-config.php to FALSE
    3. Remove or comment MU settings in wp-config.php, like this:

      /**
      define( 'MULTISITE', true );
      define( 'SUBDOMAIN_INSTALL', false );
      $base = '/wordpress/';
      define( 'DOMAIN_CURRENT_SITE', 'localhost' );
      define( 'PATH_CURRENT_SITE', '/wordpress/' );
      define( 'SITE_ID_CURRENT_SITE', 1 );
      define( 'BLOG_ID_CURRENT_SITE', 1 );
      */
      
    4. Remove the MU settings from .htaccess, like the source below:

      # BEGIN WordPress
      RewriteEngine On
      RewriteBase /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).*) $2 [L]
      RewriteRule  ^([_0-9a-zA-Z-]+/)?(.*.php)$ $2 [L]
      RewriteRule . index.php [L]
      # END WordPress
      
    5. Create the permalinks new, in the backend wp-admin/options-permalink.php and maybe copy the result in .htaccess, if is not possible for WP, rights for write on this file.

    6. Remove un-usefull entries in table users; use the follow sql statement in a tool, like phpMyAdmin or Adminer

      `ALTER TABLE `wp_users` DROP `spam`, DROP `deleted`;`
      
    7. The follow tables can be dropped:

      • wp_blogs
      • wp_blog_versions
      • wp_registration_log
      • wp_signups
      • wp_site
      • wp_sitemeta
      • wp_sitecategories (only, if exist)

      (change wp_ to your database prefix)

    8. Now you have only the last tables of other blogs of the network. If you will use it also this content, then export this before via WordPress export as XML and import now in the clean single install.

  3. Actually it is possible and fairly easy to do; I’ve done it myself several times.

    There are there things to consider.

    1. wp-config.php which defines if multi site or single site
    2. .htaccess which contains the rewrite rules to support multi site
    3. the additional tables created to support multi site

    Commenting out the multi site define(?) in wp-config and updating your permalinks will revert the site to single site/default mode. Then all you have to do is clean up your database.

    If for some reason you are not able to access your wp-admin to update the permalinks simply delete your .htaccess file. WordPress will recreate it for you in single site mode.

    I’ll do my best to find the link to the codes/support article and update the answer with it.

    Here’s a link to one item on the support forum http://wordpress.org/support/topic/revert-to-single-site

  4. The basic processes here work well even in WP 3.5.1
    One clarification: If you named your subsite something you’ll have to change the links in the database to remove that name. If my subsite was named… mysite.com/comics then after following the above procedures your WP will look for mysite.com/comics and get errors on the permalinks. Edit the WP-OPTIONS table looking for the /comics extension and remove it. Also, check that the Uploads directory is pointing to the proper location – it may still show a blogs.dir entry and should now instead point to wp-content/uploads/

  5. The very important point that shouldn’t be missed, and it’s less talked about, is that you should still do have the line:

    define( 'WP_ALLOW_MULTISITE',

    But it should be changed updated to

    define( 'WP_ALLOW_MULTISITE', 0 );