DokuWiki

It's better when it's simple

Outils pour utilisateurs

Outils du site


fr:tips:farm

Les fermes de wiki avec DokuWiki

Cette page décrit une installation particulière de DokuWiki appelée une ferme de wiki. Dans une telle configuration, un exemplaire unique du moteur du wiki (le wiki parent ou un contrôleur de ferme ou fermier) est utilisé pour exécuter plusieurs (lire beaucoup) instances filles d'un wiki (c'est-à-dire les wikis individuels ou animaux). Le plus gros avantage est qu'une seule instance du moteur de wiki doit être maintenue et mise à jour, tout en conservant de nombreux animaux wiki avec des contenus complètement séparés (c'est-à-dire la configuration et les données) utilisant ce moteur.

L'approche plus ancienne (à l'origine sur cette page) basée sur des liens symboliques peut maintenant être trouvée sur Symlink Farm.

Les greffons et les modèles (plugins et templates) sont communs à tous les wikis : vous devez les installer manuellement dans le wiki fermier. Les modèles peuvent être propres à chaque wiki animal. Les greffons ne peuvent pas être activés ou désactivés dans le wiki animal au moment de l'écriture (8 nov. 2009), bien qu'il existe des plans pour la rendre possible. Mais il est possible de configurer les greffons par animal.

Structure de répertoire de la ferme

Le répertoire de la ferme peut théoriquement être n'importe où dans le système de fichiers, mais nous recommandons la structure suivante:

  • /var/www/farmer – l'instance de DokuWiki (le fermier)
  • /var/www/farm – la ferme contenant tous les animaux
    • /animal1
    • /animal2

Installer le fermier

Le fermier est l'instance de DokuWiki utilisée pour lancer tous les animaux.

  • Installez la dernière version stable de DokuWiki (ou une version de développement) ou utiliser une installation déjà existante avec la version correcte (ce guide suppose que vous utilisez /var/www/farmer).
  • Désactivez le gestionnaire de plugins de l'instance DokuWiki principale (il n'apparaitra alors pas dans le menu d'administration des fermes) :
    $> touch /var/www/farmer/lib/plugins/plugin/disabled

Ajout de « preload.php »

Copiez le fichier ci-dessous dans /var/www/farmer/inc/preload.php et paramétrez la variable $farm avec votre répertoire farm.

preload.php
<?php
/**
* This overwrites the DOKU_CONF. Each animal gets its own configuration and data directory.
*
* The farm ($farm) can be any directory and needs to be set.
* Animals are direct subdirectories of the farm directory.
* There are two different approaches:
*  * An .htaccess based setup can use any animal directory name:
*    http://domain.org/<path_to_farm>/subdir/ will need the subdirectory '$farm/subdir/'.
*  * A virtual host based setup needs animal directory names which have to reflect
*    the domain name: If an animal resides in http://www.domain.org:8080/mysite/test/,
*    directories that will match range from '$farm/8080.www.domain.org.mysite.test/'
*    to a simple '$farm/domain/'.
*/
 
$farm = '/var/www/farm'; // SET THIS to your farm directory
 
if(!defined('DOKU_CONF')) define('DOKU_CONF', conf_path($farm));
if(!defined('DOKU_FARM')) define('DOKU_FARM', false);
 
 
/**
 * Find the appropriate configuration directory.
 *
 * If the .htaccess based setup is used, the configuration directory can be
 * any subdirectory of the farm directory.
 *
 * Otherwise try finding a matching configuration directory by stripping the
 * website's hostname from left to right and pathname from right to left. The
 * first configuration file found will be used; the remaining will ignored.
 * If no configuration file is found, return the default confdir './conf'.
 *
 * @author Anika Henke <anika@selfthinker.org>
 * @author htaccess part based on http://www.dokuwiki.org/doku.php?id=tips:farm2#preload.php1
 * @author virtual host part based on conf_path() from Drupal.org's /includes/bootstrap.inc
 *   (see http://cvs.drupal.org/viewvc/drupal/drupal/includes/bootstrap.inc?view=markup)
 */
function conf_path($farm) {
 
    // htaccess based
    if(isset($_REQUEST['animal'])) {
        if(!is_dir($farm.'/'.$_REQUEST['animal'])) nice_die("Sorry! This Wiki doesn't exist!");
        if(!defined('DOKU_FARM')) define('DOKU_FARM', 'htaccess');
        return $farm.'/'.$_REQUEST['animal'].'/conf/';
    }
 
    // virtual host based
    $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("$farm/$dir/conf/")) {
                if(!defined('DOKU_FARM')) define('DOKU_FARM', 'virtual');
                return "$farm/$dir/conf/";
            }
        }
    }
 
    // default conf directory in farm
    if(is_dir("$farm/default/conf/")) {
        if(!defined('DOKU_FARM')) define('DOKU_FARM', 'default');
        return "$farm/default/conf/";
    }
    // farmer
    return DOKU_INC.'conf/';
}
 
 
/* Use default config files and local animal config files */
$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'),
    ),
);

Ce fichier surchargera les constances de DokuWiki (chemin vers les paramètres de configuration, etc.) avant la phase d'initialisation de DokuWiki d'après le répertoire farm que vous avez spécifié. Ceci permet d'avoir des répertoires de configuration et de données propres à chaque animal DokuWiki.

Cela fixe également une constante (DOKU_FARM) à utiliser dans d'autres codes (plugins par exemple). Il ajoute également la possibilité d'avoir un répertoire de configuration « par défaut » de la ferme (au cas où vous auriez des problèmes avec la configuration du fermier, ce qui peut arriver avec certains paramètres de réécriture).

Ceci est juste une configuration minimale d'une ferme. Vous pouvez utiliser d'autres ressources pour placer les répertoires de la ferme, comme les bases de données, etc. Vous pouvez automatiser l'ensemble du processus de création de ferme avec l'enregistrement d'une exploitation agricole, etc. à votre convenance. Soyez créatif et, si possible, partagez vos idées sur cette page.

Deux configurations différentes

Vous avez maintenant deux choix possibles de configurations fermières :

  1. configuration basée sur les hôtes virtuels :
    • besoin d'une certaine forme d'accès au serveur de créer des serveurs virtuels 1) ;
    • permet tout type de domaine, de yourdomain.org à subdomain.anotherdomain.net voire test.domain.org:8080/foo/bar/ 2) ;
    • possibilité d'utiliser l'option de configuration userewrite avec un fichier « .htaccess ».
  2. configuration basée sur les répertoires (.htaccess) :
    • votre serveur doit être capable d'utiliser les fichiers « .htaccess » sur Apache ou d'autres méthode de réécriture d'URL avec d'autres serveurs web ;
    • autorise seulement les URL de forme yourdomain.org/farm/foo, yourdomain.org/farm/bar, etc. ;
    • impossibilité d'utiliser l'option de configuration userewrite avec un fichier « .htaccess ». FIXME Est-ce vrai ? Y a-t-il une solution ?

Configuration basée sur les hôtes virtuels

Pour cette configuration, vous devez configurer l'hôte virtuel de chaque animal.

NameVirtualHost *
 
<VirtualHost *:8080>                     # ceci fonctionne seulement pour un port particulier
    ServerName domain.org
    ServerAlias *.domain.org             # ceci fonctionne pour tous les sous-domaines de domain.org
    DocumentRoot /var/www/farmer/        # la racine du document doit toujours être le répertoire de l'instance principale de Dokuwiki
</VirtualHost>
 
<VirtualHost *>
    ServerName subdomain.otherdomain.org # ceci fonctionne seulement pour un sous-domaine particulier
    DocumentRoot /var/www/farmer/        # la racine du document doit toujours être le répertoire de l'instance principale de Dokuwiki
</VirtualHost>

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.

Sur la plupart des environnements mutualisés, vous n'avez qu'à ajouter le nom du serveur (votre nom de domaine désiré avec ou sans sous-domaine) et la racine du document (pointant toujours vers le répertoire farmer) par leur IHM.

Configuration basée sur les répertoires (.htaccess)

Dans ce scénario, nous utilisons seulement un domaine unique et l'accès des animaux par l'intermédiaire des répertoires, comme http://farmer.org/farm/cat et http://farmer.org/farm/dog.

Ce fichier .htaccess (nécessaire pour rediriger l'animal consulté au fermier) doit être mis dans le répertoire /var/www/farm qui contient tous les animaux.

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

Soyez prudent si vous avez une boucle de redirection, votre DocumentRoot doit être /var/www/ (ni /var/www/farmer/, ni /var/www/farm/).

albin [dot] blaschka [at] standortsanalyse [dot] net, 25. November 2009: The buttons “Login” et al. do not work for me: If clicked, I get to the main “farmer” - instance of the wiki, not to the individual animal, called http://server/farm/animal. At the moment, I have no solution for the problem (FIXME forms seem not to get re-written), working on it, it is a showstopper for me, if I am right…looking deeper, I will report back…

benjamin [dot] seclier [at] univ [dash] nancy2 [dot] fr, 7. December 2009 : With the .htaccess script above, I have a redirection loop if I call an animal (which doesn't exist) without the last slash on the URL. For instance, if I call this bad animal :

http://my-wiki.fr/badanimal/

the preload.php file send me “This wiki doesn't exist” but if I call

http://my-wiki.fr/badanimal

I have a redirection loop.
In order to fix it, I had to modify my .htacces (which I wrote in my apache's configuration file instead) like this :

RewriteEngine On
RewriteRule index - [L]
RewriteRule ^([^/]+)/(.*) ./dokuwiki/master/$2?animal=$1 [QSA,L]
RewriteRule ^([^/]+)$ http://my-wiki.fr/$1/ [QSA,L]

Thanks to this hack, when I type an URL without the last slash, it is rewrited with this last slash and I don't have this redirection loop anymore.

Redirection d'URL avec 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):

Comme le serveur web Abysss ne figure pas “htaccess” la redirection d'URL doit être configuré dans le serveur lui-même. L'agriculteur se trouve dans le sous-répertoire “dokuwiki” et les animaux sont également en sous répertoires. La configuration suivante a fonctionné pour moi (une seule règle de redirection est nécessaire):

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)
  1. Charly 2009/10/22 10:49

Creating an Animal

You can

  • go through the following steps
  • or use the script which combines all of these steps
  • or create one master template directory which you can just copy to each new animal directory.

Step by Step

Create a Directory

The rules how to name the directory in which your animal stores all its files depends on the setup:

  • The virtual host setup needs animal directory names which reflect the virtual host: e.g. yourdomain.org or only yourdomain, subdomain.anotherdomain.net or even 8080.test.domain.org.foo.bar (for the URL example of test.domain.org:8080/foo/bar/). 3)
  • The directory / htaccess setup needs the animal directory names as they are called by the URL: e.g. yourdomain.org/farm/foo would need an animal directory called foo.

You can use the following shell commands to create the /data (together with all its subdirectories: /attic, /cache, /index, /locks, /media, /meta, /pages, /tmp) and /conf (together with the four files: local.php, local.protected.php, acl.auth.php, users.auth.php) directories and set the required permissions4).

$> cd /var/www/farm
$> mkdir -p domain.org/{data/{attic,cache,index,locks,media,meta,pages,tmp},conf}
$> cd domain.org
$> find ./ -type d -exec chmod -v 777 {} \;
$> touch conf/{local.php,local.protected.php,acl.auth.php,users.auth.php}
$> chmod 666 conf/{local.php,acl.auth.php,users.auth.php}

Note: If you have root access on the server you could also change the owner of the respective directories and configuration files to the user/group under which your webserver is running and use more restrictive (secure) chmod settings. Assuming that the webserver user and group are www-data you could use the following commands inside the animal directory.

find ./ -exec chown www-data:www-data \;
find ./ -type d -exec chmod 775 {} };
chown www-data:www-data conf/{local.php,acl.auth.php,users.auth.php}
chmod 664 conf/{local.php,acl.auth.php,users.auth.php}

Add Basic Configuration

This adds a basic configuration (with title, language, superuser and activating ACLs with useacl).

$> cat << EOF >> conf/local.php
> <?php
> \$conf['title'] = 'Farm Title';
> \$conf['lang'] = 'en';
> \$conf['useacl'] = 1;
> \$conf['superuser'] = '@admin';

Add Fixed Configuration

This adds some configuration to the local.protected.php (savedir and updatecheck) so that the admin of the wiki instance isn't able to overwrite it.

$> cat << EOF >> conf/local.protected.php 
> <?php
> \$conf['savedir'] = DOKU_CONF.'../data';
> \$conf['updatecheck'] = 0;

Set Basic Permissions

This sets some basic permissions to “all can read, members of the @admin group can do anything” which can be altered later via the ACL manager.

$> cat << EOF >> conf/acl.auth.php
> # <?php exit()?>
> * @admin 255
> * @ALL 1

Add Admin User

The following adds a user 'admin' with password 'admin', the password and the user credentials should be changed via the update profile form ASAP.

$> echo "# <?php exit()?>" > conf/users.auth.php
$> echo 'admin:$1$cce258b2$U9o5nK0z4MhTfB5QlKF23/:admin:admin@mail.org:admin,user' >> conf/users.auth.php

Using A 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.

addanimal.sh
#!/bin/bash
if [ $# -lt 1 ]; then
    echo "Usage: $(basename $0) [farm domain/directory]"
    exit 1
fi
 
ANIMAL=${PWD}/${1}
ANIMAL_TITLE=$1
 
if [ -d $ANIMAL ]; then
    echo "ERROR: $ANIMAL exists already!"
    exit 1
fi
 
echo ">> adding animal $1"
 
echo ">> creating directory structure ..."
mkdir -p ${ANIMAL}/{data/{attic,cache,index,locks,media,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}
chmod 666 ${ANIMAL}/conf/{local.php,acl.auth.php,users.auth.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['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/:admin:admin@mail.org:admin,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/farm
$> addanimal cat.domain.org
$> cd /var/www/farm
$> addanimal subdir

URL Rewriting

You can use nice URLs on a farm using the virtual host based setup. 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.

You cannot use URL rewriting in the directory (.htaccess) based setup or the Symlink Farm. FIXME Is that true? Or is there a way?

Discussion

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 @@
 <?php
 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__).'/../').'/');
 require_once(DOKU_INC.'inc/init.php');
 require_once(DOKU_INC.'inc/common.php');

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

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).

<?php
/**
 * This overwrites the DOKU_CONF. Each farm gets its own configuration and data directory.
 * Animal is not a subdirectory with the farmer, but at same level directroy level.
 * Acces farmer like this: http://domain.org/farmer/doku.php
 * Access animal like this: http://domain.org/animal/doku.php
 * 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
    return;
}

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 farm). After adding the animal directory to the farm (should be something like “domain.org.subdir”5)), 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.

1)
Cela ne signifie pas que vous ne pouvez pas le faire dans un environnement mutualisé. De nombreux hébergeurs permettent la mise en place de sous-domaines via leur interface web habituelle.
2)
bien que les sous-répertoires peut devenir compliqués
3)
This approach is based on Drupal's way of farming, see their multi-site page for more information on this.
4)
*nix systems only
5)
see Drupal's multi-site page for more information on this
fr/tips/farm.txt · Dernière modification : 2009-12-28 19:48 de ner0lph

Sauf mention contraire, le contenu de ce wiki est placé sous les termes de la licence suivante : 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