Carnet Wiki

Version 15 — Mai 2007 — 81.185.xx.xx

Résumé

-  Installez les fichiers de SPIP dans un répertoire ; appelons-le spip/, c’est la racine de votre système :
svn co svn://trac.rezo.net/spip/spip/ spip/ ;
-  Installez les fichiers de mutualisation facile en les chargeant depuis la zone, vers un répertoire quelconque :
svn co svn://zone.spip.org/spip-zone/_plugins_/_test_/mutualisation/ spip/mutualisation/ ;
-  Faites pointer les URLs à mutualiser vers le répertoire racine spip/ (VirtualHost) ;
-  Créez un répertoire sites/ à l’intérieur du répertoire racine, dans lequel le serveur peut écrire.
-  Assurez-vous d’avoir un utilisateur MySQL autorisé à créer des bases de données (optionnel) ;
-  Créez le fichier spip/config/mes_options.php avec :

<?php


require _DIR_RACINE.'mutualisation/mutualiser.php';


$site = str_replace('www.', '', $_SERVER['HTTP_HOST']);
    if ($site != $_SERVER['HTTP_HOST']) {
        include_spip('inc/headers');
        redirige_par_entete('http://'.$site.'/');
    }
    $ site  =   strtolower($site ); 


define ('_INSTALL_HOST_DB', 'localhost');
    define ('_INSTALL_USER_DB', 'loginsql');
    define ('_INSTALL_PASS_DB', '123456HDJ');
    define ('_INSTALL_NAME_DB', 'mutu_'.prefixe_mutualisation($site));
    define ('_INSTALL_TABLE_PREFIX', 'spip');


// options par defaut pour tous les sites, surchargeables par sites/xx/config/mes_options.php
    $type_urls='html';


demarrer_site($site,
        array(
            'creer_site' => true,
            'creer_base' => true,
            'mail' => 'fil@rezo.net',
            'code' => 'rhooo'
        )
    );
?>

La mutualisation, qu’est ce ?

Supposons que vous avez plusieurs sites sous SPIP... Vous pouvez bien sûr installer les fichiers de SPIP en plusieurs exemplaires, mais vous perdez ainsi de la place et surtout de la facilité de maintenance.

Mutualiser des sites SPIP, c’est mettre en commun ce qui peut l’être (le moteur de squelette, l’interface privée etc), tout en proposant des données séparées.

Comment mutualiser ?

Il existe déja une documentation complète (mais complexe) sur la Mutualisation du noyau SPIP. Ce code est en train d’être revu, dans la branche de développement de SPIP 1.9.3, de manière à simplifier le procédé.

Voici où nous en sommes, à la révision 9330 de SPIP et 12308 du plugin :

-  Installez les fichiers de SPIP dans un répertoire, comme vous le ferez classiquement ; appelons-le spip/, c’est la racine de votre système.
-  Créez un répertoire sites/ à l’intérieur du répertoire racine.

Le principe est simple : à chaque site, qu’on identifiera par une variable $site, correspond à un répertoire sites/$site/ ; ce répertoire contient lui-même les quatre sous-répertoires de données du site :
-  spip/sites/$site/config/ contient les données de connexion connect.php et éventuellement le fichier mes_options.php du site ;
-  spip/sites/$site/IMG/ contient les images et documents associés aux articles de ce site ;
-  spip/sites/$site/tmp/ contient les fichiers cache de tout type ;
-  spip/sites/$site/local/ contient les images calculées (vignettes réduites, formules TeX...).

Comment identifier un site ?

Prenons l’exemple d’un système mutualisé qui sert les pages pour différents noms de domaines, chose.tld et truc.tld.

Il faut, tout d’abord, que http://chose.tld/ et http://truc.tld/ pointent tous deux vers la racine du système : pour cela il faut :

  1. que le DNS pointe vers le serveur ;
  2. que le serveur soit configuré de manière à servir ces domaines depuis notre répertoire spip/ (directive VirtualHost, commande « Héberger un domaine » d’AlternC, etc.)
    Voir article 2194

Une fois ceci effectué, nous avons donc deux sites, tous deux servis par la même installation de SPIP. Bien évidemment, si on installe le site maintenant, il répondra de la même manière aux deux noms de domaines, il faut donc agir avant de procéder à l’installation du site.

On commence par créer un fichier central de configuration, dans spip/config/mes_options.php, qui contient :

<?php
    require _DIR_RACINE.'ecrire/inc/mutualiser.php';
    demarrer_site($_SERVER['HTTP_HOST']);
?>

Cette configuration est exécutée à chaque hit sur un fichier de SPIP, et définit les répertoires où le script ira chercher les images, la connexion à la base de données etc, comme indiqué plus haut.

En l’occurrence, nous avons décidé que chaque site serait représenté par la valeur de $_SERVER['HTTP_HOST'], c’est-à-dire truc.tld ou chose.tld. Si le site n’est pas installé (le répertoire spip/sites/truc.tld/ n’existe pas), la commande demarrer_site($site) le signale et vous demande de créer ce répertoire ainsi que les quatre sous-répertoires indispensables.

<blockquote class="spip">

www ou pas ?

Il est possible de décider que l’url http://www.chose.tld/ doit être identifiée avec l’url http://chose.tld/, en d’autres termes qu’il ne s’agit que d’un seul et même site ; il faut dans ce cas être un peu plus subtil :

<?php
    require _DIR_RACINE.'ecrire/inc/mutualiser.php';
    $site = str_replace('www.', '', $_SERVER['HTTP_HOST']);
    demarrer_site($site);
?>

Cependant, une autre possibilité est largement préférable : il faut rediriger http://www.chose.tld/ vers http://chose.tld/ (ou l’inverse), en faisant par exemple :

<?php
    require _DIR_RACINE.'ecrire/inc/mutualiser.php';
    $site = str_replace('www.', '', $_SERVER['HTTP_HOST']);
    if ($site != $_SERVER['HTTP_HOST']) {
         include_spip('inc/headers');
        redirige_par_entete('http://'.$site.'/');
    }
    demarrer_site($site);
?>
</blockquote>

Quoiqu’il en soit, le système de nommage du site est ouvert et peut se baser sur ce que l’on veut ; si on héberge par exemple sur ce système mutualisé tous les sites des sections locales de chose.tld, par exemple antananarivo.chose.tld, capetown.chose.tld, beijing.chose.tld, on fera :

<?php
    require _DIR_RACINE.'ecrire/inc/mutualiser.php';
    if (!preg_match(',^(www\.)?(.*)\.chose.tld$,', $_SERVER['HTTP_HOST'], $r))
        die ("Erreur : ce site n'est pas une chose.tld : ".$_SERVER['HTTP_HOST']);
    demarrer_site($r[2]); // $r[2] correspond au (.*) de l'expression rationnelle
?>

et dans ce cas les répertoires créés seront spip/sites/antanarivo/, spip/sites/capetown/, spip/sites/beijing/...

Partager une même base de données ?

Il est bien clair que les sites ne doivent pas mélanger leurs données ; en revanche il est possible (mais pas forcément souhaitable) de n’utiliser qu’une seule et unique base de données pour l’ensemble des sites d’un même système de mutualisation. On séparera alors les différents sites en utilisant des tables dont les noms seront préfixés différemment.

Pour utiliser les préfixes de table, dans notre exemple ci-dessus, on utilisera antanarivo comme préfixe pour les tables du site antanarivo, etc ; ainsi dans la base de données (unique), on aura des tables antanarivo_articles pour les articles du site antanarivo, et beijing_articles pour les articles du site beijing.

Pour faire cela, il suffit d’indiquer l’option suivante, dans l’appel à demarrer_site() :

    demarrer_site($site, array('table_prefix' => true)); 

Cette option « rabote » un peu la variable $site de manière à en faire un préfixe valide pour MySQL (12 caractères, lettres ou chiffres, pas de points ni de tiret, commence par une lettre). Le préfixe est enregistré dans la variable globale de SPIP $GLOBALS['table_prefix'].

Pour tenter de garantir l’unicité (tant que possible), si le nom du site est trop long (saint-gravier-la-bruyarde), le préfixe sera de la forme 'saintg'+6 derniers caractères de la clé md5($site), afin d’éviter un clash avec saint-gravier-le-feuillu. Afin d’éviter de confondre deux sites comme a.b.domaine.tld et ab.domaine.tld, la fonction appose aussi un bout de md5 si le nom du site contient des caractères autres que lettres ou chiffres (un point, par exemple).

Si l’on utilise des bases différentes, on peut aussi changer le préfixe, mais pour le coup ça n’a pas d’importance. C’est lors de la connexion initiale (« installation du site ») qu’on précisera la base à employer, après l’avoir éventuellement créée, depuis SPIP ou dans l’interface AlternC.

Héberger des sites pour d’autres personnes

Dès lors que l’on veut héberger des sites pour d’autres que soi-même, on est confronté au processus d’installation de SPIP qui exige le login, mot de passe de la base de données, et permet ensuite à celle qui installe de choisir sa base parmi la liste des bases disponibles. S’il faut créer une base par utilisateur, ou si on doit prendre le risque de laisser l’installation partir sur les données d’un autre site (suite à une fausse manipe de sélection de la base ou du préfixe), on perd un des avantages de la mutualisation.

Considérons ici le scénario d’une seule base de données partagée par tous les sites : SPIP permet désormais de préciser dans mes_options.php une ou plusieurs des données de connexion à la base :

define ('_INSTALL_HOST_DB', 'localhost');
define ('_INSTALL_USER_DB', 'truc.tld');
define ('_INSTALL_PASS_DB', '1234FGH78');
define ('_INSTALL_NAME_DB', 'touslestructld');

Ces données étant ainsi figées, l’installation de SPIP ne les demande pas à la personne qui installe le site, mais lui signale que la donnée est fournie par l’hébergeur. Cette astuce est aussi bien pratique si on veut installer beaucoup de sites pour soi-même : on peut par exemple définir _INSTALL_HOST_DB, _INSTALL_USER_DB, _INSTALL_PASS_DB, mais laisser libre le nom de la base, pour pouvoir la créer/choisir à chaque installation (mais alors attention à la sécurité de la chose : mal géré, ça peut devenir catastrophique).

Création automatique du site

Les réglages précédents indiquent comment on gère l’association entre une URL, un site et une base de données. Il reste à voir comment créer automatiquement le site, sans avoir à aller par FTP créer des sous-répertoires etc.

Création automatique des sous-répertoires. C’est très simple, pour que le répertoire spip/sites/xxxx/ et ses sous-répertoires soient créés à la volée lors de la première connexion sur le site (au premier hit, une fois le DNS et le VHost/VirtualServer installés), il suffit de l’indiquer dans les options de la fonction demarrer_site() :

demarrer_site($site, array(
     'creer_site' => true
));

La première visite sur le site créera automatiquement les répertoires nécessaires, et il vous suffira d’aller dans ecrire/ pour lancer l’installation.

Attention ici à la sécurité : il faut absolument éviter d’avoir à la fois un domaine pas encore installé, les mots de passe SQL définis et un accès lire à toutes les bases ou tables de votre base mutualisée ; dans un tel cas en effet n’importe qui peut venir prendre le contrôle de n’importe quel site hébergé, ce qui fait mauvais effet...

Toutefois, le système est verrouillé par un code d’activation qui sera demandé au visiteur qui souhaite créer le site. Par défaut ce code est ecureuil, mais vous pouvez le supprimer en indiquant, dans demarrer_site(), l’option 'code' => '', ou le modifier en indiquant 'code' => 'rhooo' ou tout autre secret. (Et, si le code est activé, il faut que le visiteur accepte les cookies pour pouvoir créer son site.)

Le système peut aussi créer la base à la demande. A condition que tous les codes d’accès à la base de données soient définis, et que l’utilisateur MySQL ainsi défini ait les droits suffisants pour créer de nouvelles bases, l’option 'creer_base' => true permet de créer la base à la volée avant de déclencher l’installation. Il est alors recommandé de nommer la table de a façon suivante :
define ('_INSTALL_NAME_DB', 'mutu_'.prefixe_mutualisation($site));
ce qui donnera des tables nommées spip_articles dans la base mutu_capetown.

Envoyer des mails à la création d’un site. L’option 'email' => 'fil@rezo.net' tente d’envoyer un email à cette adresse à chaque création automatique d’une base ou des répertoires d’un site.

TODO 1 : éviter les curieux

Avec ce système les documents ajoutés peuvent être communs à tous les sites : qu’il s’agisse des documents installés dans IMG/ ou d’éventuelles pages ajoutées « à la main », le serveur enverra la même chose pour tous les appels http ne passant pas par SPIP, indépendamment du nom de domaine.

Autrement dit, le document chargé dans le site capetown sous l’URL
http://capetown.chose.tld/sites/capetown/IMG/pdf/document.pdf
est aussi accessible via
http://antananarivo.chose.tld/sites/capetown/IMG/pdf/document.pdf

Il est possible de contourner ce problème en bidouillant le .htaccess des répertoires sites/capetown/ pour bloquer les appels provenant d’un autre nom d’hôte. Cela pourrait être ajouté comme option de mutualiser_creer().

TODO 2 : sécuriser ein bischen la création de base/site

On pourrait ajouter une option de mutualiser_creer() qui demanderait un login/mot de passe (en auth http), pour éviter toute surprise venant d’un inconnu total.

Réflexions sur les mises à jour

Mises à jour centralisées. Au fil du temps, on voudra sans doute procéder à des mises à jour, forcément centralisées, des fichiers de SPIP. Le schéma actuel des mises à jour est le suivant :

  1. mise à jour des fichiers
  2. lors d’un accès à l’espace privé, comparaison de la variable $spip_version avec la valeur mémorisée dans la base de données.
  3. si ces valeurs diffèrent, SPIP propose une mise à niveau de la base (ecrire/base/upgrade.php), laquelle se fait après une vérification FTP.

Clairement, ce processus ne peut pas fonctionner dans le cadre de la mutualisation : on ne va pas demander au responsable de chaque site d’aller créer un fichier ad hoc par FTP.

Remarque : avec dans le mes_options.php global la ligne suivante :

define('_ID_WEBMESTRES', '1');

on va permettre à celui qui crée le site d’être webmestre de celui-ci et de ne pas avoir besoin de l’authentification FTP et donc de réaliser les mises à jour sans accès FTP.

Il faut donc procéder autrement. Une piste (TODO) serait de faire un script spécialisé, qui ferait un « foreach » sur les sites, et les mettrait à jour chacun son tour en appelant la fonction spécifique d’upgrade. Sachant que, si une mise à jour joru se passe mal, le risque est de planter tous les sites d’un coup.

Offrir plusieurs versions. Autre problématique, la compatibilité des squelettes avec les versions de SPIP. En règle générale ça ne pose pas de problème, mais dans certains cas, on peut avoir envie de vérifier avant de basculer. On suppose alors que chaque site va vouloir upgrader à son rythme, après des vérifications (par exemple en local).

Dans ce cas, il faut prévoir quelque chose comme plusieurs installations mutualisées de SPIP, côte à côte, avec un lien symbolique identifiant les répertoires spip-version1/sites/ et spip-version2/sites/ (dans ce cas, on va créer les répertoire sites/ au même niveau que les répertoires spip-version1/ et spip-version2/).

La définition d’un site, du coup, repose dans la création d’un lien symbolique de la racine VHost du site vers la version souhaitée de SPIP. Pour changer de version, il suffit alors de modifier un lien symbolique, de vérifier si le site tourne, puis d’aller dans l’espace privé procéder à la « mise à niveau » (en général irréversible) de la base de données.

TODO : Récupérer son site

Pour être viable, le système doit proposer au webmestre de chaque site une méthode simple pour récupérer ses données et les réinstaller aillurs (en local pour tests, ou sur un site « dédié »). Pour récupérer ses données, il y a deux méthodes : la sauvegarde SPIP et le dump SQL classique. Il faut voir comment on détermine qui est le webmestre autorisé à récupérer cela (une piste avec autoriser(webmestre), cf. -Autorite-). Pour récupérer les images, un simple script avec wget suffit, mais est-ce suffisamment pratique ?

Retour à la version courante

Toutes les versions