max-klinger.org > Projects > Mediawiki setup

Multiple mediawikis on one host with/without short URLs

There are many guides on the net, that detail how to get one or the other working, i don't think i saw one for both and on top of that they cease to work since 1.19, so i hope this helps someone. I sure wish i'd have found something like it. This is probably considered advanced, if you aren't you won't get satisfaction. Use your brain, adjust domains/paths/programs/options. I have no clue if this can be made to work under windows, but if you are masochistic enough to put that on a server, then you'll no doubt enjoy the extra pain in figuring it out yourself.

First up what are we doing: I want to host multiple mediawikis, but don't want to update them all one after another. This setup works by unifying all those wikis into one code base along with the plugins. This is how it works:

1. Normal install

First of all create one mediawiki code directory

mkdir /srv/http/common/mediawiki
cd /srv/http/common/mediawiki

Afterwards grab a copy from the webpage

http://www.mediawiki.org/wiki/Download

or in my case install from git

git clone https://gerrit.wikimedia.org/r/p/mediawiki/core.git
# and decide which one you want, don't just take master, 
# that's a very bad idea on a production system!  
git tag -l
git checkout 1.19.2 # or whatever is current at the time you read this. 

Make it public by using these rules in your apache config

Alias /wiki /srv/http/common/mediawiki
If you haven't setup the wiki you need before just do the usual install by navigating to

firefox http://domain/wiki/index.php

and following the usual instructions. If you just want short URLS goto 3, for multiple wikis on one host continue.

2. More than one instance on the same host

So far this is a normal wiki install, now lets make it more than one. All code in blue is to be done for every instance, the black parts are to be done only on the first run.
For every instance you want, make a directory, put the LocalSettings.php into it, along with an upload/images dir if you allow that. Please remember to not call the directory wiki, otherwise Short URLs are tricky and some other stuff is complicated as well.

mkdir -p /srv/http/de.tehsuck/w/images
cp LocalSettings /srv/http/de.tehsuck/w/

We now have to create a directory keeping symlinks to dispatch into 

mkdir -p /srv/http/common/mediawiki-sites/
cd /srv/http/common/mediawiki-sites/
# the part after the domain is what the url later is supposed to look like
ln -s  /srv/http/de.tehsuck/w tehsuck.de.wiki

This will ensure that the common base dir knows where to look for the site specific files/dirs. 
Now replace the common base dir LocalSettings.php with this dispatcher code:

<?php
  static $confdir = '/srv/http/common/mediawiki-sites';

  $uri = explode('/', $_SERVER['REQUEST_URI']);
  $server = explode(':', $_SERVER['HTTP_HOST']);
  $uri[0] = $server[0];
  $i = count($uri);
  while ($i > 0) {
      $dir = implode('.', array_slice($uri, 0, $i));
      if (file_exists("$confdir/$dir/LocalSettings.php")) {
        $conf = "$confdir/$dir";
        require_once( $conf . '/LocalSettings.php' );
        break;
       }
    $i--;
  }

  if (!isset($conf)){
      $IP = '.';
      require_once( './includes/DefaultSettings.php' ); # used for printing the version
      require_once( './includes/templates/NoLocalSettings.php' );
      die();
  }
?>

What this does is take the domain name and the request URL, replace all funny chars by '.' and then try this as the name of a symlink in that dir we just created to search for the LocalSettings.php. If it finds one then it is sourced and the normal code resume. This code is my take on the drupal style install code. If that's more to your liking, take theirs; i just don't have the need to cut the domain from the left. 
For a host where security is paramount, replace the 
     if (!isset($conf)){ ...} 
part with 
     if (!isset($conf)) die("denied"); 

Now the apache config has to be changed to something like this:
         Alias /wiki/uploads /srv/http/de.lmu.fs.psy/wiki/uploads
         Alias /wiki /srv/http/common/mediawiki
Now remember how the dispatcher works. It looks at the exact domain and Request and tries to find a symlink like that, that means if you have server aliases, then these symlinks will either need to be created for every alias as well or easier use a canonicalizing rewrite rule like these
        RewriteEngine on
#       RewriteLog  /var/log/apache2/de.tehsuck/de.tehsuck-rewrite.log
#       RewriteLogLevel 3
        RewriteCond %{HTTP_HOST} !^tehsuck.de$
        RewriteRule ^(.*)$ http://tehsuck.de$1 [R=permanent,L]


Don't forget to reload
/etc/init.d/apache reload Now you still have to adjust the rules in the LocalSettings.php. The import things are:



$wgScriptPath      = "/wiki";      #This needs to be the URL part, not the path!# I took the var out of the "" because it broke for me, no idea why. 

$wgArticlePath     = $wgScript."/$1";  # Choose according to the url style you want
$wgUploadDirectory = $_SERVER['DOCUMENT_ROOT']."/w/images";
$wgUploadPath      = $wgScriptPath."/images";
$IP is a bit of a mixed bag, i had to remove it in some places otherwise it broke stuff! Remember it points to the common directory, which is wrong sometimes.
This should be it, try it out, see if it works. Debugging is best done with a mix of the error log, the rewrite log and firebug.
Note that you can easily use more than one extensions directory, i have one in a couple of instances that is called local_extensions and you only got to change your normal requires to something similar to
      require_once("local_extensions/Maintenance/Maintenance.php");

3. Short URLs

This basically boils down to the right combination of RewriteRules and variables in the LocalSettings.php. In the past one would create rules like these:
        RewriteRule ^/?wiki(/.*)?$ %{DOCUMENT_ROOT}/w/index.php [L]
But this doesn't work anymore. In Version 1.19 the ressource loader was split out. If you used the one wiki to rule them all approach explained above, then it wouldn't have worked in any case. So assume you are on version 1.19 then the right rules would be:

   RewriteRule ^/?wiki/skins(/.*)?$ /srv/http/common/mediawiki/skins$1 [L]
   RewriteRule ^/?wiki/load.php(/.*)?$ /srv/http/common/mediawiki/load.php$1 [L] 
   RewriteRule ^/?wiki(/.*)?$ %{DOCUMENT_ROOT}/w/index.php [L]

These split out the requests for direct image loading in the skins directory and the ressource loader (I'm assuming, everything will go through the loader in the future) and redirect everything else to /w/index.php where w is the folder you installed into (i hope you didn't call it wiki).
The settings in the LocalSettings.php have to be something like this then:
 
   $wgScriptPath = "/w";
   $wgArticlePath = "/wiki/$1";

Please realize that this will break the images if you opted for both solutions, so go to the next section.

4. Making both work at the same time

Now first of all observe that the Aliases we used in section 2 won't work anymore. The reason for this is the fact, that Alias is only considered after the rewrite rules are done, but the /wiki/images match is more specific than the last rule above used as a fallback. So this would give wrong results, It is correctly done via these lines

   RewriteRule ^/?wiki/images(/.*)? %{DOCUMENT_ROOT}/w/images$1 [L]
   RewriteRule ^/?wiki/skins(/.*)?$ /srv/http/common/mediawiki/skins$1 [L]
   RewriteRule ^/?wiki/load.php(/.*)?$ /srv/http/common/mediawiki/load.php$1 [L]
   RewriteRule ^/?wiki(/.*)?$ /srv/http/common/mediawiki/index.php [L]

The settings in the LocalSettings.php have to be made different though. After some tracing i realized that $wgScriptPath isn't meant to be set to the directory where your Localsettings is, but for the rest of the code. So this has to read

   $wgScriptPath         = "/wiki";
   $wgArticlePath        = "/wiki/$1";
	    $wgUploadDirectory    = $_SERVER['DOCUMENT_ROOT']."/w/images";
		    $wgUploadPath         = $wgScriptPath."/images";

Note the change in $wgArticlePath. Hope you got it all working, if not read those logs, they do help.

5. Closing Remarks

You can use this setup to do even crazier things like sharing the upload directory
I believe this can even be made to work in a .htaccess file, if the main config allows that. 
Don't give up too fast, It took me a day. Good luck.

Contact

Questions? Improvements? Drop me a line: Contact