Compartir el núcleo de SPIP entre varios sitios

Procedimiento para compartir el núcleo de SPIP entre varios sitios.

Desde SPIP 1.9 es posible compartir el núcleo de SPIP. Se trata de poder administrar varios sitios SPIP sobre un único servidor o alojamiento utilizando una sola copia de los archivos de funcionamiento de SPIP .

Eso permite un ahorro de espacio de disco importante, así como la posibilidad de actualizar el conjunto de los sitios SPIP de forma simple, con sólo poner al día el núcleo.

Las evoluciones de SPIP 1.9.1 simplificaban un poco el procedimiento, pero es con SPIP 1.9.2 y sus mejoras [1] que la mutualización se vuelve robusta al punto de permitir el uso compartido del núcleo de SPIP.

Este artículo explica el procedimiento para SPIP 1.9.2, en servidores Apache [2] que permiten la reescritura de URL (url_rewriting).

Hay varios métodos para llegar a los mismos resultados, según se desee configurar directamente la mutualización desde un alojamiento o desde un servidor.

El concepto...

Desde SPIP 1.9.2, es decir para las versiones 1.9.2 y posteriores, los directorios necesarios para el funcionamiento del núcleo de SPIP (ecrire, dist, oo), y los que describen las particularidades de un sitio (config, IMG, tmp, local) son claramente identificables y están separados. Esta separación es la que permite tener varios sitios SPIP autónomos funcionando bajo un mismo núcleo.

Esta autonomía se basa en la existencia de un cuarteto de directorios por sitio, en los que SPIP escribe los datos que resultan de la actividad particular que este tenga. Estos directorios son cuatro, ya que se distinguen los datos temporales y permanentes por una parte, y los datos accesibles por http y las que no lo son por otra. Los dos directorios inaccesibles por http serán protegidos por un archivo .htaccess instalado automáticamente por SPIP (los administradores del servidor hasta podrían poner estos directorios fuera de la estructura accesible por http).

Antes de SPIP 1.9.2, estos cuatro tipos de datos no se distinguían claramente, y se encontraban en los directorios IMG, CACHE, ecrire y ecrire/data. Con SPIP 1.9.2, estos cuatro directorios son distintos y nombrados por las siguientes constantes PHP:

define('_NOM_TEMPORAIRES_INACCESSIBLES', "tmp/");
define('_NOM_TEMPORAIRES_ACCESSIBLES', "local/");
define('_NOM_PERMANENTS_INACCESSIBLES', "config/");
define('_NOM_PERMANENTS_ACCESSIBLES', "IMG/");

En una instalación de SPIP no compartida, estos directorios se crean en la raíz del sitio, cuando se aplica la función spip_initialisation sobre las cuatro constantes definidas más arriba. Para obtener la mutualización del núcleo SPIP, basta con saber asociar una URL específica a su cuarteto de directorios específicos, llamando a la función spip_initialisation sobre cuatro valores distintos, deducidos de la URL.

Crear los directorios necesarios

Para empezar la mutualización, es necesario en primer lugar partir de un sitio funcional. Para los ejemplos, partiremos de un sitio llamado por la URL http://ejemplo.org/ almacenado físicamente en /home/pepe/public_html/.

Es necesario crear un directorio (por ejemplo llamado ’sitios’) que va a contener los directorios de los sitios mutualizados, en la raíz de la distribución (al mismo nivel que /ecrire).

-  mutualización de un directorio :
Si se desea que las direcciones http://ejemplo.org/primer_sitio/ y http://ejemplo.org/segundo_sitio/ correspondan cada una a un sitio spip, es necesario crear los subdirectorios /primer_sitio y /segundo_sitio en el directorio /sitios, y para cada uno de ellos crear los directorios /config, /IMG, /tmp y /local. Estos cuatro directorios deben ser accesibles en escritura. Por supuesto, también será posible añadir un directorio /squelettes para personalizar los esqueletos de cada sitio.

-  mutualización de subdominios y dominios (algunas ideas):
Si deseas que las direcciones http://pepe.ejemplo.org/, http://ejemplo.tld/ y http://usuario.ejemplo.com/ sean cada una un sitio SPIP, se puede prever crear en /sitios los directorios /pepe, /ejemplo.tld, y /ejemplo.com/usuario

Importante: Todas las URL deben señalar a la raíz de la distribución SPIP, es decir, a /home/pepe/public_html/. Luego se determinará su función en un archivo .htaccess explicado más adelante.

¡Redirecciones bien hechas!

Para que SPIP reconozca que se mutualiza un sitio, es necesario que se ejecute el script spip.php (llamado por index.php). Éste buscará, gracias a un código añadido en /config/mes_options.php, si la URL llamada corresponde a un sitio mutualizado o no. Para eso, es necesario que direcciones como http://ejemplo.org/primer_sitio/ o http://ejemplo.org/segundo_sitio/ sean redirigidas hacia http://ejemplo.org/ para ejecutar el index.php que allí se encuentre.

Este es el papel asignado al archivo .htaccess (o directamente a la configuración del servidor Apache).

Es necesario copiar y renombrar el fichero htaccess.txt en la raíz de la distribución por .htaccess, y luego modificarlo:

Para permitir la reescritura de URL (no cambia normalmente nada) : RewriteEngine On

Si la distribución SPIP está dentro de un subdirectorio, modificar la base rewrite. Aquí, el sitio está en la raíz, y entonces:

RewriteBase /

Por último, en ajustes personalizados, añadir el código siguiente para que los directorios /primer_sitio, /segundo_sitio, /tercer_sitio, etc. estén tratados desde la raíz de la distribución:

#Mutualisation
RewriteRule ^(primer_sitio|segundo_sitio|tercer_sitio)$ /$1/ [R,L]
RewriteRule ^(primer_sitio|segundo_sitio|tercer_sitio)/(.*) /$2 [QSA,L]

La primera regla redirige las direcciones http://ejemplo.org/primer_sitio hacia http://ejemplo.org/primer_sitio{{/. La segunda redirige todo lo que hay detrás de /primer_sitio/ a la raíz: http://ejemplo.org/primer_sitio/article112 es redirigido hacia http://ejemplo.org/article112. (¡Sin embargo, esta redirección es transparente, el nombre de la URL no cambia, es todavía http://ejemplo.org/primer_sitio/article112, incluso y sobre todo para PHP!)

¿Y si SPIP está dentro de un directorio??
En el caso de que, por poner un ejemplo, los archivos de SPIP se encuentren en /home/toto/public_html/spip/, SPIP es llamado por http://ejemplo.org/spip/, y los sitios mutualizados por http://ejemplo.org/spip/primer_sitio/ o http://ejemplo.org/spip/segundo_sitio/.

Entonces es necesario crear el siguiente archivo .htaccess:

RewriteEngine On
RewriteBase /spip/

#Mutualisation
RewriteRule ^(primer_sitio|segundo_sitio|tercer_sitio)$ /spip/$1/ [R,L]
RewriteRule ^(primer_sitio|segundo_sitio|tercer_sitio)/(.*) /spip/$2 [QSA,L]

¿Y para redirigir todos los directorios de sitios mutualizados?

Es posible crear reglas de reescritura genéricas, utilizables cualquiera que sea el nombre del directorio del sitio mutualizado.

-  en la raíz:

RewriteCond %{REQUEST_URI} !^/(config|dist|ecrire|IMG|oo|plugins|sitios|squelettes|tmp|local)/(.*)
RewriteRule ^[^/]+/(.*) /$1 [QSA,L]

-  o dentro de un directorio, por ejemplo /spip :

RewriteCond %{REQUEST_URI} !^/spip/(config|dist|ecrire|IMG|oo|plugins|sitios|squelettes|tmp|local)/(.*)
RewriteRule ^[^/]+/(.*) /spip/$1 [QSA,L]

Básicamente, lo que se hace es interpretar que cualquier directorio que no sea alguno de los listados será un sitio mutualizado.

¿Y para los dominios y subdominios?
Por una feliz casualidad, no hay ningún trabajo que hacer aquí, puesto que éstos normalmente apuntan hacia la raíz de la distribución SPIP...

Mutualizar según la URL gracias a mes_options.php

Es el archivo /config/mes_options.php en la raíz de la distribución el que va a realizar la mayor parte del trabajo: debe buscar si una URL debe mutualizarse o no, e inicializar SPIP en función de eso.

Numerosos casos pueden presentarse entre los directorios, los dominios y subdominios. PHP puede utilizar dos variables para conocer la URL que invocó al script:

$_SERVER['REQUEST_URI']; // contiene todo lo que hay detrás del nombre de dominio: /primer_sitio/article112 por ejemplo...
$_SERVER['SERVER_NAME']; // contiene el nombre del dominio o subdominio: usuario.ejemplo.org por ejemplo

Estas dos variables van a compararse con una expresión regular para extraer el nombre del directorio que contiene el sitio mutualizado que se quiere conocer. Una forma simple de mutualizar todos los directorios es copiar el siguiente código:

<?php 
if ( preg_match(',/([a-zA-Z0-9_-]+)/?,',$_SERVER['REQUEST_URI'],$r)) {

    if (is_dir($e = _DIR_RACINE . 'sitios/' . $r[1]. '/')) {

        $cookie_prefix = $table_prefix = $r[1]; 

        define('_SPIP_PATH',
            $e . ':' .
            _DIR_RACINE .':' .
            _DIR_RACINE .'dist/:' .
            _DIR_RESTREINT);

        spip_initialisation(
            ($e . _NOM_PERMANENTS_INACCESSIBLES),
            ($e . _NOM_PERMANENTS_ACCESSIBLES),
            ($e . _NOM_TEMPORAIRES_INACCESSIBLES),
            ($e . _NOM_TEMPORAIRES_ACCESSIBLES)
            );

       $GLOBALS['dossier_squelettes'] = $e.'squelettes';

        if (is_readable($f = $e._NOM_PERMANENTS_INACCESSIBLES._NOM_CONFIG.'.php')) include($f);
    }
} 
?>

La linea preg_match recupera el nombre de un directorio desde la estructura de la URL, por ejemplo ’primer_sitio’ dentro de http://ejemplo.org/primer_sitio/ ... Luego el script intenta una mutualización si el directorio /sitios/primer_sitio/ existe.

Si SPIP se encuentra dentro de un directorio /spip, es suficiente modificar la primera línea if (preg_match(',/spip/([a-zA-Z0-9_-]+)/?,', $_SERVER['REQUEST_URI'], $r)) {

Es necesario decirle a SPIP cuál es el prefijo para las tablas de la base de datos. Eso se hace con $cookie_prefix = $table_prefix = $r[1];

Esta línea va a crear tablas MySQL con prefijos que tienen el nombre del directorio que contiene al sitio: mi_sitio_article en reemplazo de spip_article por ejemplo. Esto permite hospedar todos los sitios sobre una única base de datos. Se podría conservar el prefijo por defecto (spip), pero para eso será necesario tener bases de datos diferentes para cada sitio.

Para eso, reemplazar lo anterior por:

$cookie_prefix = $r[1]; 
$table_prefix='spip';

La función spip_initialisation admite cuatro parámetros, que son las direcciones de cada uno de los directorios necesarios para el funcionamiento del sitio mutualizado.

$GLOBALS['dossier_squelettes'] = $e.'squelettes'; define la ubicación del directorio de esqueletos para el sitio

Finalmente las últimas líneas cargan un posible /sitios/premier_site/config/mes_options.php para configuraciones propias de cada sitio.

Información:

Toda modificación del archivo /config/mes_options.php del núcleo SPIP afectará a las opciones de todos los sitios albergados.

Por ejemplo, poner en este archivo: $type_urls = ’propres’ ;

Dará por defecto a todos los sitios este tipo de URL. No obstante, cada sitio puede cambiarlo en su propio archivo mes_options.php (por ejemplo, /sitios/mon_site/config/mes_options.php ).

Configurar Apache para los dominios y subdominios

La mutualización de la parte del servidor, con respecto a la gestión de los subdominios o dominios sigue siendo simple, pero requiere de crear algunas redirecciones de URL en la configuración del servidor Apache para tener en cuenta estos sitios.

He aquí un ejemplo de configuración para un servidor llamado ’exemple.tld’ (aquí un SPIP mutualizado) utilizando subdominios (SPIP llamado desde http://usuario.ejemplo.org/spip/).

El núcleo de SPIP está dentro de ’/home/toto/public_html/spip/’.

Entonces es necesario crear los directorios /sitios/exemple.tld/ , /sitios/exemple.tld/usuario/.

El archivo de configuración Apache 2/linux se sitúa en /etc/apache2/sites_available/default (también puedes crear un nuevo archivo en el directorio ./sitios_availables y activarlo).

# SERVEUR exemple.tld
# SPIP par sous domaine... / SPIP en subdominios
<VirtualHost *>
        ServerName exemple.tld
	ServerAlias *.exemple.tld

        # Redirection vers le SPIP noyau /Redirección hacia el núcleo SPIP
	DocumentRoot "/home/toto/public_html"
	<Directory "/home/toto/public_html/">
		AllowOverride All
		Order allow,deny
		Allow from all
	</Directory>

	# Seule l'adresse http://utilisateur.exemple.tld/spip/* doit être redirigée
        # Sólo la dirección http://utilisateur.exemple.tld/spip/* debe ser redirigida

	# (usuario.exemple.tld/spip/* -> /home/toto/public_html/*)
	RewriteCond %{SERVER_NAME} (www\.)?([^.]+)\.example\.net$
	RewriteRule ^/spip/(.*) /home/toto/public_html/spip/$1 [QSA,L]

	# (usuario.exemple.tld/* -> /home/toto/public_html/sitios/exemple.tld/usuario/*)
	RewriteCond %{SERVER_NAME} (www\.)?([^.]+)\.example\.net$
	RewriteRule (.*) /home/toto/public_html/sitios/exemple.tld/%1/$1 [QSA,L]

</VirtualHost>

Ahora es necesario analizar estas mutualizaciones posibles desde /config/mes_options.php :

<?php
# pour usuario.exemple.tld/spip/ 
if ( preg_match(',(.*)\.exemple\.tld/spip/?,',$_SERVER['SERVER_NAME'].$_SERVER['REQUEST_URI'],$r)) {

    if (is_dir($e = _DIR_RACINE . 'sitios/exemple.tld/' . $r[1]. '/')) {

       $cookie_prefix = $table_prefix = $r[1]; 

       define('_SPIP_PATH',
            $e . ':' .
            _DIR_RACINE .':' .
            _DIR_RACINE .'dist/:' .
            _DIR_RESTREINT);

        spip_initialisation(
            ($e . _NOM_PERMANENTS_INACCESSIBLES),
            ($e . _NOM_PERMANENTS_ACCESSIBLES),
            ($e . _NOM_TEMPORAIRES_INACCESSIBLES),
            ($e . _NOM_TEMPORAIRES_ACCESSIBLES)
            );

       $GLOBALS['dossier_squelettes'] = $e.'squelettes';

        if (is_readable($f = $e._NOM_PERMANENTS_INACCESSIBLES._NOM_CONFIG.'.php')) include($f);
    }
} 
?>

Nota sobre las copias de seguridad y las restauraciones

Cada sitio crea sus copias de seguridad en el directorio /sitios/primer_sitio/tmp/dump (o /sitios/primer_sitio/tmp/upload/login para los respaldos de un administrador restringido). Las restauraciones se hacen desde el mismo directorio.

Atención :

Actualmente SPIP registra las referencias al directorio /IMG de sitios mutualizados la direccion del tipo sitios/primer_sitio/IMG/* en lugar de IMG/* como es habitual para un sitio independiente.

Por lo tanto, una restauración sólo funcionará si se efectúa en el mismo sitio en el que se creó la copia de respaldo.

Una astucia para restaurar el sitio en otra parte consiste en editar el archivo dump.xml y sustituyendo todas las apariciones (a excepción de las de las declaraciones dir_img y dir_logo en la apertura de la baliza SPIP):

-  sitios/primer_sitio/IMG/

  • por (SPIP independiente) : IMG/
  • o (otro SPIP mutualizado) : sitios/mi_nuevo_sitio/IMG/

Inversamente, para pasar un SPIP independiente a uno mutualizado, es necesario sustituir todas las apariciones de:

-  IMG/
-  por : sitios/mi_sitio/IMG/

(Esta dificultad se corregirá en la próxima versión de SPIP.)

Notas

[1nueva distribución de los directorios, corrección de los problemas de logins y nombres de sitios que se mezclaban a veces entre los sitios con núcleo compartido, función de inicialización de un sitio compartido más clara

[2Para más información: estos procedimientos se probaron con Apache 2.0.55 y PHP 5.1.2 en servidor Ubuntu Dapper Drake así como sobre PHP 5.1.6 en servidor Ubuntu Edgy Eft

Autor o autora David Sánchez Crespillo, JavSP, tin Publicado el: Actualizado: 26/10/12

Traducciones: عربي, català, English, Español, français, italiano, Türkçe