It's better when it's simple

User Tools

Site Tools


The redirect farm

A setup that is very similar to the setup that is described on this page is now part of DokuWiki. The farms documentation describes how it can be used. This page might still be useful as it describes some things like more advanced techniques how animals can be created that aren't covered in the new documentation yet that are still valid. Once this information has been transferred to the new documentation pages, this page should be deleted.

In a farm, one single copy of wiki engine (the farmer) is used to run several individual wikis (the animals). For a generic introduction, and for different approaches to set up a DokuWiki farm, see farm.

This page describes how to setup a farm in a particularly elegant way, letting the web server do the main work of redirecting HTTP requests to the pertinent wiki.


Plugins and Templates

Plugins and Templates are common to all the wikis: You have to install them manually in the farmer wiki. Templates can be chosen from each individual animal wiki. Plugins cannot be enabled or disabled in the animal wiki at the time of writing (8 Nov 2009), although there are plans to make it possible. But it is possible to configure the plugins per animal.

Two URL binding methods

There are two different methods to organize the binding of URLs to animal directories:

Method (1), using RewriteRules:

  • you need either
    • a server with a user space URL rewrite mechanism like .htaccess on Apache, or
    • access to a server configuration file where you can place RewriteRules;
  • allows only one domain; URLs have forms like;

Method (2), using virtual hosts:

  • you need some access to the server to create virtual hosts 1)
  • allows different URLs and subdomains to,
    • allows use of different ports like in
    • using subdirectories like is more complicated;

Nice URLs

You can use the userewrite config option with .htaccess, regardless of the URL rewrite method. With method (1) 2), the basedir configuration option must be set in each animal.

A Basic Installation

In this section, we will explain how to set up a most basic wiki farm with just one animal (called cow) under the URL localhost:barn/cow. The order of the installation steps is chosen so that we can test some new functionality after each step.

We will install into the following directories:

  • /var/www/farmer – the DokuWiki engine
  • /var/www/barn – contains all the animals
  • /var/www/barn/cow — one animal wiki

We will choose the URL binding method (1). For method (2), see below (Advanced Configuration).

Step 1: Create directories

Supposing your login is bob, and your web server runs in group www-data:

sudo mkdir          /var/www/{farmer,barn}
sudo chown bob      /var/www/{farmer,barn}
sudo chgrp www-data /var/www/{farmer,barn}

If you install to a private directory (say ~bob/public_html), root privilege is not needed.

Test: point your browser to http://localhost. You should see an index containing the empty directories farmer and barn. If not, debug the web server configuration.

Step 2: Setup the URL binding

Here we describe the simples URL rewrite method, using .htaccess under Apache.

Copy the following to /var/www/barn/.htaccess:

RewriteEngine On
RewriteRule ^/?([^/]+)/(.*)  /farmer/$2?animal=$1 [QSA]
RewriteRule ^/?([^/]+)$      /farmer/?animal=$1 [QSA]
Options +FollowSymLinks

Test: Point your browser to http://localhost/barn/foo. You should see the index of farmer. Point to http://localhost/barn/foo/bar. You should get a 404 error “The requested URL /farmer/bar was not found”. This shows that the URL binding works.

If the test fails:

  • .htaccess must be enabled in the in the Apache Configuration (AllowOverride All);
  • mod_rewrite must be Included.
  • If you have a redirection loop, your DocumentRoot needs to be /var/www/ (neither /var/www/farmer/ nor /var/www/barn/).

Step 3: Install the farmer

The farmer is the DokuWiki instance which is used to run all the animals.

Install a recent DokuWiki release to the farmer directory /var/www/farmer).

Disable the plugin manager of the main DokuWiki instance (so it doesn't appear in the admin menu of the animals)

touch /var/www/farmer/lib/plugins/plugin/disabled

Test: point the browser to http://localhost/farmer. You should get some response from DokuWiki, though possibly not more than a “DokuWiki Setup Error” because subdirectories are not accessible or writeable.

Unless the test brings you to the DokuWiki installer page, permissions must be corrected:

If you have root rights, do

cd /var/www/farmer
sudo chown -R bob:www-data .                # replace 'bob' by your account
find ./ -type d -exec chmod 775 {} \;  # make directories accessible
# not needed? chmod 664 conf/*                       # make config files writeable

Without root privilege, less restrictive settings are needed:

find ./ -type d -exec chmod -v 777 {} \;
chmod 666 conf/*

Test: point the browser to http://localhost/farmer. You should get to the installer page that prompts you for the name of the wiki and for a superuser registration. You do not need to fill that form since the farmer wiki will not be filled with any contents.

Step 4: Let the farmer redirect

The script preload.php is executed near the beginning of inc/init.php. It does the following:

  • Set DOKU_CONF to the animals subdirectory;
  • set a constant DOKU_FARM for use in other plugins;
  • set the $config_cascade.

The $config_cascade determines for each config file type (e.g. 'main') the order in which config files are read in. Typically, local configurations are read after the default ones in order to overwrite them. Modify this to give animal admins more or less freedom.

Copy this script into /var/www/farmer/inc/preload.php:

 * DokuWiki farm setup according to
 * @author Anika Henke <>
 * @author Michael Klier <>
 * @author Christopher Smith <>
 * @author virtual host part of conf_path() based on conf_path() from's /includes/
 *   (see
 * @license GPL 2 (
$barn = '/var/www/barn'; // SET THIS to your barn directory
if(!defined('DOKU_CONF')) define('DOKU_CONF', conf_path($barn));
if(!defined('DOKU_FARM')) define('DOKU_FARM', false);
/* Get the appropriate configuration directory from $_REQUEST */
function conf_path($barn) {
    if(isset($_REQUEST['animal'])) {
            nice_die("Sorry! This Wiki doesn't exist!");
        if(!defined('DOKU_FARM')) define('DOKU_FARM', 'htaccess');
        return $barn.'/'.$_REQUEST['animal'].'/conf/';
    } else {
        // if you want to allow direct use of the farmer wiki uncomment the following:
        // return DOKU_INC.'conf/';
        // otherwise fail with error message:
        nice_die( "Invalid request: wiki not specified" );
/* Define order in which configuration files are read */
$config_cascade = array(
    'main' => array(
        'default'   => array(DOKU_INC.'conf/dokuwiki.php'),
        'local'     => array(DOKU_CONF.'local.php'),
        'protected' => array(DOKU_CONF.'local.protected.php'),
    'acronyms'  => array(
        'default'   => array(DOKU_INC.'conf/acronyms.conf'),
        'local'     => array(DOKU_CONF.'acronyms.local.conf'),
    'entities'  => array(
        'default'   => array(DOKU_INC.'conf/entities.conf'),
        'local'     => array(DOKU_CONF.'entities.local.conf'),
    'interwiki' => array(
        'default'   => array(DOKU_INC.'conf/interwiki.conf'),
        'local'     => array(DOKU_CONF.'interwiki.local.conf'),
    'license' => array(
        'default'   => array(DOKU_INC.'conf/license.php'),
        'local'     => array(DOKU_CONF.'license.local.php'),
    'mediameta' => array(
        'default'   => array(DOKU_INC.'conf/mediameta.php'),
        'local'     => array(DOKU_CONF.'mediameta.local.php'),
    'mime'      => array(
        'default'   => array(DOKU_INC.'conf/mime.conf'),
        'local'     => array(DOKU_CONF.'mime.local.conf'),
    'scheme'    => array(
        'default'   => array(DOKU_INC.'conf/scheme.conf'),
        'local'     => array(DOKU_CONF.'scheme.local.conf'),
    'smileys'   => array(
        'default'   => array(DOKU_INC.'conf/smileys.conf'),
        'local'     => array(DOKU_CONF.'smileys.local.conf'),
    'wordblock' => array(
        'default'   => array(DOKU_INC.'conf/wordblock.conf'),
        'local'     => array(DOKU_CONF.'wordblock.local.conf'),
    'acl'       => array(
        'default'   => DOKU_CONF.'acl.auth.php',
    'plainauth.users' => array(
        'default'   => DOKU_CONF.'users.auth.php',
    'plugins' => array( // needed since Angua
        'local'     => array(DOKU_CONF.'plugins.local.php'),
        'protected' => array(
    'userstyle' => array(
        'screen'  => DOKU_CONF.'userstyle.css',
        'rtl'     => DOKU_CONF.'userrtl.css',
        'print'   => DOKU_CONF.'userprint.css',
        'feed'    => DOKU_CONF.'userfeed.css',
        'all'     => DOKU_CONF.'userall.css',
    'userscript' => array(
        'default' => DOKU_CONF.'userscript.js'

Test: Point your browser to http://localhost/barn/cow/. You should get a “DokuWiki Setup Error” explaining that “This Wiki doesn't exist!”.

Clear the farmer wiki

Pointing the browser to http://localhost/farmer, you should now get the error message “Invalid request: wiki not specified” from the above script. This is intentional: we do not want anybody to use the farmer as a wiki of its own. Therefore we can now purge the farmer directory:

rm install.php
# rm -r data ### too dangerous for the time being
mv data data.bak ### revert if there is a problem with loading the stylesheet vi csss.php

At present, css.php tests for the existence of data/pages. Hopefully, this will be fixed: → Closed. For the time being, it depends on $conf['basedir'] whether data/pages is searched in the farmer or in the animal directory. If in doubt, better do not remove the data directory.

Step 5: Create an Animal

Instead of going through the remaining steps, you can

  • use a script which combines all of them,
  • or create one master template directory which you can just copy to each new animal directory.

Create the animal directory cow:

mkdir /var/www/barn/cow

Test: http://localhost/barn/cow should bring you to a wiki start page with error messages due to a missing conf directory.

Step 6: Configure the Animal

Create a few configuration files.

In particular, create a user 'admin' with password 'admin'. The password and the user credentials should be changed as soon as possible, via the update profile form.

cd /var/www/barn/cow
mkdir conf
cat > conf/local.php <<'EOF'
$conf['title'] = 'Animal Wiki Title';
$conf['lang'] = 'en';
$conf['useacl'] = 1;
$conf['superuser'] = '@admin';
cat > conf/local.protected.php <<'EOF'
$conf['savedir'] = DOKU_CONF.'../data';
# $conf['basedir'] = '/barn/cow';
$conf['updatecheck'] = 0;
cat > conf/acl.auth.php <<'EOF'
# <?php exit()?>
* @admin 255
* @ALL 1
cat > conf/users.auth.php <<'EOF'
# <?php exit()?>

Set group and permissions:

sudo chgrp -R www-data conf
chmod 775 conf                       # allow wiki to write into this directory
chmod 664 conf/*                     # allow wiki to modify the files created above
chmod 644 conf/local.protected.php   # this one must not be modified by the wiki

Without root privilege, it is necessary to set file permissions 666 and directory permissions 777.

Test: http://localhost/barn/cow should yield a “DokuWiki Setup Error” because there is no datadir ('pages').

If you find you need to set the basedir configuration option, uncomment the basedir setting in the the above script, replacing it with the one needed for the current animal. This can be automated; see the Advanced Configuration script.

Step 7: Create Animal Data Directories

Create data directory with some subdirectories. Assuming you have a powerful shell, the following commands will do it:

cd /var/www/barn/cow
mkdir -p data/{attic,cache,index,locks,media,media_attic,media_meta,meta,pages,tmp}
sudo chgrp -R www-data data
chmod -R 775 data

Without root privilege, it is necessary to set directory permissions 777.

Test: http://localhost/barn/cow should bring you again to a wiki start page, now without error messages.

Login as admin, and update the user profile.

Advanced Configuration

Using a Bash Script to Setup an Animal

Here's a little bash script which will perform the above steps in one go inside the directory it's executed in (if you're using this with other scripts you have to make sure you cd into the designated directory before executing it). Save it as addanimal, make sure it's in your shell $PATH (i.e. by putting it into /usr/local/bin), and make it executable. It takes the domain/directory of the new animal as argument.
# This script is under public domain do with it whatever you want (yes, that includes eating it).
if [ $# -lt 1 ]; then
    echo "Usage: $(basename $0) [animal domain or directory]"
    exit 1
# set_basedir
# Author: Myron Turner
set_basedir() {
BARN=`pwd | awk -F/ '{ print $(NF)  }'`
echo "'/"$BARN"/$1/'"
if [ -d $ANIMAL ]; then
    echo "ERROR: $ANIMAL exists already!"
    exit 1
echo ">> adding animal $1"
echo ">> creating directory structure ..."
mkdir -p ${ANIMAL}/{data/{attic,cache,index,locks,media,media_attic,media_meta,meta,pages,tmp},conf}
find ${ANIMAL}/ -type d -exec chmod 777 {} \;
touch ${ANIMAL}/conf/{local.php,local.protected.php,acl.auth.php,users.auth.php,plugins.local.php}
chmod 666 ${ANIMAL}/conf/{local.php,acl.auth.php,users.auth.php,plugins.local.php}
echo ">> creating basic configuration ..."
echo "<?php
\$conf['title'] = '${ANIMAL_TITLE}';
\$conf['lang'] = 'en';
\$conf['useacl'] = 1;
\$conf['superuser'] = '@admin';" > ${ANIMAL}/conf/local.php
echo ">> setting fixed configuration ..."
echo "<?php
\$conf['savedir'] = DOKU_CONF.'../data';
# \$conf['basedir'] = `set_basedir $1`;
\$conf['updatecheck'] = 0;" > ${ANIMAL}/conf/local.protected.php
echo ">> setting basic permissions ..."
echo "# <?php exit()?>
* @admin 255
* @ALL 1" > ${ANIMAL}/conf/acl.auth.php
echo ">> adding admin user ..."
echo '# <?php exit()?>
admin:$1$cce258b2$U9o5nK0z4MhTfB5QlKF23/,user' > ${ANIMAL}/conf/users.auth.php
echo ">> IMPORTANT: Don't forget to change your admin username + password!"
echo ">> finished!"
echo ">> bye!"
exit 0
# vim:ts=4:sw=4:noet:enc=utf-8:

Usage Example:

$> cd /var/www/barn
$> addanimal
$> cd /var/www/barn
$> addanimal subdir

You may need to set the basedir configuration option. If so, uncomment the following line in the addanimal script:

 # \$conf['basedir'] = `set_basedir $1`;

This will create a basedir setting for the animal being added. Without setting this option, there have been some problems accessing new animals.3)

Using a Powershell Script to Setup an Animal

for those who prefer IIS, here is a small powershell script. You need to customize it to your Environment. Be aware, we use Active Directory and SSO. This script is still an alpha version! Features of this script:

  • Create AD Groups for Control ACL over AD Groups
  • Set NTFS Permissions on IIS Server
  • Enable SSO

Tested with IIS 8 and PHP 5.6 and Detritus.

		Legt Dokuwiki Animals an.
		Legt Dokuwiki Animals an. Inklusive AD-Gruppen, ACL, Konfig, NTFS Rechte, ....
        New-DokuwikiAnimal.ps1 -Animal IT
		Author     : Fabian Niesen
		Filename   : New-DokuwikiAnimal.ps1
		Requires   : PowerShell Version 3.0
		Version    : 0.1
		History    : 0.1 Los geht es
	[Parameter(Mandatory=$false, Position=1, ValueFromPipeline=$False)]
### Parameters ###
$wwwroot ="C:\inetpub\wwwroot"
$farmpath = $wwwroot+"\wiki"
$GroupOU = "OU=Wiki,OU=groups,DC=domain,DC=tld"
$wikiadmins = "Wiki-Admins"
$GroupPreFix = "Wiki-"
$ErrorActionPreference = "Stop"
$before = Get-Date
$date = get-date -format yyyyMMdd-HHmm
### Proof for administrative permissions (UAC) ###
If (-NOT ([Security.Principal.WindowsPrincipal] [Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole( [Security.Principal.WindowsBuiltInRole] "Administrator"))
    Write-Warning "Not run as administrator! You failed! ;)"
Write-Host "Lade ActiveDirectory Module"
  Import-Module ActiveDirectory 
Write-Warning "ActiveDirectory Module ist missing. Please install first"
If ($Animal -eq "!notset!") { 
  Write-Host ""
  $Animal = $( Read-Host "How should the animal be named?" )
  Write-Host ""
$cleananimal = $($Animal -replace " ","").ToLower()
$animalpath = $farmpath+"\"+$cleananimal
new-item -Path $animalpath -ItemType directory| Out-Null
$GroupRead = $GroupPreFix+$Animal+"-Lesen"
$GroupEditor = $GroupPreFix+$Animal+"-Editor"
$GroupManager = $GroupPreFix+$Animal+"-Manager"
$GroupAdmins = $GroupPreFix+$Animal+"-Admins"
New-ADGroup -Name $GroupRead -SamAccountName $GroupRead -GroupCategory Security -GroupScope Global -DisplayName $GroupRead -Path $GroupOU 
New-ADGroup -Name $GroupEditor -SamAccountName $GroupEditor -GroupCategory Security -GroupScope Global -DisplayName $GroupEditor -Path $GroupOU
New-ADGroup -Name $GroupManager -SamAccountName $GroupManager -GroupCategory Security -GroupScope Global -DisplayName $GroupManager -Path $GroupOU"
New-ADGroup -Name $GroupAdmins -SamAccountName $GroupAdmins -GroupCategory Security -GroupScope Global -DisplayName $GroupAdmins -Path $GroupOU 
Add-ADGroupMember $GroupAdmins $wikiadmins
Add-ADGroupMember $GroupRead $GroupEditor,$GroupManager,$GroupAdmins
$inherit = []"ContainerInherit, ObjectInherit"
$propagation = []"InheritOnly"
$modify = [System.Security.AccessControl.FileSystemRights]"Read, Write, Modify, ExecuteFile" 
$read = [System.Security.AccessControl.FileSystemRights]"ReadAndExecute"
$groups = @($GroupRead,$GroupEditor,$GroupManager,$GroupAdmins)
foreach ($group in $groups) {
  $Acl = (Get-Item $wwwroot).GetAccessControl('Access')
  $Ar = New-Object$group,$read,"None","None","Allow")
  Set-Acl $wwwroot $Acl
  $Acl = (Get-Item $farmpath).GetAccessControl('Access')
  $Ar = New-Object$group,$read,"None","None","Allow")
  Set-Acl $farmpath $Acl
  $Acl = (Get-Item $($wwwroot+"\dokuwiki")).GetAccessControl('Access')
  $Ar = New-Object$group,$read,$inherit, $propagation, "Allow")  
  Set-Acl $($wwwroot+"\dokuwiki") $Acl  
  ##NTFS Für Animal
  $Acl = (Get-Item $animalpath).GetAccessControl('Access')
  IF ($group -eq $GroupEditor -OR $group -eq $GroupManager -OR $group -eq $GroupAdmin) {
    $Ar = New-Object$group,$modify,$inherit, $propagation, "Allow")
  } Else {
    $Ar = New-Object$group,$read,$inherit, $propagation, "Allow")
  Set-Acl $animalpath $Acl
new-item -Path $($animalpath+"\data\") -ItemType directory| Out-Null
new-item -Path $($animalpath+"\conf\") -ItemType directory| Out-Null
$verz = @("attic","cache","index","locks","media","media_attic","media_meta","meta","pages","tmp")
foreach ($ver in $verz) {
new-item -Path $($animalpath+"\data\"+$ver) -ItemType directory | Out-Null
$conffiles = @("local.php","local.protected.php","acl.auth.php","users.auth.php","plugins.local.php")
foreach ($conffile in $conffiles) {
new-item -Path $($animalpath+"\conf\"+$conffile) -ItemType File| Out-Null
Copy-Item -Path $($wwwroot+"\dokuwiki\data\pages\wiki") -Destination $($animalpath+"\data\pages\") -Recurse
Copy-Item -Path $($wwwroot+"\dokuwiki\data\pages\playground") -Destination $($animalpath+"\data\pages\") -Recurse
Copy-Item -Path $($wwwroot+"\dokuwiki\data\meta\wiki") -Destination $($animalpath+"\data\meta\") -Recurse
Copy-Item -Path $($wwwroot+"\dokuwiki\data\media\wiki\logo.png") -Destination $($animalpath+"\data\media\")
### Writing 
$lc = $animalpath+"\conf\local.protected.php"
"<?php" | Out-File $lc 
"`$conf['title'] = '$Animal Wiki';" | Out-File $lc -Append 
"`$conf['lang'] = 'en';" | Out-File $lc -Append 
"`$conf['license'] = '0';" | Out-File $lc -Append 
"`$conf['useacl'] = 1;" | Out-File $lc -Append 
"`$conf['authtype'] = 'authad';" | Out-File $lc -Append 
"`$conf['superuser'] = '@$GroupAdmins';" | Out-File $lc -Append 
"`$conf['manager'] = '@$GroupManager';" | Out-File $lc -Append 
"`$conf['plugin']['authad']['account_suffix'] = '@domain.tld';" | Out-File $lc -Append 
"`$conf['plugin']['authad']['base_dn'] = 'DC=Domain,DC=tld';" | Out-File $lc -Append 
"`$conf['plugin']['authad']['domain_controllers'] = 'DC1, DC2';" | Out-File $lc -Append 
"`$conf['plugin']['authad']['sso'] = 1;" | Out-File $lc -Append 
"`$conf['plugin']['authad']['expirywarn'] = 5;" | Out-File $lc -Append 
"`$conf['plugin']['authad']['recursive_groups'] = 1;" | Out-File $lc -Append 
"`$conf['plugin']['authad']['admin_username'] = 'SSO-User';" | Out-File $lc -Append 
"`$conf['plugin']['authad']['admin_password'] = 'SSO-PW';" | Out-File $lc -Append 
"`$conf['basedir'] = '/$cleananimal/';" | Out-File $lc -Append 
"`$conf['useheading'] = 'content';" | Out-File $lc -Append 
"`$conf['sneaky_index'] = 1;" | Out-File $lc -Append 
"`$conf['disableactions'] = 'register,resendpwd,profile,profile_delete';" | Out-File $lc -Append 
"`$conf['remoteuser'] = '@$GroupRead';" | Out-File $lc -Append 
"`$conf['target']['interwiki'] = '_blank';" | Out-File $lc -Append 
"`$conf['target']['extern'] = '_blank';" | Out-File $lc -Append 
"`$conf['target']['windows'] = '_blank';" | Out-File $lc -Append 
"`$conf['subscribers'] = 1;" | Out-File $lc -Append 
"`$conf['mailfrom'] = 'wiki@domain.tld';" | Out-File $lc -Append 
"`$conf['mailprefix'] = '$Animal Wiki: ';" | Out-File $lc -Append 
"`$conf['gzip_output'] = 1;" | Out-File $lc -Append 
"`$conf['savedir'] = DOKU_CONF.'../data';" | Out-File $lc -Append
$file_content = Get-Content "$lc";
[System.IO.File]::WriteAllLines("$lc", $file_content);
##Set ACL
### Writing acl.auth.php
$aclc = $animalpath+"\conf\acl.auth.php"
$file= "acl.auth.php"
"# acl.auth.php" | Out-File $aclc 
"# <?php exit()?>" | Out-File $aclc -Append 
"# Don't modify the lines above" | Out-File $aclc -Append 
"# Access Control Lists" | Out-File $aclc -Append 
"*	@$($GroupAdmins -replace '-','%2d')	16" | Out-File $aclc -Append 
"*	@$($GroupManager -replace '-','%2d')	16" | Out-File $aclc -Append 
"*	@$($GroupEditor -replace '-','%2d')	8" | Out-File $aclc -Append 
"*	@$($GroupRead -replace '-','%2d')	1" | Out-File $aclc -Append 
$file_content = Get-Content "$aclc";
[System.IO.File]::WriteAllLines("$aclc", $file_content);
## Startseite
$startpage = $animalpath+"\data\pages\start.txt"
"====== Welcome at $Animal Wiki ======" |Out-File $startpage -Append
"==== Usage of DokuWiki ====" |Out-File $startpage -Append
"  * [[wiki:syntax|DokuWiki Syntax]]" |Out-File $startpage -Append
"  * [[playground:playground|Playgound]]" |Out-File $startpage -Append
$file_content = Get-Content "$startpage"
[System.IO.File]::WriteAllLines("$startpage", $file_content)

FNiesen 2016/04/19 09:44

URL Rewriting

You can use nice URLs. Just add the .htaccess file into your /var/www/farmer directory as if this were a singleton copy, and then each animal may set their URLs how they chose without further intervention from the farmer. If you are using the directory (.htaccess) based setup you additionally need to configure the basedir configuration option in each animal.

Enabling/disabling plugins in animals

Since Angua the plugins can be enabled and disabled per animal using the plugin manager. Activating and deactivating is stored in the plugins.local.php config file. You can globally (or locally) fix the enabling or disabling of plugins by adding their values to plugins.protected.php. But before Angua you would need to change the following:

As described in farm you need to create your own plugin manager class in order to disable or enable plugins on a per animal basis. You can put the following code into inc/preload.php as a start:

require_once DOKU_INC.'inc/plugincontroller.class.php';
class Farm_Plugin_Controller extends Doku_Plugin_Controller {
    function Farm_Plugin_Controller() {
        if (!isset($conf['disabled_plugins']) || !is_array($conf['disabled_plugins'])) {
            $conf['disabled_plugins'] = array();
    function isdisabled($plugin) {
        global $conf;
        if (parent::isdisabled($plugin)) {
            return true;
        } elseif (isset($conf['disabled_plugins'][$plugin])) {
            return $conf['disabled_plugins'][$plugin];
        } else {
            return false;
$plugin_controller_class = 'Farm_Plugin_Controller';

This farm plugin controller class first asks if a plugin is globally disabled and if not it looks for a configuration setting named $conf['disabled_plugins'][$plugin]. You can disable plugins in any configuration file with lines like

$conf['disabled_plugins']['discussion'] = '1';

FIXME This code should be further improved to hide disabled plugins in the configuration manager.

Variants for URL binding

Method (1) with Abyss Webserver

As the Abysss Webserver does not feature .htaccess the URL redirection has to be configured within the server itself. The farmer is located in the subdirectory “dokuwiki” and the animals are also in own subdirectories. The following configuration worked for me (only one redirecting rule was necessary):

Virtual Path Regular Expression: /([^/]+)/(.*)
Case Sensitive: On (default)
No conditions
Apply to subrequests too: On (default)
If this rule matches: Perform an internal redirection
Redirect to: /dokuwiki/$2?animal=$1
Append Query String: On (default)
Escape Redirection Location: On (default) — Charly 2009/10/22 10:49

Method (2), using virtual hosts

For this setup you have to configure the virtual host for each new animal.

NameVirtualHost *
<VirtualHost *:8080>                  # this only works for a specific port
    ServerAlias *         # works for all subdomains of
    DocumentRoot /var/www/farmer/     # the DokuWiki engine directory
<VirtualHost *>
    ServerName  # this only works for one specific subdomain
    DocumentRoot /var/www/farmer/     # as above, this is invariable

On most shared hosts environments you only need to add the server name (your desired domain with or without subdomain) and the document root (always pointing to the farmer directory) through their GUI.

Furthermore, you need to replace the function conf_path in farmer/inc/preload.php by the following variant:

function conf_path($barn) {
    // Method (1), using RewriteRules: get animal subdirectory from $_REQUEST
    if(isset($_REQUEST['animal'])) {
            nice_die("Sorry! This Wiki doesn't exist!");
        if(!defined('DOKU_FARM')) define('DOKU_FARM', 'htaccess');
        return $barn.'/'.$_REQUEST['animal'].'/conf/';
    // Method (2), virtual host based:
       // Use the first conf directory found by stripping the website's hostname
       // from left to right and pathname from right to left. If none is found,
       // return the default './conf'.
    $uri = explode('/', $_SERVER['SCRIPT_NAME'] ? $_SERVER['SCRIPT_NAME'] : $_SERVER['SCRIPT_FILENAME']);
    $server = explode('.', implode('.', array_reverse(explode(':', rtrim($_SERVER['HTTP_HOST'], '.')))));
    for ($i = count($uri) - 1; $i > 0; $i--) {
        for ($j = count($server); $j > 0; $j--) {
            $dir = implode('.', array_slice($server, -$j)) . implode('.', array_slice($uri, 0, $i));
            if(is_dir("$barn/$dir/conf/")) {
                if(!defined('DOKU_FARM')) define('DOKU_FARM', 'virtual');
                return "$barn/$dir/conf/";
    // optional: try default directory
    if(is_dir("$barn/default/conf/")) {
        if(!defined('DOKU_FARM')) define('DOKU_FARM', 'default');
        return "$barn/default/conf/";
    // farmer
    return DOKU_INC.'conf/';


Patch for using preload.php in an older release

If you want to get this with releases before rc2009-02-06, you could patch “init.php” like this

--- init.php
+++ init.php.patched
@@ -9,6 +9,9 @@
     return ((float)$usec+(float)$sec)-((float)$start);
   define('DOKU_START_TIME', delta_time());
+  // if available load a preload config file
+  @include(fullpath(dirname(__FILE__)).'/preload.php');
   // define the include path
   if(!defined('DOKU_INC')) define('DOKU_INC',fullpath(dirname(__FILE__).'/../').'/');

Or you could use PHP's auto_prepend_file option to include the above preload.php and overwrite the configuration settings. In this case you just need to remember that in contrast to “DokuWiki preload” not even DOKU_INC is defined when your auto_prepend_file is executed. — Christian Marg

Patch/Code for making DokuWiki commandline programs work (somehow) with DokuWiki farm

Since I set “DOKU_CONF” depending on “$_SERVER['Servername'] in my preload.php, the indexing program 'bin/indexer.php' didn't work anymore. At first I opted for a patch to “indexer.php” - it should be possible to also put that code in “preload.php” to avoid this patch. All it does is to search $argv for ”–path <path to one dokufarm-animal>“, remove the additional parameters from $argv and set DOKU_CONF accordingly:

--- indexer.php.dist    2008-09-23 13:43:00.000000000 +0200
+++ indexer.php 2008-09-23 16:54:40.000000000 +0200
@@ -2,6 +2,24 @@
 if ('cli' != php_sapi_name()) die();
+for($i = 1; $i < sizeof($argv); ++$i)
+  if ($argv[$i] == "--path") {
+       if (!isset($argv[$i+1])) {
+               die("--path: no path given.\n");
+       } else {
+               $path=$argv[$i+1];
+               unset($argv[$i],$argv[$i+1]);
+               $argv=array_values($argv);
+               if (($path= realpath($path."/conf/").'/')===false) {
+                       die("--path: path doesn't exist.\n");
+               }
+               if(!defined('DOKU_CONF')) define('DOKU_CONF', $path );
+               last;
+       }
+  }
 if(!defined('DOKU_INC')) define('DOKU_INC',realpath(dirname(__FILE__).'/../').'/');

To create an index for every animal, you just have to iterate over all animals and call the indexer script for each one.
Christian Marg 2008/09/23 17:13

Another approach is using an environment variable for setting the animal and checking for that environment variable in inc/preload.php. I've added the following snippet to inc/preload.php as the first part of the conf_path function:

    // cli
    if ('cli' == php_sapi_name() && isset($_SERVER['animal'])) {
        if (!is_dir($barn.'/'.$_SERVER['animal'])) die("Sorry! This Wiki doesn't exist!");
        if (!defined('DOKU_FARM')) define('DOKU_FARM', 'cli');
        return $barn.'/'.$_SERVER['animal'].'/conf/';

With that you can use all cli scripts by executing


Michitux 2010/10/30 14:39

Variant of the directory based setup (farmer and animal at same directory level)

If you want to have both DokuWiki farmer and animals each located in an own subdirectory of the server you have to use a different preload.php. basically you have to set additional constants in order to have anything working. of course you still have to set URL rewriting in your webserver (see above).

 * This overwrites the DOKU_CONF.
 * Animal is not a subdirectory with the farmer, but at same level directory level.
 * Access farmer like this:
 * Access animal like this:
 * Farmer on server e.g. /var/www/farmer
 * Animal on server e.g. /var/www/animal
// the home directory for all animals and the farmer located in subdirectories
$farmdir = DOKU_INC.'../';
// don't do anything if the animal doesn't exist
if(isset($_REQUEST['animal'])) {
    if(!is_dir($farmdir . $_REQUEST['animal'])) {
        nice_die("Sorry! This Wiki doesn't exist!");
    if(!defined('DOKU_CONF')) {
        define('DOKU_CONF', $farmdir . $_REQUEST['animal'] . '/conf/');
    //  correct paths according to animal and make nice looking in HTML source
    if(!defined('DOKU_URL')) define('DOKU_URL',preg_replace('/(.+)\/([^\/]+)\//','$1/'.$_REQUEST['animal'].'/',getBaseURL(true)));
    if(!defined('DOKU_REL')) define('DOKU_REL',preg_replace('/([^\/]+)\/\/([^\/]+)\/(.+)\//','/$3/',DOKU_URL));
 } else {
    // don't do anything on the farmer instance

How to have subdirectories with the virtual host setup

You can have subdirectories with the virtual host based setup (i.e. without a .htaccess file in the barn). After adding the animal directory to the barn (should be something like “”4)), you only need to create a symlink in the farmer directory like this:

ln -s . subdir

If you need to make subdirectories within a virtual directory setup work with userewrite=1, you need to add the following to the farmer's .htaccess for every subdirectory, right before RewriteRule ^$ doku.php [L]:

RewriteRule ^$                        subdir/doku.php  [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_URI}            subdir
RewriteRule ^(.*)$                    subdir/doku.php?id=$1  [QSA,L]
RewriteRule ^subdir/index.php$        subdir/doku.php

FIXME I am no rewrite rules expert, can someone please check and correct this (if necessary)? :!: Be careful, this is not fully tested and is already known to cause trouble in some setups.

How to solve the problem with the login

I had a problem with this tip, when I want to login I got to the main “farmer” - instance of the wiki, not to the individual animal, called http://server/barn/animal. To solve this, edit inc/preload.php and add these two lines into if(isset($_REQUEST['animal']). You have to change the barn directory if you choose another.

if(!defined('DOKU_URL')) define('DOKU_URL',preg_replace('/(.+)\/([^\/]+)\//','$1/**barn**/'.$_REQUEST['animal'].'/',getBaseURL(true)));
if(!defined('DOKU_REL')) define('DOKU_REL',preg_replace('/([^\/]+)\/\/([^\/]+)\/(.+)\//','/$3/',DOKU_URL));
This doesn't mean you cannot do it in a shared host environment. Many hosting providers allow the setting up of subdomains through their usual web interface.
and not with method (2) ??
See which describes one problem. Another is the corruption of the browser output.
see Drupal's multi-site page for more information on this
tips/redirect_farm.txt · Last modified: 2017-06-27 23:52 by

Except where otherwise noted, content on this wiki is licensed under the following license: CC Attribution-Share Alike 4.0 International
CC Attribution-Share Alike 4.0 International Donate Powered by PHP Valid HTML5 Valid CSS Driven by DokuWiki