Setting up Mephisto for Multiple Sites

This site uses Rick Olsen’s open-source Mephisto blog engine. Like all Rails applications, it needs to stay resident in RAM on the server. If you want to host multiple blogs, you can simply have multiple copies of Mephisto, but with this approach the amount of server memory needed grows with each new blog.

Fortunately, Mephisto can be set up in a multi-site mode, in which one Mephisto installation can host any number of blogs. This is an “experimental” feature, because there is no admin interface to support it, and you need to set up some directories manually, add sites using the Rails console, and add rewrite rules to your web server configuration.

I took me a while to understand how it all works and get everything set up properly. In this article, I’ll walk you through how it works and what my implementation looks like, in the hope that this tutorial may help others facing the same task. (Also check out the Hosting Multiple Sites page on the Mephisto wiki.)

How Multi-Site Works

In the multi-site mode, Mephisto looks at the host name (domain name) provided by the server and uses this name to change the routing. For the most part, this happens internally to the application.

There are three places, however, where it is exposed to the file system: assets, cache, and themes. Assets are files that you’ve uploaded, such as images, that are part of your articles. The cache is a set of html files for previously accessed pages, which eliminates the need for Rails to run at all when accessing a page that has already been viewed (and has not changed since). Themes are the liquid templates and CSS files that control the appearance of the site. All three of these need to be made domain-specific for multi-site mode to work.

Mephisto creates a subdirectory for each domain within the public/assets and public/cache directories. So if you have two blogs, blog-one.com and blog-two.com, you’ll have a structure like this:

  • public
    • assets
      • blog-one.com
      • blog-two.com
    • cache
      • blog-one.com
      • blog-two.com

Mephisto will create these automatically, so you may not need to be concerned with them, other than ensuring that the web server is configured with the appropriate rewrite rules (described later). If you are moving a regular Mephisto installation to one site in a multi-site version, as I was, then you’ll need to move the contents of your public/assets directory into the appropriate public/assets/sitename.com directory.

The other set of files that must be unique for each site is the theme. The themes directory for a single-site installation includes a directory named site-1, which includes all the template and CSS files. In a multi-site installation, you simply add additional directories with the theme files, named site-2, site-3, etc. Unlike the assets and cache directories, these are named according to the database ID in the sites table, rather than by the domain name. Mephisto doesn’t set these up for you, so you need to create the required directories and copy in the files for the desired theme.

Setting up Multi-site Mephisto

With that background behind us, here’s the steps to set up a Mephisto installation for multi-site operation.

  1. Do a basic Mephisto install. (See the Mephisto site for details.)
  2. Edit environment.rb and uncomment the line
    Site.multi_sites_enabled = true
  3. Start a Rails console, being sure to set it for production mode, assuming that’s what you’re running in. (Open a shell window at the root of the app, and type ruby script/console production.)
  4. In the console, enter the following command to create each site:
    s = Site.create(:host => "domainname.com", :title => "Site Title Goes Here")
    Of course, you need to substitute your domain name for domainname.com and put in the site title (you can also change the site title when you get into the site’s admin pages).
  5. Take a look at the sites table in the database to confirm that the sites are as you expect, and to confirm the database ID of each.
  6. In the themes directory, copy the site-1 directory to a new directory for each site, named site-2, site-3, etc. The numbers must match the database IDs in the site table.
  7. In your Apache configuration, assuming you’re using a virtual host, add a ServerAlias directive, in the VirtualHost section, for each domain name, so the application will respond to all the domain names.
  8. Set up the rewrite rules, as described in the following section.
  9. Start (or restart) the web server (e.g., Apache) and the application server (e.g., Mongrel Cluster)

Now you should be able to access the admin page for each site by simply browsing to domainname.com/admin to set up your sections, choose a new template if desired, edit the template, and so forth. Everything for each site should be independent.

If you ran Mephisto in single-site mode before setting up multi-site, then you’ll have some .html files in the public folder. Delete them all, or you’ll get unexpected (cached) results.

Configuring the Web Server

For requests that are processed by Mephisto, the application takes care of detecting the host name and accessing the appropriate site. Static files are served directly by the web server (e.g. Apache), however, so Mephisto can’t take care of mapping those requests to the appropriate directories for each site.

So, in addition to the setup of Mephisto itself, you need to add rewrite rules for your web server that, on each request, insert the domain name into file paths for asset, cache, and theme file requests. Just how this is done depends on what web and application server you’re using. I’ll explain the rules I’m using with Apache 2.2 and Mongel Cluster. These rules could go in an .htaccess file in Mephisto’s public directory; in my case, they’re in the httpd.conf file, since my configuration allows me to change the base configuration, which is more efficient than using .htaccess.

Several different sets of rewrite rules have been published in various blogs, groups, and wikis; what follows is derived from postings by dusty and seth to the Mephisto Google group. (If you’re not using Apache, you’ll need rules appropriate for your server; the Hosting Multiple Sites page on the Mephisto wiki has examples for Lighttpd and nginx.)

If you’re not familiar with Apache rewrite rules, the Apache site has a nice introduction. In essence, each rewrite rule uses a regular expression to translate the URL. If preceded by one or more rewrite condition statements, as in the examples below, the rewrite rule is only invoked if all the conditions are true.

Note that each of these rewrite rules has the L option applied, so if the rule is matched, none of the later rules are invoked.

The first rewrite rule inserts the domain name into URLs that begin with /assets. It first checks to see if the file exists, which may not be strictly necessary; if the file doesn’t exist, you’re going to get an error either way.

RewriteCond %{REQUEST_URI} ^/assets/.*$
RewriteCond %{DOCUMENT_ROOT}/assets/%{HTTP_HOST}/$1 -f
RewriteRule ^/assets/(.*)$ /assets/%{HTTP_HOST}/$1 [QSA,L]

The next rule rewrites the base URL to the index.rhtml file in the appropriate cache directory, if that file exists.

RewriteCond %{REQUEST_URI} ^/$
RewriteCond %{DOCUMENT_ROOT}/cache/%{HTTP_HOST}/index.html -f
RewriteRule ^/(.*)$ /cache/%{HTTP_HOST}/index.html [QSA,L]

Now we need to check for any URL with a string after the domain name that doesn’t include a period. This means it is a Rails URL, and not one for a static file. In this case, we want to check to see if there is a corresponding .html file in the appropriate cache, and if so, rewrite it to a URL that includes /cache/domainname/ and appends .html.

RewriteCond %{REQUEST_URI} ^/[^.]+$
RewriteCond %{DOCUMENT_ROOT}/cache/%{HTTP_HOST}%{REQUEST_FILENAME}.html -f
RewriteRule ^/(.*)$ /cache/%{HTTP_HOST}%{REQUEST_FILENAME}.html [QSA,L]

For static files that may be in the cache, we do a similar rewrite but without appending .html. This rule applies only to URL strings that include a period, indicating a static file (ending is something like .css or .jpg).

RewriteCond %{REQUEST_URI} ^/.+$
RewriteCond %{DOCUMENT_ROOT}/cache/%{HTTP_HOST}%{REQUEST_FILENAME} -f
RewriteRule ^/(.*)$ /cache/%{HTTP_HOST}%{REQUEST_FILENAME} [QSA,L]

And finally, anything that wasn’t matched by any of the above rules is simply sent to Rails. In my case, this means invoking Mongrel Cluster, and the cluster is named blogs_cluster.

RewriteRule ^/(.*)$ balancer://blogs_cluster%{REQUEST_FILENAME} [P,QSA,L] 

Don’t forget to restart Apache after making any configuration changes.

If all goes well, you’ll now have a Mephisto installation capable or running many sites. If you have lots of sites, or any of them gets high traffic, you may want to have more than the basic two Mongrels, but for a few low-traffic blogs, two should be fine.

Comments

Leave a response

  1. HikingJune 28, 2007 @ 09:29 AM
    Thanks This helped me getting a multisite working. One thing to watch out for is HTTP_HOST if you come in through www.domain.com and domain.com