Moving a Site Out From a Multi-Site WordPress Network

This documentation is for Linux only.

When I first learned about the Multi-Site capability of WordPress, I immediately liked the idea and started to experiment.

After a while, I decided that I should use this to offer personal WP sites to people in my community.

Eventually I realized that it was not really a good idea. Conflicting plugins, themes, not being able to upgrade freely were only a few of the nuisances. Refraining from upgrades is out of question. On the other hand, some updates can cause a conflict with many of the plugins and/or themes and this kills all the sites. Therefore at some point you have to move critical sites out of the network, one by one.

It s not easy to automate this process but after googling for a long time and reading a lot of things people had written, I managed to move a site out semi-automatically. Here are the steps to follow:

Step 1
Find out the ID number of the site that you want to move out of the multi-site network. This ID is displayed in the site list for the super-admin. Suppose the ID# is 28. Next, find out the table name prefix used on your multi-site database. Suppose it is “web2_”. (You can see this in the wp-config.php file, or by the “show tables;” MySQL command.)

Step 2
We shall need the dump of all tables of the site (e.g. ID#: 28) in question. To get this dump, install phpmyadmin on the multi-site server. If you do not want to install phpmyadmin and have shell access to the db server; you can use the following shell command:

mysqldump -u <dbUser> -p<dbPwd> <db> $(mysql -D <db> -u <dbUser> -p<dbPwd> -Bse “show tables like ‘<tablePrefix>\_<ID#>\_%'”) > /tmp/exported.sql

If you preferred and used the shell command way of dumping the tables, you can skip to Step 5.

Since I had a lot of sites in the network, I had hundreds of tables in the database. To make phpmyadmin list all tables, I had to tweak one of its parameters.

“Settings -> “Navigation Panel” -> “Maximum items in branch” = 250

and set  “max_input_vars = 10000” in the php.ini file so that the export function works properly and restart apache2.

Step 3
Using phpmyadmin, find all tables with names starting with the prefix and site ID# you’ve figured out in Step 1. (i.e. “web2_” and “28“) and check the boxes for all of them.

Step 4
Using the “With Selected” option box at the bottom of the phpmyadmin table listing, choose “Export” and get the dump file for these tables and save the file (say; /tmp/exported.sql).

Step 5
Install a fresh WordPress. Make sure that you install a WP of EXACTLY the same version with your multi-site installation. Not newer, not older! Suppose that the database name is “newdb” and table name prefix you chose for this fresh install is “wp_“.

Step 6
Using any text editor, change all occurrences of “web2_28_” with “wp_” in the /tmp/exported.sql file. Make sure that you make these changes ONLY on “CREATE TABLE”  and “INSERT INTO” and “LOCK TABLES” and “ALTER TABLE” lines.

Step 7
Install wp-cli (WordPress Command Line tool – see https://wp-cli.org) on the server that will host the moved site. The tool’s web site has excellent documentation about its installation.

Step 8
Copy the file export file to some directory on the new server. and execute the command

mysql -u root -p newdb < /tmp/exported.sql

Step 9
The export file has a lot of URL’s in the multi-site format. A typical one would look like

http://web2.bilkent.edu.tr/ds/wp-content/uploads/sites/28/2016/02/cropped-logo.jpg

and there will be a lot of path strings like “wp-content/uploads/sites/28” embedded here and there. URLs and file paths on standalone WP installations do not have the “/sites/nnn” strings.

These have to be corrected by removing the substrings “/sites/28” but you cannot do this using a text editor because the export file stores these info in serialized object data format which include string length info for each piece of string data.

WP-CLI will do it for you properly.

The wp-cli tool doesn’t want to run with root credentials, therefore I used a regular user’s account.

# su – myself
$ cd /var/www (or the directory where your fresh WP sits)
$ wp search-replace ‘sites/28/’ ” 

Step 10
Copy all files of the site to move (in our example the one with ID# 28) from the multi-site server’s “/var/www/wp-content/uploads/sites/28 ” directory to the  “/var/www/wp-content/uploads” directory on the new server.

Step 11
This is probably the hardest step. Due to the architecture of the multi-site WP, it is not possible to find which plugins are used in a certain site of the network (at least I couldn’t figure out how). If you already know which plugins your site has used among the network wide plugins, that is wonderful. Copy these plugins’ code files to the new server. If you don’t know which ones are used, you have to copy all of them. Then, later, you might try to remove plugins one by one and see what happens on the new site. Please note that the plugins that you have put under /var/www/wp-content/plugins directory will need to be activated on the fresh WP.

Step 12
Make sure that all the files and directories are owned by the web server user and group  (usually they are www-data:www-data).

Browse the new site and see if everything looks as it should. Check and test critical plugin-widget settings (like SMTP, firewall & security, galleries, carousels, video players, tables, contact form settings, etc.).

I personally didn’t loose any settings but now I have an excess of plugins for which I should try to figure out if they are used and remove them if they are not.