Multisite: mehrere Seiten in einer Drupal Installation mit symlink

Do, 29.07.2010 - 18:06 -- Daniel Espendiller

Hat man mehrere Seiten in Drupal (Installationen) zu verwalten, stellt sich immer wieder das Problem mit den Updates. Auf jeder Seite muss der CMS-Core aktualisiert werden. Zentraler kann man das ganze über die Multisite Funktion nutzen. Hiermit ist es möglich mit einer einzelnen Installation mehrere Webseiten zu realisieren. Hat man vollen Zugriff auf den Webserver, so kann man auch mit Symlinks (Junctions) arbeiten, was die Sache noch etwas einfacher macht.

Kleiner Nebeneffekt der ganzen Geschichte: Dadurch dass alle Seiten die gleichen PHP-Skripte nutzen und somit das gleichen Skript nicht in unterschiedlichen Ordner liegt, kriegt man einen enormen Performance schub, wenn man einen PHP-Compiler wie APC, eAccelerator (Optimierung für Apache, PHP und MySQL für Drupal und andere Web-Anwendungen nutzt. Sämtliche Skripte werden so aus dem Cache geladen.

Drupal: Hintergrund

Drupal ist von der Verzeichnisstruktur so ausgelagt, dass sämtliche zusätzliche Datei in /sites abgelegt werden. Alle anderen Ordner und Daten sind bei jeder Drupalinstallation gleich. Innerhalb des sites Ordner können Unterordner für verschiedene Domains angelegt werden, so kann man Module, Themes und Dateien nur für bestimmte Seiten zur Verfügung stellen (der Hauptgedanke von Multisite).

  • /drupal/sites/all: (used by all sites) /modules, /themes
  • /drupal/sites/default: (used when there is no /sites/example.com directory) /files, settings.php
  • /drupal/sites/example1.com: (used when there is no /sites/example.com directory) /files, /modules, /themes, /tmp, settings.php

Drupal Multisite

Wie erwähnt ist es relativ einfach mehrere Seiten über Domain Unterordner innerhalb von /sites über eine Drupal Installation zu verwalten. Man muss nur dafür sorgen, dass Anfragen an z.B. www.example.com und www.example1.com im gleichen Ordner laden. Dazu reicht es folgendes Beispiel in die httpd.conf vom Apache einzutragen:

<VirtualHost *:80>
   DocumentRoot "C:/xampp/htdocs"
   ServerName localhost
   ServerAlias www.site1.local, www.site2.local, www.site3.local
</VirtualHost>

Nachteil der ganzen Geschichte ist, dass man keine strikte Trennung (Sicherheitsrisiko) zwischen den unterschiedlichen Seiten hat, "unschöne" Dateipfade mit Domainname und Dateien von einer fremden Domain aufgerufen werden kann.

Multisite mit Symlink simulieren

Man kann den Weg allerdings auch anderes herum angehen. Da wir wissen, dass sich nur der Order sites von unterschiedlichen Seiten unterscheidet, legen wir halt für jede Domain eine Simulierte Drupalumgebung drumherum. Wir legen z.B. unter /var/www/drupal.6.x eine entpackte Drupal Version mit allen Dateien an und eventuell entfernen den sites Ordner direkt.
Nun legen wir die Ordner /var/www/example.com und /var/www/example1.com an und kopieren uns den sites Ordner dort hinein.
Jetzt müssen wir logischerweise noch die Drupal Dateien in unsere beiden Ordner bekommen. Dieses machen wir dann mit symlinks (sind quasi Verknüpfungen; Windows: Junctions). So lassen wir z.B. /var/www/example.com/themes auf /var/www/drupal.6.x/themes Verweisen.
Das müssen wir dann für alle Ordner machen und die Datei im Drupal Stammpfad z.B so:

.htaccess -> ../drupal_home/current/.htaccess
cron.php -> ../drupal_home/current/cron.php
includes/ -> ../drupal_home/current/includes
index.php -> ../drupal_home/current/index.php
misc/ -> ../drupal_home/current/misc
modules -> ../drupal_home/current/modules
profiles/ -> ../drupal_home/current/profiles
scripts/ -> ../drupal_home/current/scripts
themes-> ../drupal_home/current/themes
update.php -> ../drupal_home/current/update.php
xmlrpc.php -> ../drupal_home/current/xmlrpc.php

Sieht zwar umständlich aus, aber so bekommt wir wirklich getrennte Drupal Installation, die alle die gleichen PHP-Skripte nutzen. Wenn man sich etwas mehr Gedanken macht, kann man so auch unterschiedliche Versionstände verwalten. Wenn z.B. eine Drupal Update kommt legt man sich einen Ordner /var/www/drupal.6.13an und kann nach und nach die jede Seite per symlink umstellen.
Weiter erkennt eAcceleator (APC und co.) auch, dass es sich bei den Dateiverweisen um einen symlink handelt und legt dann nur die Zieldatei in den Cache.

gemeinsame Tabellen

Über die Datei settings.php regelt man in Drupal die Datenbankanbindung. Meistens legt man für jede Seite eine eigene Datenbank an. Will man nun zum Beispiel die Benutzer und Berechtigung auf mehreren Seiten zu gleich nutzen oder man hat nur eine Datenbank zur Verfügung, sollte man sich die Datei bzw das Prefix Feature etwas genauer ansehen.
Wir können einmal per default sagen, dass jede Tabelle einen Prefix erhalten soll also z.B. example2_user oder wir lassen diesen Prefix für eine bestimmte Tabelle überschreiben shared_user. Folgendes Beispiel zeigt wie man die Benutzer / Berechtigungen über mehrere Seiten hinweg nutzen kann.

// from /sites/example2.com/settings.php
$db_url = 'mysqli://username:password@localhost/databasename';
$db_prefix = array(
  'default'   => 'example2_',
  'users'     => 'shared_',
  'sessions'  => 'shared_',
  'role'      => 'shared_',
  'authmap'   => 'shared_',
);

Will man die Usertabellen über mehere Datenbanken hinweg nutzen. Könnte man dieses mit FEDERATED Tables (MySQL 5.0 Reference Manual :: 13.7.2 How to Use FEDERATED Tables) realisieren. Ähnlich wie mit symlinks kann man hiermit fremde Tabellen von anderen Datenbank oder Remote Server Verknüpfen als wäre sie direkt innerhalb der Datenbank.
Weiter sollte man mal auf Drupal7 warten, da hat sich auch einiges getan bzgl. mehrere Datenbankenverbindungen..

Module

Zusätzliche Module lassen sich ebenso wunderbar über symlinks einbinden. So kann man benötigte Module einfach ähnlich ablegen wie den Drupal Core z.B./var/www/drupal/module. Weiter kann man die Module innerhalb diesem Ordner per Unterordner gruppieren. Globale und einzelnen Module kann man in weiteren Unterordner anlegen. Diese lassen sich dann mittels symlink direkt unter /sites/all/global einbinden. Drupal durchsucht nämlich alle Unterordner nach möglichen Modulen.
So binde ich die üblichen Module wie Views, CKK, FileField, Imagecache und co. über einen einzelnen symlink auf einen global Ordner zu.

SVN: Versionverteilung

Zu Letzt noch eine Konzept zur Anbindung von Multisite Webseiten an die Versionsverwaltung SVN (Subversion): agile approach | Wikheu - Managing Drupal Multisite Releases with SVN