Xaprb

Stay curious!

How to install and maintain multiple WordPress blogs easily

with 18 comments

My wife has a site that needs two WordPress blog installations. The URLs differ by a subdirectory name. Both blogs need to be (URL-wise) subdirectories of /blog/. They need to be completely independent of each other, yet use the same custom theme. And there used to be just a single blog, which was not in a subdirectory; its permalinks must not break. (It has nice URLs with the date and title in them, not post ID-style URLs). And because I’m the husband, I get to maintain it, so tack “easy to maintain” onto the requirements (it must be easy to upgrade WP in both blogs, for example). In this article I’ll show you how I did it with a single .htaccess file, a single copy of WordPress, two MySQL databases, and a single configuration file.

Fixing URLs

As I mentioned, there used to be a blog at /blog/ which must not break. Suppose this blog was about dogs and my wife has recently started blogging about cats. She wants two completely independent blogs: /blog/dogs/ and /blog/cats/. Now the old permalinks structure, e.g. /blog/2006/03/01/dogs-are-great/, must redirect to /blog/dogs/2006/03/01/dogs-are-great/. How to do this?

I’m not a mod_rewrite wizard, but I figured there must be a way. And indeed there is: if an incoming URL doesn’t contain dogs or cats, it can be rewritten and redirected to the new URL. Here’s the code, which goes in /blog/.htaccess:

RewriteBase /blog/
RewriteCond %{REQUEST_URI} !dogs|cats
RewriteRule ^(.*)$ http://www.furryfriends.org/blog/dogs/$1 [R]

(By the way, the furryfriends thing is just an example, not the real site name).

So far, so good. That works just fine: when I access a URL without dogs or cats in it, it redirects me. But I need to do more: I need rewrite rules to match the date-and-title permalinks both blogs will use. I accomplish that like so:

RewriteCond %{REQUEST_URI} dogs|cats
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule (dogs|cats) /blog/$1/index.php [L]

This is basically the same thing WordPress usually does, but I’ve made it tolerate either dogs or cats and figure out which installation should get the request. The .htaccess file lives in /blog/, not inside /dogs/ or /cats/ where it would be hard to maintain (it would get wiped out with upgrades). I can see different ways of doing this, but this is the way I chose. So here’s the whole file:


RewriteEngine On

# Anything to the old address (e.g. /blog/foo/bar) goes to the new address
# (e.g. /blog/dogs/foo/bar)
RewriteBase /blog/
RewriteCond %{REQUEST_URI} !dogs|cats
RewriteRule ^(.*)$ http://www.furryfriends.org/blog/dogs/$1 [R]

# If that fired, then we didn't reach this code.  If we did, then this rule
# should do what a normal WP rule does.
RewriteCond %{REQUEST_URI} dogs|cats
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule (dogs|cats) /blog/$1/index.php [L]

Are there any better ways of doing this? I’m curious. Leave a comment if you know of one.

Fixing the maintenance headache

Installing two copies of WordPress, then customizing both is a pain. And it makes upgrades harder, too. I’d have to upgrade them both, fiddle with plugins (some of them are customized, too) etc etc. Even backups would be more complicated. It would be all too easy to screw up and delete some data. There are just so many ways this is a bad idea.

It occurred to me that I could use a single copy and turn the dogs/ and cats/ subdirectories in the filesystem into symbolic links. (Windows users, you can stop reading now: this won’t work for you).

To make the blogs, the WordPress installation, and the custom blog theme all independent of each other, I created the following filesystem hierarchy:

blog/
   wordpress/
      2.3.2/
         [The usual WP files are here]
      wp_content/
         plugins/
         uploads/
         themes/
            my_custom_theme/

What I’ve done is separate the custom bits — the parts that don’t ship with WordPress — away from the files I want to upgrade when I upgrade WordPress. How will this work, though?

I’ll make symbolic links from the dogs/ and cats/ directories to the currently installed version of WordPress. So, from the root directory of the website, I type the following at the command line:

$ ln -s wordpress/2.3.2/ dogs
$ ln -s wordpress/2.3.2/ cats
$ cd wordpress/2.3.2/
$ rm -rf wp-content/
$ ln -s ../wp-content wp-content

The directory hierarchy now looks like this:

blog/
   cats/ -> wordpress/
   dogs/ -> wordpress/
   wordpress/
      2.3.2/
         [The usual WP files are here]
         wp-content/ -> ../wp-content
      wp_content/
         plugins/
         uploads/
         themes/
            my_custom_theme/

This is looking pretty good! There’s only one minor detail missing: because both blogs are running literally the same code via the magic of symlinks, each blog is trying to access the same database tables. I need to customize the WordPress configuration file, too. I’ll just give each installation a different table name prefix in wp-config.php:

$table_prefix  = strpos($_SERVER['REQUEST_URI'], 'blog/cats/') ? 'wp_cats_' : 'wp_dogs';

And voila, it works perfectly now. I accessed the two URLs, ran through the installation procedure twice, and have two completely independent blogs running the same code in the same database.

The upgrade procedure

So, this is all a little complicated, right? What if I’ve forgotten how I did it when I upgrade next time, or what if someone else does it instead of me? I wrote myself a little README file to fix this. Here’s what it says:

This is how to upgrade Lynn's blog.

The two blogs are actually using shared files, which are symlinked to make
it so there is only one copy of files.  You can't change the files in one
without changing them in the other.

The wp-content subdirectory is symlinked.

The wp-config file is customized so it will work in either blog:

$table_prefix  = strpos($_SERVER['REQUEST_URI'], 'blog/cats/') ? 'wp_cats_' : 'wp_dogs';

To upgrade, 

 1. Download the latest version and unpack it inside wordpress/ as 2.3.2/
    or whatever version it is.
 2. Then go into that directory.
 3. Remove the wp-content/ directory completely.
 4. Then symlink it like this: ln -s ../wp-content wp-content
 5. Now re-customize wp-config.php
 6. Go back to the blog/ directory.  rm dogs cats
 7. ln -s wordpress/2.3.2/ dogs
 8. ln -s wordpress/2.3.2/ cats

It’s still a manual process, but it should take me all of thirty seconds. I’m okay with that. As long as I remember there’s a README file, that is!

Written by Xaprb

March 11th, 2008 at 10:20 pm

Posted in Uncategorized

Tagged with , , ,

18 Responses to 'How to install and maintain multiple WordPress blogs easily'

Subscribe to comments with RSS

  1. You may also be able to skip all the rewrites and symlinks and use the same source code just with different URLs, and maintain upgradeability all in one.

    Just edit wp-config.php and add in conditionals

    if(stristr($_SERVER['HTTP_HOST'], ‘domain1.com’)) {
    define(‘DB_NAME’, ‘domain1wp’);
    … etc …
    } elseif(stristr($_SERVER['HTTP_HOST'], ‘domain2.com’)) {
    define(‘DB_NAME’, ‘domain2wp’);
    … etc …
    }

    I use the same source directory for our blog system in three different geographical regions (three separate servers in three separate languages) and just use a couple conditionals in wp-config.php to handle routing to the right database, or whatever (in this case, all of the information is the same though)

    Works like a charm. Rewrite stuff would only need to be done if you needed to setup multiple blogs under the same host with friendly URLs and stuff, I believe. I guess it just depends on your needs :)

    mike

    11 Mar 08 at 10:53 pm

  2. On hindsight, I should have looked at the post a little bit more. You used $table_prefix (I missed that line) to accomplish basically the same thing.

    That works too, I suppose :) However, I don’t think you need to do all the extra rewrite work and stuff. You should be able to share the same source directory just fine.

    mike

    11 Mar 08 at 10:55 pm

  3. Even though I have neither tried it nor the need to do so, I don’t see, why NTFS directory symlinks (aka junctions) wouldn’t work.

    Daniel Schneller

    12 Mar 08 at 5:12 am

  4. When I worked at b5media I was working on a similar approach. WordPress itself is pretty good about the symlinks, just be careful with third party plugins. They don’t all behave properly.

    Sharing the same wp-content/uploads directory might get confusing if a person from blog A starts seeing images from blog B.

    A positive side effect of symlinking is that you only need to store one copy of WordPress in the PHP opcode cache.

    Then again, there is always wpmu ;)

    Sean

    12 Mar 08 at 8:46 am

  5. The question mark operator is important:

    $table_prefix = strpos($_SERVER['REQUEST_URI'], ‘blog/cats/’) ? ‘wp_cats_’ : ‘wp_dogs’;

    You don’t want to assume the URL is friendly — the forced switch ensures bad guys can’t head off elsewhere in the DB structure.

    Likely do this our our two blogs at some point…

    :)

    A

    Alan

    12 Mar 08 at 1:28 pm

  6. Andrisi

    12 Mar 08 at 10:11 pm

  7. There is a minor bug here:

    “if an incoming URL doesn’t contain dogs or cats, it can be rewritten and redirected to the new URL.”

    it should read:

    “if an incoming URL doesn’t start with /blog/dogs/ or /blog/cats/, it can be rewritten and redirected to the new URL.”

    For example /blog/2006/03/01/dogs-are-great/ already contains “dogs” and thus will not be redirected to /blog/dogs/2006/03/01/dogs-are-great/

    ;-)

    Vasil Dimov

    13 Mar 08 at 3:17 am

  8. Yes, that’s a good point. I should have done the rewrite rule as ^/(dogs|cats). In this case the dogs/cats example is a bit silly; the real blog names will never show up in a URL though :-)

    Xaprb

    13 Mar 08 at 8:19 am

  9. I never knew about wpmu. I’d probably use that instead, in the future!

    Xaprb

    13 Mar 08 at 8:20 am

  10. wpmu is okay, but I prefer separate table installation and using wp-config to route to the right installation appropriately. when I tried wmpu a while ago I wasn’t very happy with it.

    mike

    13 Mar 08 at 12:20 pm

  11. There are two particular reasons to use WPMU as far as I can tell:
    1) Allowing end-users to create their own blogs easily.
    2) Creating the concept of a “super admin” which has the facility for a non-tech to add/terminate/edit WP blogs as required.

    If you are just running a few blogs as Mike describes, I advise against WPMU due to the extra complexity, reduction in flexibility and issues with some plugins. I think Mike made the right decision in his particular case.

    Jof Arnold

    14 Mar 08 at 6:34 am

  12. I see… Actually we choose to postpone migrating to MU, just because of this complexity. So you’re probably right. :-)

    Andrisi

    14 Mar 08 at 9:48 am

  13. Thanks for your website. I have learned fixing my websites’ urls here.

    travesti

    2 May 08 at 4:47 am

  14. Okay complicated code, but I’m definitely going to try it when I get home! :) Thanks for posting it.

    Alison

    15 May 08 at 11:22 am

  15. I have not understood for what it it is necessary, than standard adjustments are bad?

    Sasha

    18 May 08 at 6:44 am

  16. “Why don’t you just install WPMU?” Agreed. If you have not tried MU yet, then you seriously need to. It’s a totally awesome multi-user content management system that can run thousands of blogs on a single install… It’s the way to go folks.

    Larry

    11 Aug 08 at 4:01 pm

  17. Mike is right with his posting, I’ve tried this method and am now running three blogs with the same installation. Each with with its own name postings, theme and plugins. Works nicely

    Thomas

    20 Aug 08 at 3:24 am

  18. Look at the date (2008)! WP now (2010, from version 3) supports multiple blogs from one installation by default, so there’s no need for this. :-)

    Andris

    18 Feb 11 at 6:19 am

Leave a Reply