Multiple Sites Driven By One WordPress Installation Part II: Please Be Careful, You Really Might Mess Up ;)

This is just a little update on what I’ve been doing and what I have acheived so far. So, what we have: two different hosts – example.org and example-two.org both on one webserver right next to eachother, let’s say in the /home/username/www (we’ll just call it www further on) directory. The apache vhosts are configured correctly, the document roots are set. Everything’s working fine. There are two wordpress installations, one in /www/example.org and the second one in /www/example-two.org, which I got rid of. Here’s how.

So, first, create a new directory for the installation somewhere unreachable. I created mine in /www/wordpress_public/ and copied all the files and folders from /www/example.org to /www/wordpress_public. Remember to copy, not move, cause you might mess up. Always keep your backup right by your side in case you destroy everything ;) Also, do not copy the .htaccess file, it has to say in your example.org root folder, while the files in wordpress_public should be accessible by everyone.

Next, you have to create a symbolic link in the example.org directory that links to ../wordpress_public (I called mine “core”, I think it’s fuzzy ;) On a linux system, being in the example.org directory it goes like this:

ln -s ../wordpress_public ./core

So now, /www/example.org/core is pretty much the same as /www/wordpress_public, get it? Note, that if you are running suPHP you’ll get a “is not in document root of Vhost” error when trying to access example.org/core. To get rid of that error, edit the suPHP config file (probably located in /etc/suphp.conf), find the check_vhost_docroot parameter and set it to false. Restart the httpd daemon.

Open up index.php in /www/exaple.org and replace this line:

require('./wp-blog-header.php');

With something like this:

require('./core/wp-blog-header.php');

Before proceeding, delete your .htaccess file in /www/example.org. Then, Open up your usual wordpress admin panel on example.org (yes, it’s still accessible) probably on example.org/wp-admin, browse to your Settings – General screen, then change the WordPress address (URL) to http://example.org/core instead of http://example.org. No trailing slashes! Click save and bang! You’re logged out. Now browse to http://example.org/core/wp-admin and you should be able to login using your old credentials. Browse to your Permalinks settings and refresh them (that should create a new .htaccess file). Done! Almost..

Now, if you’re going to have more than one website (which is actually the point I’m writing all this stuff, duh!) then you should keep a little order in your wp-content directory. I’m talking about the uploads, photos & other post attachments. The generic WordPress attachments are quite easy to change in the settings. Switch them to wp-content/uploads/example.org, next using an FTP client or SSH move all the files and folders in /www/wordpress_public/wp-content/uploads to /www/wordpress_publoic/wp-content/uploads/example.org. That should do the trick. To run a test try creating a new post and uploading a photo or whatever, see where it places it.

If there were already posts on your blog with images attached, then their paths will not change automatically to your new uploads folder, you’d have to do that manually if you didn’t know some basic SQL ;) Run this in phpMyAdmin or whatever:

UPDATE wp_posts w SET `post_content` =
    REPLACE(`post_content`, 'http://example.org/wp-content/uploads',
    'http://example.org/core/wp-content/uploads/example.org')
    WHERE `post_content` LIKE '%http://example.org/wp-content/uploads%';

The WHERE condition is just to make sure other posts aren’t messed up.. Make sure everything’s working and proceed.

Now we’d like the example-two.org website to use the same WordPress installation located in /www/wordpress_public. First, copy themes and plugins from the example-two.org directory to the wordpress_public folder (so that wordpress_public will contain all the plugins and themes that both websites use). In SSH you’d type something like this:

cp -R www/example.org/wp-content/plugins/* www/wordpress_public/wp-content/plugins/
cp -R www/example.org/wp-content/themes/* www/wordpress_public/wp-content/themes/

Then, you have to somehow distinguish in wordpress_public which website we’re gonna show, right? I wrote this little hack you could use for wp-config.php (the one located in /www/wordpress_public) which could handle as many websites as you like:

$wp_multi = array(
	"example.org" => array(
		"DB_NAME" => "example_database",
		"DB_USER" => "examlpe_username",
		"DB_PASSWORD" => "example_password",
		"DB_HOST" => "example_host"
	),

	"example-two.org" => array(
		"DB_NAME" => "example2_database",
		"DB_USER" => "example2_username",
		"DB_PASSWORD" => "example2_password",
		"DB_HOST" => "example2_host"
	)
);
$server_name = $_SERVER["SERVER_NAME"];
$wp_settings = $wp_multi[$server_name];

// ** MySQL settings ** //
define('DB_NAME', $wp_settings["DB_NAME"]);
define('DB_USER', $wp_settings["DB_USER"]);
define('DB_PASSWORD', $wp_settings["DB_PASSWORD"]);
define('DB_HOST', $wp_settings["DB_HOST"]);

I hope you get my point and don’t delete the rest of the wp-config.php file which I didn’t list here ;) Oh and you do have to change example.org and example-two.org, unless you own those domains … Now, save the file and check back on example.org, see if it still works (yes, it should ..)

Back to example-two.org. Create the symbolic link (core) in /www/example-two.org pointing to the wordpress_public folder, just like we did for example.org, remember? Make sure it’s accessible. Browse to your old example-two.org admin panel, switch the WordPress address (URL) to http://example-two.org/core (no trailing slash!), remove your .htaccess file from /www/example-two.org and edit index.php (it should read the same as the index.php of the example.org website). Browse to your new admin panel (http://example-two.org/core/wp-admin) and refresh your permalinks settings. Browse to example-two.org and see if it works. If it does, then you did everything right, and remember to set your upload directory to wp-content/uploads/example-two.org and don’t forget to copy all your previous uploads to the new place.

Now when everything’s working fine, you can go ahead and remove all the files and folders that are somehow related to WordPress from your /www/example.org and /www/example-two.org directories (except from, of course, .htaccess).

Congrats! You now have two websites, driven by one single WordPress installation!

Here’s a list of rules to follow when using this method:

  • You update your WordPress core only once on any of the two (or more) hosts. If there’s a database structure change in the update, then each website will ask about updating its database seperately (when in the admin panel)
  • Same with the plugins. Update only once, and if you do encounter any issues after a certain plugin update, deactive and activate it on each and every site
  • If you’re using the Next Gen Gallery plugin, change the settings to store your gallery in /wp-content/gallery/example.org and /wp-content/gallery/example-two.org, for the two websites, not in one single folder, otherwiste you’ll have a complete mess when you reach 5 or 10 websites
  • I’ve no idea what will happen with cache plugins, still trying to figure out what WP-Super Cache is up to and it’s not my fault if you mess everything up, alright? ;)
  • All this might be pretty dangerous, so you shouldn’t experiment on super popular blogs unless you know what you’re doing

Guess that’s it. I’ll keep running the tests and stuff. I’m really worried about the cache plugin, so I’ll get back at you with that later this week. Also, for your information, kovshenin.com and blog.foller.me are now running this method, so if you notice anything strange, please let me know, okay?

About the author

Konstantin Kovshenin

WordPress Core Contributor, ex-Automattician, public speaker and consultant, enjoying life in Moscow. I blog about tech, WordPress and DevOps.

6 comments

  • I had the same issues with suPHP. Quite easy to solve on a VPS or a dedicated server, but what about shared hosting? Is there a way of overriding it?

  • Thanks for posting this link. I red both part 1 and part 2 pages. So you've been already testing it; for the feedback to me all appears as per normal. I will wait for your next post or posts before trying a multiple site, a couple, on one wp installation – as you advice I want to avoid messing up something. I wonder how this ability of wp evolves?! But certainly I plan to add more than one domain. ta

    • Hey, cool. Yeah, the issues may raise when using certain low-level plugins, such as caching, etc, the would require a little bit of extra configuration for each of the websites. I wonder if WordPress will continue their merge with MU, it may be interesting to see something evolving from their side as I believe they've written quite some stuff for multi-blog handling, in one database ;)