**Driving on MT**: Single Installation, Multiple Domains

Tuesday, November 13, 2007

About the same time I was looking into moving our websites to a VPS, I read some comments on the Pronet list by Mark Carey about using a single installation of Movable Type to run multiple domains. I was very interested—we have several MT sites, and it would be great to run everything from a central location. MT is built to run multiple blogs, so it seems silly to install it multiple times on a server if you don’t have to. With this setup, I only have one installation to upgrade, one place to install plugins, and one login to control all my blogs.

It took some tweaking, but I’ve got it working and wanted to write up the process.

The first step is to install MT. Choose a central location on your server to upload the files. In your mt-config.cgi file, you’ll want the following:

CGIPath        /mt/

Notice that’s a relative path and not a full path. Of course, that should be whatever directory you want each of your domains to use to access MT. Keep in mind, if your domain has a directory with the same name, it’s local files will no longer be accessible after this is set up. Also, be sure not to add a StaticWebPath line to your configuration file. That will cause problems. With this setup, mt-static can and should be left in your MT directory.

The key to making this work is the Apache Alias directive. This allows you to treat a directory outside your web root directory as if it were part of your website. You’ll need this line in your httpd.conf file:

    Alias /mt /full/path/to/mt

You’ll need to follow that with a Directory definition. What you put in that will depend on your server, but here’s an example:

    <Directory /full/path/to/mt>
    AllowOverride All
    <IfModule mod_perl.c>
    <Files ~ (\.pl$)>
            SetHandler perl-script
            PerlHandler ModPerl::Registry
            Options ExecCGI
            allow from all
            PerlSendHeader On
    </Files>
    </IfModule>
    <IfModule mod_fcgid.c>
            AddHandler fcgid-script .fcgi
    </IfModule>
            AddHandler cgi-script .cgi
            Options +Includes +ExecCGI +FollowSymLinks
    </Directory>

Since my server is set up to use suexec, any domain that is going to use MT must have the following in its VirtualHost definition:

SuexecUserGroup mtuser mtgroup

Which, of course, can be any appropriate user and group for your system. This isn’t ideal, because it means one user must own the files for multiple domains, which negates some of the security of suexec. Still, this is the path we’ve chosen, there’s no turning back now.

There’s one more minor detail. I’m running MT under FastCGI. In that environment, for this multi-domain setup to work, we have to… edit a core MT file.

(Cue record-scratching sound effect)

I know, I hated doing it, but commenting out one line of code put an end to a major irritation. Here’s the problem: Various actions in the MT interface require the system to take an action, then redirect the user to another page in the interface. When it does this, it has to build a URL to the location it’s redirecting to. Part of building that URL is finding out what your domain is. The first time during a session that it has to do this it runs a series of checks, figures out the domain, then stores that value for future use.

In a FastCGI environment, all the code that runs the MT interface is loaded into memory and kept there for use by multiple users. This is where we run into a problem. If User A writes an entry in MT from Domain A, at some point in that process MT will figure out it’s on Domain A and store that information. Then, when User B edits a template in MT via Domain B, when MT tries to figure out where it is it still has that information from when User A was using the system. So, it redirects User B to a page on Domain A. But, User B is not logged in to Domain A, so he gets redirected to a login page instead. Eventually, this happens enough times to drive User B insane, at which point he starts reading through the MT code to figure out how to fix this problem.

Or her. User B could be a her. User B could be anybody, really.

Anyway, the file to edit is lib/MT/App.pm in your MT directory. Around line 2524, in the base subroutine, is this line of code:

    return $app->{__host} if exists $app->{__host};

Comment it out, save it, then restart your MT processes. Now, MT won’t store the domain it’s running from, it will recheck every time it needs to know. This is obviously less efficient, but the performance hit is minor compared to constantly logging into different domains.

And that’s it, I think. If any of this doesn’t make sense, or you run into problems, leave a comment and I’ll see what I can do.