Mediawiki

From HerzbubeWiki
Jump to: navigation, search

This page contains information about installing Mediawiki on a Debian system. Various parts of this document may refer to different versions of the Mediawiki package. If no specific version is mentioned, the information hopefully applies to all Mediawiki versions.


References


Packaging history

The packaging of Mediawiki in Debian has a troubled history. Because I find Mediawiki to be such an important piece of software, and I always imagine others also depend on it heavily, I find it astonishing that support for it in the Debian community is so patchy. Here is a short historical overview.

  • In the beginning there was not even a Debian package, which is why parts of this page still contain information about a manual setup.
  • The first packaged release was 1.7 in 2005.
  • Later releases were promptly packaged, but the upgrade handling usually was pretty horrible.
  • The package for release 1.15 in 2009 was the first one that provided a nice and smooth upgrade experience. From then on things became really good for a few years.
  • 1.19 was the last major upstream release to be packaged in June 2012. Package maintenance then dwindled to practically nothing, with only occasional bugfix and security updates.
  • The last package update was a non-maintainer security update in December 2014. This update resulted in package version 1.19.20+dfsg-0+deb7u3. After that the package received no more updates.
  • Even though 1.19 was an LTS release, upstream support for it ceased in mid-2015, roughly 3 years after the initial release. Because of this lack of upstream support the package was finally removed from the Debian stable distribution (jessie) at the beginning of June 2016.
  • An ITP (intent to package) was filed in January 2016, but a couple of months later nothing has come of it.
  • Just a few days before the time of writing this (beginning of July 2016) upstream has released the new version 1.27, which is another LTS version.
  • 5 July 2016: According to the ITP bug report, the new package for 1.25.5-1 has been finally accepted into the Debian archive. In the package changelog the upload is marked with the date 9 August 2015 - if I'm reading this correctly, the package was hanging around in the queue for almost an entire year!
  • Later in 2016: The 1.27.0-1 package has landed. Again, the package changelog has a strange date: 30 June 2016. This is before the last entries in the ITP bug report. I'm not fussing, though, I'm just happy that things seem to be moving again.
  • December 2017: The Jessie backports package has received a more or less steady stream of updates, so that we're now at package version 1.27.4-1~bpo8+1. It seems that Mediawiki has returned to the land of the living - at least for the moment.
  • December 2019: The upstream version 1.31.6 is packaged into the Debian package 1.31.6-1~deb10u1, which is distributed via Debian buster security updates. The last two years have seen a steady stream of package updates. The return to the land of the living has been for good, as it seems.


References


Debian setup

Packages

Install these Debian packages:

mediawiki
mediawiki-classes
php-wikidiff2


Historical notes

  • Up to version 1.10, the Debian meta package mediawiki always pointed to the latest version of Mediawiki. For instance, it pointed to the concrete package mediawiki1.7 or mediawiki1.10.
  • In version 1.12, only the Debian package mediawiki remains, there is no split anymore between a meta package and a concrete package.
  • In version 1.27 the Debian package mediawiki-extensions no longer exists, instead it's now mediawiki-classes. I'm not sure but this may just be a package rename, because mediawiki-classes has a history that goes back to version 1.7.


LocalSettings.php

The settings for the normal operation of the wiki are stored here:

/etc/mediawiki/LocalSettings.php

Settings for extensions or for customizing various aspects of Mediawiki are explained in other sections further down. Here are the most important settings that affect integration with the web server and the database:

$wgSitename         = "HerzbubeWiki";

$wgScriptPath       = "";  # The wiki resides at the base of a Virtual Host, e.g. http://wiki.herzbube.ch/
$wgScript           = "$wgScriptPath/index.php";
$wgRedirectScript   = "$wgScriptPath/redirect.php";
$wgArticlePath      = "$wgScript/$1";

$wgDBserver         = "localhost";
$wgDBname           = "mediawikidb";
$wgDBuser           = "mediawiki";
$wgDBpassword       = "secret";

Because it contains a password, the file should be protected:

cd /etc/mediawiki
chmod 400 LocalSettings.php
chown www-data:www-data LocalSettings.php


Historical note: In older versions the Mediawiki configuration used to be split into two files: AdminSettings.php (settings that are necessary to perform administrative tasks on the command line, typically database upgrade) and LocalSettings.php (settings that are necessary for the normal operation of the wiki). Nowadays everything has been merged into the single file LocalSettings.php.


Web server configuration

This is the Apache vhost configuration:

# --------------------------------------------------------------------------------
# wiki.herzbube.ch
# --------------------------------------------------------------------------------
<VirtualHost *:80>
  ServerName wiki.herzbube.ch
  Redirect permanent "/" "https://wiki.herzbube.ch/"
</VirtualHost>

# --------------------------------------------------------------------------------
# SSL Host
# --------------------------------------------------------------------------------
<VirtualHost *:443>
  ServerName wiki.herzbube.ch
  ServerAdmin webmaster@herzbube.ch
  ErrorLog ${APACHE_LOG_DIR}/wiki.herzbube.ch/error.log
  CustomLog ${APACHE_LOG_DIR}/wiki.herzbube.ch/access.log combined

  DocumentRoot /var/lib/mediawiki
  Alias /robots.txt /var/www/wiki.herzbube.ch/robots.txt

  <Directory /var/lib/mediawiki>
    php_admin_flag engine on
  </Directory>

  <Directory /var/www/wiki.herzbube.ch/>
    Require all granted
  </Directory>

  Include conf-available/pelargir-herzbube.ch-vhosts-ssl.conf
</VirtualHost>


Mediawiki package 1.31 on Debian buster

When I upgraded to Debian buster I also upgraded to Mediawiki 1.31. The upgrade was pretty painless:

  • Remove the references to the skins "Modern" and "CologneBlue" that no longer exist
  • Add the following line to LocalSettings.php just after the line that includes DefaultSettings.php:
require_once "$IP/includes/PlatformSettings.php";
  • Run this command: php maintenance/update.php


Mediawiki package 1.27 on Debian jessie and stretch

I don't recall the exact steps I had to perform to upgrade to 1.27 while I was still on Debian jessie, but the following bullet point list provides at least an overview. In Debian stretch, Mediawiki version 1.27 is still available and the system upgrade from jessie to stretch worked flawlessly.

  • In jessie the package was available from jessie-backports. The version at the time of the upgrade was 1:1.27.4-1~bpo8+1.
  • In stretch the package is available from the regular package database. The version at the time of writing is 1:1.27.4-1~deb9u1.
  • The mediawiki-extensions package no longer exists, it's now mediawiki-classes.
  • The following extensions are now part of the main package (mediawiki): Cite, SpecialInterwiki, ParserFunctions
  • The extension CategoryTree is not available via Debian package. I installed it manually via git clone.
  • The extension LDAPAuthentication is not available via Debian package. I installed it manually via git clone.


Mediawiki package 1.19 on Debian jessie

While pelargir was a MacMini, the system was running on Debian testing. When pelargir first reincarnated on a Dedicated Server I switched the system to Debian stable - in this case Debian jessie. At that time (June 2016) I discovered that the Debian package for Mediawiki has been removed from the stable distribution because the package had been virtually unmaintained for a very long time. See the packaging history section further up for more information.


I didn't want to fall back to a completely manual setup, so I decided to manually download and install the obsolete Debian package. This section lists the actions that were necessary to get this setup to run.


First, the package download:

cd /var/archive
wget http://ftp.ch.debian.org/debian/pool/main/m/mediawiki/mediawiki_1.19.20+dfsg-0+deb7u3_all.deb


The first attempt to install the package failed because some of its dependencies were missing. Here's what dpkg is seeing:

root@pelargir:~# dpkg -I /var/archive/mediawiki_1.19.20+dfsg-0+deb7u3_all.deb
[...]
 Depends: apache2 | httpd, php5, php5-mysql | php5-pgsql | php5-sqlite | php5-mysqlnd, mime-support, libjs-jquery, libjs-jquery-tipsy, libjs-jquery-cookie, libjs-jquery-form, debconf (>= 0.5) | debconf-2.0
 Recommends: mysql-server | postgresql-contrib, php5-cli, python, php-wikidiff2, mediawiki-extensions-base
 Suggests: imagemagick | php5-gd, mediawiki-math, memcached, clamav
 Conflicts: mediawiki-classes, mediawiki-extensions-base (<< 3.5~), mediawiki-extensions-confirmedit
 Breaks: fusionforge-plugin-mediawiki (<< 5.2~rc1+1~), mediawiki-extensions (<< 2.8~), mediawiki-extensions-collection (<< 2.8~), mediawiki-extensions-fckeditor, mediawiki-extensions-geshi (<< 2.8~), mediawiki-extensions-graphviz (<< 2.8~), mediawiki-extensions-ldapauth (<< 2.8~), mediawiki-extensions-openid (<< 2.8~)
 Replaces: mediawiki-extensions-confirmedit
[...]


In the end I had to install the following packages:

  • libjs-jquery-tipsy, libjs-jquery-cookie, libjs-jquery-form: These are plain dependencies.
  • php5-mysql: This is also a dependency, but dpkg didn't tell me about it because the system already had php5-pgsql. I noticed the missing package only later when I was trying to access the MySQL database.
  • mediawiki-extensions: I knew from previous experience that I would need this, not the recommended mediawiki-extensions-base
  • php-wikidiff2: This is a recommendation


Finally, install the package

dpkg -i /var/archive/mediawiki_1.19.20+dfsg-0+deb7u3_all.deb


MySQL configuration

  • Create MySQL database and restore its content from backup:
mysql -u root -p -e 'create database mediawikidb;'
mysql -u root -p mediawikidb </path/to/mediawikidb.sql
  • Create MySQL database user:
mysql -u root -p -e 'grant all privileges on mediawikidb.* to mediawiki@localhost identified by 'secret';'


Restore images from backup. Currently the only image I have is the site logo, which is stored in a subfolder "7".

cp -R /path/to/backup/images/7 /var/lib/mediawiki/images
chown -R www-data:www-data /var/lib/mediawiki/images/7


Configuration files

  • Restore AdminSettings.php and LocalSettings.php from backup and place the restored files into /etc/mediawiki
  • Update passwords in those files to new values
  • Make sure the files' privileges are correct


Apache configuration

  • Restore apache.conf from backup and place the restored file into /etc/mediawiki
  • Fix Apache symlinks. The manually installed mediawiki package created a symlink in the obsolete Apache configuration folder /etc/apache2/conf.d, so we need to fix this manually:
git mv /etc/apache2/conf.d/mediawiki.conf /etc/apache2/conf-available/mediawiki.conf
rmdir /etc/apache2/conf.d
a2enconf mediawiki
  • Configure and activate the Apache virtual host in
/etc/apache2/sites-available/wiki.herzbube.ch.conf


PHP configuration

  • On installation, the package php-wikidiff2 properly activated the Mediawiki extension for me (i.e. it executed mwenext wikidiff2.php), but it "forgot" to also activate the PHP module. Here's the command to make up for this:
php5enmod wikidiff2
  • Note that without the PHP module Mediawiki does not show any diffs - there are no error messages, neither in the browser nor in the Apache logs.


LDAP configuration

  • Enable the LDAP extension
mwenext LdapAuthentication.php
  • Create and configure the necessary groups in the LDAP directory (e.g. cn=wikiusers,ou=groups,dc=herzbube,dc=ch). See the LDAP section further down for the details.
  • In LocalSettings.php adjust the LDAP connection settings so that the LDAP server is contacted over ldapi:/// (i.e. a UNIX domain socket). Again, see the LDAP section for details.


Finally, activate all the other extensions:

mwenext Cite.php
mwenext SpecialInterwiki.php
mwenext ParserFunctions.php
mwenext CategoryTree.php


Manual setup

This chapter covers a manual installation of Mediawiki from a tar ball downloaded from http://www.mediawiki.org.

Note: Since I currently use the Debian package, this chapter is merely kept for historical reasons. Some of the information presented is probably out-of-date.


MySQL

Create a user mediawiki that has all privileges (except GRANT) to the database mediawikidb. The database itself does not need to be created now, it will be created later through the web browser setup.


Tar ball

Extract the Mediawiki tar ball to a convenient location, e.g. /var/www/mediawiki-x.y.z. Create a symlink /var/www/mediawiki that points to the directory that contains your specific version of mediawiki. This will make for an easier upgrade to a new Mediawiki version in the future.

Give the user www-data all privileges to the config directory:

chown www-data:www-data config
chmod 755 config


Web server setup

Make sure that the PHP engine is enabled for /var/www/mediawiki (or wherever you have installed the software), but that it is disabled (!) for the upload subdirectory. Also set DirectoryIndex wiki.phtml for the main directory. Last but not least you need to have an alias such as

Alias /mediawiki /var/www/mediawiki


Web browser setup

Point your web browser to http://<hostname>/mediawiki. Provide the following configuration information:

  • Site name = HerzbubeWiki
  • Sysop account = admin, password = <something>
  • Database name = mediawikidb
  • Database user = mediawiki, password = <something>


Changes in the filesystem

Now move config/LocalSettings.php to the main directory and remove write privileges for everyone from the config directory so that nobody can change the configuration by accident or on purpose:

chmod 555 config

Perform some manual changes to LocalSettings.php:

  • wgDisableUploads = false


Upgrade

Upgrade 1.15 -> 1.19 through Debian

Same drill as for 1.15, upgrade went smoothly. Well done package maintainers!!!


Upgrade 1.12 -> 1.15 through Debian

In aptitude, upgrade the package mediawiki (mediawiki-extensions has previously been upgraded). Still no automatic upgrade, so here's the usual drill:

  • Database backup
  • Perform the database upgrade (update.php prints an alert which can be ignored: "script tried to increase memory_limit to 4294967295 bytes which is above the allowed value")
cd /var/lib/mediawiki
php maintenance/update.php

That's it!?! The shortest, least painful of all the upgrades, even across 3 versions. I almost can't believe it, but it seems to be true. It appears the Mediawiki project has matured as well as the Debian packaging effort. Congratulations!


Older upgrades

See this wiki page's history if you're interested to see older upgrade paths.


Modifications to Mediawiki

Skin (theme)

Authenticated users can choose their own skin (theme) in their preferences. The default skin (theme) is set with this line in LocalSettings.php:

$wgDefaultSkin = 'vector';

The skin name to use is the internal symbolic name of the skin.

Skins must be loaded for them to be available. This happens in LocalSettings.php, with a series of wfLoadSkin function calls:

wfLoadSkin( 'Vector' );
wfLoadSkin( 'MonoBook' );
wfLoadSkin( 'Timeless' );

Skins to be loaded are searched for in the path that is defined with this line in LocalSettings.php:

$wgStylePath        = "$wgScriptPath/skins";

On pelargir this corresponds to the filesytem path

/usr/share/mediawiki/skins


Notes on some skins:

  • The skin "Timeless" is a nice-looking modern skin with a fixed-width layout. I used this for some time but ultimately returned to "Vector" because some of the pages in this wiki have very wide tables that are cut off and become unusable with a fixed-width layout.
  • The skin "Monobook" is the classic skin that Wikipedia used for a long time. It's clean and efficient and doesn't use a lot of space for margins etc. Whenever I'm in doubt and need to test something I use this skin.
  • The skin "Vector" looks quite similar to "Monobook", but feels a bit more modern. It uses spacings more generously so the same amount of content requires more space with this skin than with "Monobook". This is the skin that I'm using currently.


For Mediawiki 1.7 and above (possibly even earlier versions):

  • edit the LocalSettings.php file and change $wgLogo to point to your logo file
  • for instance, do the following
    • enable uploads by setting $wgEnableUploads = true
    • upload the logo file
    • set wgLogo = "$wgUploadPath/7/7d/Herzbube.ch-logo.png"
    • note that the upload took place into a subdirectory of the $wgUploadPath


Modify navigation bar

You may wish to modify the navigation bar on the left, e.g. remove some unnecessary links such as "Community portal".

For versions >= 1.5:


Additional namespaces

The system defines a number of default namespaces with numeric IDs < 100. Additional namespaces can be defined by setting the following variable in LocalSettings.php:

$wgExtraNamespaces =
  array(100 => "Foo",
        101 => "Foo_Talk",
        102 => "Bar",
        103 => "Bar_Talk"
        );


Namespace protection

Certain namespaces can be protected through the wgNamespaceProtection setting, however this is available only in the upcoming 1.10 version of Mediawiki.

Another way to protect certain pages involves user groups.


User groups

Details about user rights and groups can be found on http://www.mediawiki.org/wiki/Manual:User_rights.

You can place users into groups on the Special:Userrights page.

You can assign privileges to a group by editing the file LocalSettings.php in the following way (note that you create groups by simply mentioning them in LocalSettings.php):

$wgGroupPermissions['ninja']['delete'] = true;
$wgGroupPermissions['ninja']['block'] = true;
$wgGroupPermissions['ninja']['bot'] = true;
[...]

The implicit group for anonymous users is '*'. The implicit group for logged in users is 'user'. Therefore, modifying the privileges for these 2 special groups would look like this:

$wgGroupPermissions['*'    ]['createaccount']   = true;
$wgGroupPermissions['user' ]['read']            = true;


Protecting a namespace

This section contains a copy of the instructions found on http://www.mediawiki.org/wiki/Manual:Preventing_access. If something does not work as expected, that page should be consulted as a reference, and also to see if the procedure has been updated.

For the moment I prefer manually editing some .php files to the NameSpacePermissions extension because both methods can be considered "hacking", but the extension seems to be more obscure...

If we assume that we want to protect the namespace foo whose ID is 100, so that only users in the group bar can read/edit pages, the following needs to be done:

  • change a few lines in Title.php inside the userCanRead() function (a few more lines are included for orientation).

Title.php (old)

if( $wgUser->isAllowed('read') ) { 
  return true;
} else {
  global $wgWhitelistRead;

Title.php (new)

if( $this->getNamespace() == 100 ) {
  return $wgUser->isAllowed('view_namespace_foo');
}
if( $wgUser->isAllowed('read') ) { 
  return true;
} else {
  global $wgWhitelistRead;
  • add the following lines to LocalSettings.php
# Create group
$wgGroupPermissions['foo']['edit'] = true;
# Assign the permission to the group
$wgGroupPermissions['foo']['view_namespace_foo'] = true;
  • transclusion cannot be avoided unless you have an 1.10alpha or later version of Mediawiki


Searched namespaces

Users who are logged in can change the namespaces that are searched by default in their user preferences. To modify the defaults for anonymous users, edit the file LocalSettings.php to contain the following list:

$wgNamespacesToBeSearchedDefault = array( NS_MAIN => true, NS_USER => true );

In the example above, the User namespace will be searched in addition to the Main namespace (which is the only one searched by default).

Note: Newly created user accounts inherit this setting, but existing user accounts remain unaffected (even if they have not changed their user preferences from the defaults).


No anonymous edits

By default, anonymous (i.e. not logged in) users have permission to edit wiki pages. This can be disabled by placing the following line in LocalSettings.php:

$wgGroupPermissions['*']['edit'] = false;

Note: The "edit" link on top of each page is still shown, but if an anonymous user clicks on the link he will be asked to login.


Disable account registration

By default, account registration for the Mediawiki site is enabled. This can be disabled by placing the following line in LocalSettings.php:

$wgGroupPermissions['*']['createaccount'] = false;

The "log in" link on top of each page is still labelled "log in / create account", but the "create account" link on the login page is no longer visible, and if a user directly goes to the signup page, she will be told that account registration by anonymous users is not possible.


Extensions

Managing extensions

To view a list of installed Mediawiki extensions, go to Special:Version.

The main Debian package mediawiki includes a few useful extensions. Installing the package does not automatically enable those extensions, you still have to manage them by adding a line like this to LocalSettings.php:

wfLoadExtension( 'Cite' );

After enabling an extension you may still need to add stuff to LocalSettings.php to make the extension work as desired.


If you want to install a custom extension (i.e. one that is not available via Debian package), then you can drop it into the folder

/usr/share/mediawiki/extensions

This is also the folder where you can see the list of available extensions in the filesystem.


Cite

Cite is an extension which allows a user to create footnotes. For details, see the extension website.

Cite is available through the main Debian package mediawiki. The extension is enabled by adding this to LocalSettings.php:

wfLoadExtension( 'Cite' );

The extension does not require any configuration.


Special:Interwiki

Interwiki links normally must be managed by modifying a database table (details are available on this page). The Special:Interwiki extension exposes the table and the editing process through the page Special:Interwiki. Other extensions for managing Interwiki links can be found here.


The Special:Interwiki extension is available through the main Debian package mediawiki. The extension is enabled by adding this to LocalSettings.php:

wfLoadExtension( 'Interwiki' );


Configure the extension by adding these lines to the end of LocalSettings.php:

# InterWiki extension
$wgGroupPermissions['*']['interwiki'] = false;
$wgGroupPermissions['sysop']['interwiki'] = true;


Interwiki links can now be managed by logging in as an administrator and going to Special:Interwiki.


ParserFunctions

The ParserFunctions extension is available through the main Debian package mediawiki. The extension is enabled by adding this to LocalSettings.php:

wfLoadExtension( 'ParserFunctions' );


The extension does not require any configuration. The extension provides additional parser functions that can be used on pages and in templates, such as

{{#ifexpr ...}}


The extension is enabled because various templates copied from Wikipedia use these expressions. For details, see the extension website.


LDAP Authentication

LDAP Authentication is an extension which enables LDAP to be used as an authentication backend. See the LDAP section on this page for more details.


CategoryTree

The CategoryTree extension must be installed manually:

cd /var/lib/mediawiki/extensions
git clone https://gerrit.wikimedia.org/r/p/mediawiki/extensions/CategoryTree

The extension is enabled by adding this to LocalSettings.php:

wfLoadExtension( 'CategoryTree' );

The extension displays the hierarchy below a category as a tree. When viewing a category page, sub-categories have clickable widgets that allow the user to expand or collapse the tree for that sub-category. The Special:CategoryTree page lets the user specify a category whose tree should be displayed. Last but not least, it is possible to display a category tree inline in a page using the following syntax:

<categorytree mode=pages>Foo</categorytree>

The default clickable widgets are simple "+" and "-" characters. This looks quite ugly, but the widgets can be changed by editing the following pages and specifying a different character. Note that you must have administrator privileges to edit these pages.


To further configure CategoryTree, add the following lines to the end of LocalSettings.php:

# ----------------------------------------------------------------------
# CategoryTree extension
# ----------------------------------------------------------------------
# We want to see pages when we expand a node on a category page
$wgCategoryTreeCategoryPageOptions["mode"] = "pages";
# Allows to display a fully expanded tree with the root category at the base
$wgCategoryTreeMaxDepth = array('CT_MODE_PAGES' => 50, 'CT_MODE_ALL' => 50, 'CT_MODE_CATEGORIES' => 50);


Using the template Template:Category_tree_all it is now possible to show a fully expanded category tree. See the template page for an example.


I have not been able to convince CategoryTree to display a category page, or the special page, with a tree with an initial depth greater than 1. I have tried the following settings, but they did not work:

$wgCategoryTreeSpecialPageOptions["depth"] = 10;
$wgCategoryTreeCategoryPageOptions["depth"] = 10;


At the moment there is also another unresolved issue: When the category tree is expanded, it displays CSS style information.


LDAP

Overview

LDAP Authentication is an extension which enables LDAP to be used as an authentication backend. For details, see the extension website.

The extension has plenty of configuration options that are fairly well documented. The main problem of getting this to work was that up until now my LDAP directory structure used different mechanisms for group support. The LDAP Authentication extension introduced me to the object class "groupOfUniqueNames", which might be a good solution for other applications that use groups as well.

Additional notes:

  • LocalSettings.php now contains another password
  • Users must now be created in LDAP, it is no longer possible to login as a bureaucrat or sysop and create an account
  • Passwords must now be changed in LDAP
  • I formerly logged in as user "Herzbube". This user still exists in the Mediawiki database, but it is no longer possible to login as "Herzbube". Also, I am too lazy to "convert" the account to my new personal account, which means that all edits prior to switching to LDAP authentication are still credited to it.
  • Also see the OpenLDAP page on this wiki


PHP LDAP support

As a prerequisite, PHP must be properly configured as an LDAP client.

  • The Debian package php-ldap must be installed (older Debian versions: php5-ldap)
  • Hash links in /etc/ssl/certs must be set up correctly
  • PHP will query the LDAP server as a local LDAP client. If ldap.herzbube.ch is used for connections, then the server requires TLS and the following line must be present in the system-wide client configuration file /etc/ldap/ldap.conf. The line must refer to the entire CA certificate chain used for verifying the LDAP server certicate. Note that the line may already be present due to other clients (e.g. ldapsearch) that already need to contact the LDAP directory.
TLS_CACERT /etc/ssl/certs/cacert.org.certchain


Prepare the LDAP directory

Users

Mediawiki will refer to user entries below ou=users,dc=herzbube,dc=ch. Because I do not plan to store user preferences in LDAP, the current user entries do not need to be modified. All that is required from them is the presence of the uid attribute, and the ability to use them for binding (i.e. the userPassword attribute must be present).


Groups

Mediawiki not only has support for user groups, it actively employs them even even for basic things such as identifying who is an Admin user. For this reason, new groups must be added to the LDAP directory.

Mediawiki will refer to group entries below ou=group,dc=herzbube,dc=ch:

  • Group entries must be of object class groupOfUniqueNames
  • Group entries refer to their members via the attribute uniqueMember
  • uniqueMember requires that its references are full DNs (e.g. cn=admin,ou=users,dc=herzbube,dc=ch)

The following groups are needed:

  • cn=wikiusers,ou=groups,dc=herzbube,dc=ch
    • All users that should be able to login to Mediawiki must be members of this group
    • I use this because I do not want all POSIX accounts (or in fact all user entries below ou=users,dc=herzbube,dc=ch) to be able to login to Mediawiki
    • To ensure this, in other applications I have enhanced user entries with an additional object class in order to mark the entry as an account for that application. For instance, Bugzilla accounts have the additional object class bugzillaAccount
    • Although this group formally is a Mediawiki group, it is not actually required by Mediawiki
  • cn=sysop,ou=groups,dc=herzbube,dc=ch
    • Only contains the "admin" user
  • cn=bureaucrat,ou=groups,dc=herzbube,dc=ch
    • Only contains the "admin" user
  • The page Special:ListGroupRights also lists a group named "Users". No LDAP entry is needed for this group, though, because all users automatically belong to this implicit group. This can be verified by examining the table "user_groups" in Mediawiki's database.


Activate the extension

LDAP Authentication must be installed manually:

cd /var/lib/mediawiki/extensions
git clone https://gerrit.wikimedia.org/r/p/mediawiki/extensions/LdapAuthentication

The extension cannot be enabled with the new wfLoadExtension function because extension.json would be missing. Instead the extension must be enabled in the old style by adding these two lines to LocalSettings.php:

require_once ('extensions/LdapAuthentication/LdapAuthentication.php');
require_once ('includes/AuthPlugin.php');


Configure the extension

The extension is configured by adding code to the end of LocalSettings.php. A full list of possible options is available on the extension site.


The following snippet is my current configuration.

# No need for require_once( "$IP/extensions/LdapAuthentication.php" );
# -> this is done automatically by a mechanism provided by Debian's
# mediawiki-extensions package. All that is required is that the
# extension be enabled "mwenext".

# ---------- Basic configuration ----------
# Instantiate the extension
$wgAuth = new LdapAuthenticationPlugin();
# Any domain name can be used here; this is not a DNS name,
# it's simply a name that will be displayed on the login page
$wgLDAPDomainNames = array(
  'wiki.herzbube.ch'
);
# Normally this specifies the DNS name or the IP address of
# the host that runs the LDAP server. A typical name is
# "localhost". Because we use a UNIX domain socket (ldapi:///)
# we must specify "/" here.
$wgLDAPServerNames = array(
  'wiki.herzbube.ch' => '/'
);
# Do not allow local Mediawiki users, only allow LDAP users
$wgLDAPUseLocal = false;
# The value "ldapi" is obviously used to connect to the server
# over a UNIX domain socket (ldapi:///). This is not officially
# documented but can be seen when looking at the source code.
# If TLS were required we would specify "tls" here.
$wgLDAPEncryptionType = array(
  "wiki.herzbube.ch" => "ldapi"
);
# Bind as this user to make searches
$wgLDAPProxyAgent =  array(
  'wiki.herzbube.ch' => 'cn=readonly-users,ou=users,dc=herzbube,dc=ch'
);
$wgLDAPProxyAgentPassword = array(
  'wiki.herzbube.ch' => 'secret'
);
# ---------- Base DNs for searches ----------
# Since we are defining explicit base DNs for user/group searches,
# it is unclear how $wgLDAPBaseDNs is going to be used. Somewhere
# I have read that it is still necessary, but I don't know what for.
$wgLDAPBaseDNs = array(
  'wiki.herzbube.ch' => 'dc=herzbube,dc=ch'
);
$wgLDAPUserBaseDNs= array(
  'wiki.herzbube.ch' => 'ou=users,dc=herzbube,dc=ch'
);
$wgLDAPGroupBaseDNs= array(
  'wiki.herzbube.ch' => 'ou=groups,dc=herzbube,dc=ch'
);
# ---------- Options related to user entries ----------
# The attribute whose value must match the user name
# specified at login time
$wgLDAPSearchAttributes = array(
  'wiki.herzbube.ch' => 'uid'
);
# ---------- Options related to group entries ----------
# Mediawiki groups are not POSIX groups, therefore they are not
# represented by entries of the posixGroup object class. A useful
# alternative is the core schema object class groupOfUniqueNames,
# which is a very generic way to gather a list of unique
# references to other DNs.
$wgLDAPGroupObjectclass = array(
  "wiki.herzbube.ch"=>"groupOfUniqueNames"
);
# The name of the attribute that identifies the group.
$wgLDAPGroupNameAttribute = array(
  "wiki.herzbube.ch" => "cn"
);
# The name of the attribute that stores the user references.
# uniqueMember is a core schema attribute type.
$wgLDAPGroupAttribute = array(
  "wiki.herzbube.ch" => "uniqueMember"
);
# Whether or not the group references the user with a full DN.
# We must say "true" here because the attribute uniqueMember
# requires the reference to be a full DN.
$wgLDAPGroupUseFullDN = array(
  "wiki.herzbube.ch" => true
);
# Mediawiki always converts the first letter of the user name
# to upper case, but the LDAP entries for users always use
# lower case.
$wgLDAPLowerCaseUsername = array(
  "wiki.herzbube.ch"=>true
);
# Normally it is expected that groups refer to their members.
# If this were set to true, it would be the other way round
# and users would refer to their groups via the "memberOf"
# attribute.
$wgLDAPGroupsUseMemberOf = array(
  "wiki.herzbube.ch" => false
);
# ---------- Login restrictions ----------
# Login is not allowed if the user entry does not match the
# restrictions specified here.
# NOTE: Defining this property is not really necessary since we
# are using $wgLDAPRequiredGroups. This property is here just so
# that its usage can be documented and demonstrated.
# - The vale of this property is enclosed in "()" but otherwise
#   it is used verbatim as the filter criteria in an LDAP search.
#   This means that we can use the regular LDAP search criteria
#   syntax here (e.g. "objectClass=*"
# - The base DN used for searching is the user's DN previously
#   obtained by the initial search for $wgLDAPSearchAttributes
#   below $wgLDAPUserBaseDNs
# - The check is successful if the search has a non-null result,
#   i.e. at least one entry must be returned by the search
# NOTE: This is commented because in the current release of the
# module shipped with Debian (2.0a) the code merely checks for
# the presence of the attribute specified here. Apparently this
# is a bug that crept into the code at some time, but has been
# fixed in the meantime. See this discussion:
# http://www.mediawiki.org/wiki/Extension_talk:LDAP_Authentication#LDAP_search_for_special_entry_12928
# Also check out the current code
# https://gerrit.wikimedia.org/r/gitweb?p=mediawiki/extensions/LdapAuthentication.git;a=tree
#$wgLDAPAuthAttribute = array(
#  "wiki.herzbube.ch" => "objectClass=uidObject"
#);
# Login is not allowed if a user is not a member of the groups
# specified here. In order to use this property, various other
# group-related properties must also be configured.
$wgLDAPRequiredGroups = array(
  "wiki.herzbube.ch"=>array(
    "cn=wikiusers,ou=groups,dc=herzbube,dc=ch"
  )
);


Local patching

Currently with the "git cloned" version of the extension and the 1.27 version of Mediawiki, the extension does not need any local patching. Before the current setup, local patching was necessary to prevent TLS connection errors that would fill the Apache error log with many pointless messages. Check out the page history if you need to see details. This is an example of an error log message as it used to appear in the Apache error log:

[Fri Jul 01 17:57:51.536670 2016] [:error] [pid 4195] [client 212.101.18.224:58504] PHP Warning:  ldap_start_tls(): Unable to start TLS: Can't contact LDAP server in /usr/share/mediawiki-extensions/ldapauth/LdapAuthentication.php on line 580, referer: https://wiki.herzbube.ch/index.php?title=Mediawiki&action=submit


Open issues

At the moment there is an unresolved issue: When I try to log in I am shown a "database error" message, however I can simply ignore the error message and navigate to another page to make the error go away. After that I am logged in.

The extension website has the following warning posted at the top:

Warning: The extension has not been fully updated for MediaWiki 1.27+ (AuthManager); LdapAutoAuthentication will not work with that version. See gerrit:286705 for details.


Debugging

Add the following lines to LocalSettings.php to write debugging information into a file. Warning: Passwords are written to the file in clear text!

$wgLDAPDebug = 4;
$wgDebugLogGroups = array(
  'ldap' => '/tmp/mediawiki.ldap.debug.log',
);


Troubleshooting

For general debug output, add the following line to LocalSettings.php:

$wgDebugLogFile = '/tmp/mediawiki.debug.log';

If the debug output of a specific extension is desired, it may be necessary to define other, extension-specific variables. Also, it is possible to redirect debug output to a different log file depending on which group is used by the logging statement. For instance, the "LDAP Authentication" extension uses the group "ldap" for its logging statements, therefore the following definition in LocalSettings.php redirects the extension's output to a separate file:

$wgDebugLogGroups = array(
  'ldap' => '/tmp/mediawiki.ldap.debug.log',
);              


How to clone a Mediawiki installation for local use with MAMP

Overview

This HOWTO explains how I made a clone of HerzbubeWiki so that I could use it locally on my MacBook, together with MAMP, while travelling around the world. The HOWTO is not very generic but rather specific to my installation - you will have to figure out yourself how to adapt the examples to your own needs.


Install the Mediawiki software on the MacBook

cd /Applications/MAMP/htdocs
tar xfvz ~/Downloads/mediawiki-1.12.0.tar.gz
chown -R patrick:patrick mediawiki-1.12.0/
ln -s mediawiki-1.12.0/ mediawiki
cd /Applications/MAMP/htdocs/mediawiki
mv config/LocalSettings.php .
chmod 400 LocalSettings.php


Install the Cite.php extension on the MacBook

cd /Applications/MAMP/htdocs/mediawiki/extensions
tar xfvz ~/Downloads/Cite-MW1.12-r33026.tar.gz
chown -R patrick:patrick Cite/
  • Add the following line to LocalSettings.php:
require_once('extensions/Cite/Cite.php');


Install the database contents on the MacBook

  • On the server, create a database dump
cd /tmp
mysqldump --add-drop-table -u root -p mediawikidb >mediawikidb.sql.dump
gzip mediawikidb.sql.dump
  • Also on the server, create a tar file with the images
cd /var/lib/mediawiki/images
tar cfp /tmp/mediawiki.images.tar *
gzip /tmp/mediawiki.images.tar
  • On the MacBook, restore the database (you will have to enter the password for MAMP's MySQL user root, which is "root" by default)
cd ~/Downloads
scp root@osgiliath:/tmp/mediawikidb.sql.dump.gz .
gunzip mediawikidb.sql.dump.gz
/Applications/MAMP/Library/bin/mysql -u root -p mediawikidb <mediawikidb.sql.dump
  • Also on the MacBook, restore the images
cd ~/Downloads
scp root@osgiliath:/tmp/mediawiki.images.tar.gz .
cd /Applications/MAMP/htdocs/mediawiki/images
tar xfvz ~/Downloads/mediawiki.images.tar.gz


Final configuration

  • Make the following changes to LocalSettings.php to achieve the same configuration as on the server
# enable uploads
$wgEnableUploads       = true;

# new logo (first line only needs to be present because this is not the Debian machine)
$wgUploadPath       = "$wgScriptPath/images";
$wgLogo             = "$wgUploadPath/7/7d/Herzbube.ch-logo.png";

# no anonymous edits
$wgGroupPermissions['*']['edit'] = false;

# new users get the following search settings
$wgNamespacesToBeSearchedDefault = array( NS_MAIN => true, NS_USER => true );


That's it

Point the browser at http://localhost:8888/mediawiki/.