Drupal 6 Multisiteumgebung mit PostgreSQL unter Debian 4

Installation und Einrichtung von

Installation der benötigten Pakete

Die folgenden Pakete werden benötigt:

Die eigentliche Installation:

aptitude install apache2 libapache2-mod-php5 php5 php5-common php5-pgsql php5-gd php5-cli postgresql-8.1 phppgadmin

Konfiguration

Grundlegende Konfiguration

Installation und Konfiguration der von Drupal benötigten PHP-Module, die nötigen Schritte um Suchmaschinenfreundlichen URL's nutzen zu können und das Hochsetzen der memory_limit-Direktive.

Die folgenden Schritte sind unter der ID von root auszuführen.

su

oder mit

sudo <BEFEHL>

falls sudo konfiguriert ist.

php memory_limit hochsetzen

Um einem "White-Screen" vorzubeugen wenn zu viele Drupal-Module installiert sind,
setzen wir die memory_limit in /etc/php5/apache2/php.ini höher.

memory_limit = 64M      ; Maximum amount of memory a script may consume (16MB)

Installation der clean-urls

Um das Feature der Suchmaschinenfreundlichen URL's(clean-url's) nutzen zu können, muß noch das mod_rewrite-Modul aktiviert werden. Hier werden die symbolischen Links von /etc/apache2/mods-available nach /etc/apache2/mods-enabled gesetzt für die entsprechenden Module gesetzt:

a2enmod rewrite

Neustart von Apache2

Damit die voherigen Änderungen wirksam werden, starten wir Apache erneut.

/etc/init.d/apache2 force-reload

Testen der Installation

Zum testen der Apache-Installation geben wir den FQDN oder die IP-Adrese in Browser ein
und sehen ein It works!

Um zu testen, ob php läuft und alle benötigten Module enthält legen wir eine Datei mit dem Namen index.php im Ordner /var/www an.

echo -e "<?php\n  phpinfo();\n?>" >  /var/www/index.php

Anschließend rufen Datei index.php mit der URL unseres Webservers + /index.html über Browser auf
und sehen in der Sektion apache2handler im Unterpunkt Loaded Modules, mod_rewrite und weiter unten die von Drupal benötigten PHP-Erweiterungen gd und pgsql.

Eirichtung der Datenbank

Damit der Benutzerwechsel funktioniert, machen wir uns zu root.

su

Um die folgenden Befehle auszuführen starten wir eine Shell unter der Identität von postgres

su postgres

Anlegen des zukünftigen Datenbankbenutzer mit den Optionen:
-P oder --pwprompt für Passwortauthentifizierung
-S oder --no-superuser, Default, deshalb optional
-D oder --no-createdb
-R oder --no-createrole, Benutzer darf keine Rollen anlegen
-E oder --encrypted, Verschlüsselung der Passwörter in der Datenbank

createuser -P -S  -D  -R  -E datenbankbenutzer

Anlegen der Datenbank mit UTF-8Kodierung,-E oder --encoding- für den durch -O oder --owner spezifizierten Benutzer.

createdb -E UNICODE -O datenbankbenutzer datenbankname

Anschließend

exit

um die Shell von postgres zu beenden,

exit

um auch die Rootshell wieder zu verlassen, damit wir die nächsten Schritte als normaler Benutzer auszuführen.

Drupal installieren

Damit wir uns definitiv in unserem Home-Directory befinden:

cd

Anlegen des Verzeichnisses welches später unser Drupal-Instanzen enthält,

mkdir drupal

Verzeichniswechsel nach drupal,

cd drupal

runterladen der deutschen 6er Version von drupalcenter.de,
(natürlich ist 6.4 durch die momentan aktuelleste Version von Drupal zu ersetzten)

entpacken.

tar -xzvf drupal-6.4-DE.tar.gz

Die Drupal Multisite-Umgebung

So soll die Multisiteumgebung später mal aussehen:

drupal/
|-- 6.x -> drupal-6.14
|-- 6.x_backup
|-- 6.x_profiles
|-- 6.x_sites
|   |-- all  
|   |-- default
|   |-- example.com
|   |   |-- files
|   |   |-- modules
|   |   `-- themes
|   `-- sub.example.com
|       |-- files
|       |-- modules
|       `-- themes
`-- drupal-6.14
    |-- includes
    |-- misc
    |-- modules
    |-- profiles -> ../6.x_profiles
    |-- scripts
    `-- sites  -> ../6.x_sites

Anmerkungen

Der Ordner 6.x_backup beziehungsweise der symbolische Link backup in der
Wurzel der Drupal-Installation ist drush-spezifisch.

Seit Commit 16a4e2b3cf0420a7dce7d3ed79f6701bdd97e095 auf Drush nicht mehr möglich:

Force to use a location for backups outside the drupal root.

Der Ordner 6.x_sites beziehungsweise der symbolische Link sites beinhaltet die einzelnen Sites und deren Daten.

Seit dem Fix von Issue #694708 auf drush_multi, behandle ich profiles analog zu sites.

Mulisiteumgebung vorbereiten

Erstellung des symbolische Links auf die Wurzel der Drupal-Installation, welche später in unserem VirtualHost die DokumentRoot darstellt .

ln -s drupal-6.4-DE 6.x

Erstellung der Verzeichnisse 6.x_sites, welche später unser die Subsites, Module, und Themes enthalten wird und 6.x_backup, in welchem Sicherheitskopien von Modulen und Themes, welche durch drush aktualisiert worden sind abgelegt werden.

mkdir   6.x_sites 6.x_backups

Verschieben der Ordner drupal-6.4-DE/sites/all und drupal-6.4-DE/sites/default nach 6.x_sites.

mv drupal-6.4-DE/sites/* 6.x_sites

Ersetzen des Verzeichnisses sites unterhalb von drupal-6.4-DE durch einen symbolischen Link mit relativer Pfadangabe welcher auf 6.x_sites zeigt uns setzen des symbolischen Links für backup.

rmdir drupal-6.4-DE/sites
cd drupal-6.4-DE
ln -s ../6.x_sites sites
ln -s ../6.x_backup backup
cd ..

Erstellung der Verzeichnisse modules und themes, hier sollten seit Drupal 5.x angepasste und runtergeladene Module und Themes abgelegt werden. Diese sind somit auch für die Subsites verfügbar.(Siehe auch README.txt in sites/)

mkdir 6.x_sites/all/modules 6.x_sites/all/themes

Eintrag in /etc/hosts

Damit unsere zukünfige Seite über einen FQDN erreichbar ist, erweitern wir die Datei /etc/hosts um die folgende Zeile:

127.0.0.1 example.com.localhost

Konfiguration von Apache

Abschließende Konfiguration

Einrichtung der Virtual-Hosts und Absichern der Installation.

Um die Apache-Direktiven und den Virtual-Host anzulegen benötigen wir wieder erhöhte Privilegien.

sudo su oder su

Drupal und .htaccess

Damit die von Drupal benutzte .htaccess funktioniert legen wir die Datei /etc/apache2/conf.d/drupal.conf mit folgendem Inhalt an:

<Directory /home/foobar/drupal/>
Options +FollowSymLinks Indexes
AllowOverride All
order allow,deny
allow from all
</Directory>

Drupals cron.php absichern

Um Drupals cron.php vor unberechtigtem Zugriff zu schützen, tragen wir in /etc/apache2/conf.d/drupal.conf noch die folgende Passage ein:

<Files cron.php>
Order deny,allow
Deny from all
Allow from 10.10.10.0/24
Allow from 127.0.0.1
Allow from 1.2.3.4
</Files>

In der ersten Allow-Direktive wird per CIDR-Notation der Zugriff vom kompletten VPN gewährt.
In der zweiten wird der Zugriff von localhost aus erlaubt.
Entscheidend ist aber, daß die IP-Adresse des Server(die 3.te Direktive) gelistet ist, von hier wird cron.php per Cronjob aufgerufen,

Damit unsere /etc/apache2/conf.d/drupal.conf wirksam wird, muß der Webserver auch hier die Konfiguration neu einlesen:

/etc/init.d/apache2 reload

Drupals CHANGELOG.txt absichern

Security by obscurity

Mein erster Gedanke war, die CHANGLOG.txt mit in Direktive für die Absicherung von Drupals cron.php zu nehmen um diese Datei ebenso vor fremden Blicken zu schützen...

<Files cron.php,CHANGELOG.txt>
Order deny,allow
Deny from all
# Zugriff aus dem VPN erlauben
Allow from 10.10.10.0/24
Allow from 127.0.0.1
Allow from 81.169.175.14
</Files>

Aber nach überprüfen der Konfiguration mit

sudo apache2ctl configtest

kam der folgende Fehler:

Syntax error on line 6 of /etc/apache2/conf.d/drupal.conf:
Multiple <Files> arguments not (yet) supported.

Zu praktisch gedacht, doch ein eigenes Statement:

<Files CHANGELOG.txt>
Order deny,allow
Deny from all
</Files>

Nachdem der Configtest durchgelaufen ist muss der Webserver neu gestartet werden.

/etc/init.d/apache2 restart

Virtual Host einrichten

Anlegen der Datei /etc/apache2/sites-available/example.com.localhost.conf,
auch hier ist foobar wieder durch den eigenen Benutzernamen zu ersetzten, DocumentRoot zeigt auf den symbolischen Link, welcher wiederum auf die Wurzel der Drupal-Installation zeigt.

<VirtualHost *>
ServerName example.com.localhost
ServerAlias www.example.com.localhost
ServerAdmin foobar@example.com.localhost
DocumentRoot /home/foobar/drupal/6.x
ErrorLog /var/log/apache2/example.com.localhost-error.log
CustomLog /var/log/apache2/example.com.localhost-access.log combined
</VirtualHost>

Analog zur Aktivierung des rewrite-Moduls, werden auch hier wieder symbolische Links gesetzt und zwar von /etc/apache2/sites-available nach /etc/apache2/sites-enabled.

a2ensite example.com.localhost.conf

Nach den letzten Schritten müssen wir den den Webserver neu starten, damit er seine Konfiguration erneut einließt und die angelegten Direktiven wirksam werden.

Einrichtung einer Site

Um als wieder Benutzer weiterzumachen:

exit

Wechsel in das 6.x_sites Verzeichnis:

cd
cd drupal/6.x_sites/

Anlegen eines Verzeichnisses für die erste Site,

mkdir -p example.com.localhost/files

Das Verzeichnis files für den Webserver schreibbar machen:

chmod 775 example.com.localhost/files

An dieser Stelle explizit kein su - um auch in diesem Verzeichnis zu bleiben.

su
chgrp www-data example.com.localhost/files
exit

Gesetz dem Fall, daß example.com irgendwann in den Produktiveinsatz
geht, geben wir diesen bei der Installationsroutine von Drupal den zukünftigen Speicherort für unsere Dateien an(sites/example.com/files)
und setzen hierfür noch einen Symlink

ln -s example.com.localhost example.com

Für Module und Themes, die nur für unsere Subsite verfügbar sein sollen legen wir noch die folgenden 2 Verzeichnisse an:

mkdir example.com.localhost/themes example.com.localhost/modules

Jetzt brauchen wir noch die settings.php, welche die Einstellungen für unser Site enthalten wird.

cp default/default.settings.php example.com.localhost/settings.php

Jetzt können wir mit unsere Browser unter example.com.localhost aufrufen und kommen zur Installationsroutine von Drupal.

Drupal Update in 8 Schritten

Bei einem Drupal Setup wie hier beschrieben, sind nur 8 Schritte für ein Update innerhalb eines Drupal-Zweiges nötig.

Hier wird exemplarisch das Update von Drupal-6.9 auf Drupal-6.10, welches am 27. Februar durchgeführt wurde beschrieben.

Es wird empfohlen die zu aktualisierende Seite in den Wartungsarbeiten-Modus zu versetzen und die Dateien sowie Datenbank im Vorfeld sichern.

1) Runterloaden der neuen Drupal-Version

Download der neuen Drupal-Version in das Verzeichnis in dem sich die auch die alte Drupal-Version befindet.

2) Entpacken des Drupal-Tarballs

tar xfz drupal-6.10.tar.gz

3) sites Ordner löschen

cd drupal-6.10
rm -r sites

4) Symlink auf 6.x_sites Ordner mit relativem Pfad

ln -s ../6.x_sites sites
ls -l
lrwxrwxrwx  1 florian server    12 2009-02-27 10:13 sites -> ../6.x_sites
..

5) Symlink auf 6.x_backups Ordner mit relativem Pfad

ln -s ../6.x_backup backups
ls -l
...
lrwxrwxrwx  1 florian server    13 2009-02-27 10:19 backups -> ../6.x_backup
...

6) Symlink auf alte Drupal-Version entfernen

cd ..
unlink 6.x

7) Symlink auf die neue Drupal-Version

ln -s drupal-6.10 6.x
ls -l
...
lrwxrwxrwx 1 florian server      11 2009-02-27 10:22 6.x -> drupal-6.10
...

8) update.php als User 1 aufrufen

Falls aktiviert, den Maintanance-Modus abschalten und Voila!

Drush in einer Multisite-Umgebung

Um drush in einer Multisiteumgebung zu arbeiten, haben sich folgende Mechanismen als nützlich erwiesen:

Drush-Alias für Multisite

An dieser Stelle werden Aliase auf die jeweiligen drush-Version(Symlink) und der auf -r bzw. --root folgenden Wurzel der Drupal-Installation gesetzt.

Alternativ zu Aliasen auf die Drupal-Wurzel, kann dies auch über
drushrc.php, die Konfigurationsdatei für drush erfolgen.

Drush ist in nach /usr/local/share/ installiert worden und das Wrapper-Skript /usr/local/share/drush/drush ist ein Softlink nach /usr/local/bin/drush.

alias drush5_='/usr/local/bin/drush/drush -r /home/drupal/5.x '
alias drush6_='/usr/local/bin/drush/drush -r /home/drupal/6.x '

Verwendung von drush in der Multisiteumgebung

Der Aufruf von drush erfolgt über den angelegten Alias + die Spezifizierung der Subsite,
mittels -l oder --uri="".

Im folgenden Beispiel werden die Informationen über den Status der Seite aktualisiert.

drush6_ -l http://example.com pm-refresh

Für 5.x ist das Modul Update Status Voraussetzung für die Aktionen pm-refresh (rf) und pm-update (up).

sites/all/modules & sites/example.com/modules

Wenn sites/all/modules und sites/example.com/modules parallel existieren, installiert drush Module nach sites/all/modules.

Im Falle, das sites/all/modules nicht existiert, dafür aber sites/example.com/modules wird sites/all/modules erstellt und benutzt.

Um trotzdem sites/example.com/modules verwenden zu können existiert in sites/all kein modules Verzeichnis und sites/all ist schreibgeschütz.

Multisite-Features unter Drupal 7.x

Rudimente für ein Drupal-Deployment mit

  • Lokaler Entwicklungumgebung
  • Stage-Umgebung
  • Live / Produktionsumgebung

unter Verwendung, der in Drupal-7 neu eingeführten Multisite-Features in der Datei sites.php, Drush-Aliases
und einer speziellen settings.php,
die in diesem Fall versioniert wird.

sites.php -- Verzeichnis Aliase in Drupal 7.x

Die in Drupal 7.x neu eingeführte Datei sites.php stellt erstmalig Verzeichnis-Aliase für Drupal-Multisites zur Verfügung.

So ist es jetzt möglich mit verschiedenen Domains bzw. VirtualHosts ein bestimmtes Verzeichnis innerhalb von sites anzusprechen,
ohne über z.B. Symbolische Links zu gehen, was in vorgigen Drupal-Versionen zur Folge haben konnte, daß Datei- oder Modulpfade beim "umbiegen" von der Dev-Site example.mydomain.de auf die Live-Site example.com divergent sind.

// sites/sites.php

// (LOCAL) DEV SITE
$sites['example.localhost'] = 'example.com';

// STAGE SITES
$sites['stage-example.mydomain.de'] = 'example.com';
$sites['stage.example.com'] = 'example.com';

// LIVE SITE
$sites['example.com'] = 'example.com';

@see /path/to/drupal7/sites/example.sites.php

settings.php für DEV, STAGE und LIVE

Im folgenden Ausschnitt der settings.php werden für

  • DEV SITE
  • STAGE SITE
  • LIVE SITE

unterschiedliche Datenbanken und Vorbelegungen von Variablen definiert.

Die verschiedenen Umgebungen sind von einem Switch auf $_SERVER['HTTP_HOST'] eingeschlossen,
und es werden über den Host-Header des aktuellen Requests die entsprechenden Einstellungen genommen.

Die Verwendung des Contributed-Modules "Environment Indicator" weist optisch zusätzlich darauf hin, auf welcher Umgebung man sich gerade befindet, hierzu hat mich besonders Dirk Rüdigers Artikel zu Drush site-alias motiviert(s.u.).

// sites/default/settings.php

switch ($_SERVER['HTTP_HOST']) {
  case 'stage.example.com':
  case 'stage-example.mydomain,de':

    $conf['environment_indicator_text'] = 'STAGE SITE';
    $conf['environment_indicator_color'] = 'salmon';

    $databases = array (
      'default' =>
      array (
        'default' =>
        array (
          'database' => 'stage_db',
          'username' => 'stage_db_user',
          'password' => 'stage_db_passwd',
          'host' => 'localhost',
          'port' => '',
          'driver' => 'mysql',
          'prefix' => '',
        ),
      ),
    );
    break;

  case 'example.com':

    $conf['environment_indicator_text'] = 'LIVE SITE';
    $conf['environment_indicator_color'] = 'red';

    $databases = array (
      'default' =>
      array (
        'default' =>
        array (
          'database' => 'live_db',
          'username' => 'live_db_user',
          'password' => 'live_db_passwd',
          'host' => 'localhost',
          'port' => '',
          'driver' => 'mysql',
          'prefix' => '',
        ),
      ),
    );
    break;

  default:
    $conf['environment_indicator_text'] = 'LOCAL DEV SITE';
    $conf['environment_indicator_color'] = 'green';

    $databases = array (
      'default' =>
      array (
        'default' =>
        array (
          'database' => 'local_dev',
          'username' => 'local_dev_user',
          'password' => 'local_dev_passwd',
          'host' => 'localhost',
          'port' => '',
          'driver' => 'mysql',
          'prefix' => '',
        ),
      ),
    );
}

@see /path/to/drupal7/sites/default/default.settings.php

Drush-Aliases

In drush V. 3. wurden Site-Aliase eingeführt, dies ermöglicht, ähnlich wie bei Aliasen auf der Shell eine kurze Schreibweise für eine längere Befehlangabe.

Um explizit eine Drupal-Site und deren spezifische Einstellungen in einer Drupal-Multisite-Umgebung anzusprechen,
sind die Angabe der Drupal-Wurzel (--root=/path/to/drupal)
und der Name der Site bzw. dem Namen des Verzeichnisse in dem die jeweilige Site liegt (--uri=example.com) nötig.

Durch das folgende Snippet lassen sich die Instanzen über die Aliase

  • @dev
  • @stage
  • @stage2
  • @live

ansprechen und die Optionen --uri=example.com bzw. der kurzen Schreibweise -l example.com werden $_SERVER['HTTP_HOST'] durch drush gesetzt.

// /etc/drush/aliases.drushrc.php

$aliases['dev'] = array(
  'uri' => 'example.localhost',
  'root' => '/multi/drupal/7.x',
);

$aliases['stage'] = array(
  'uri' => 'stage-example.mydomain.de',
  'root' => '/multi/drupal/7.x',
);

$aliases['stage2'] = array(
  'parent' => '@stage',
  'uri' => 'stage.example.com',
);

$aliases['live'] = array(
  'uri' => 'example.com',
  'root' => '/multi/drupal/7.x',
);

Analog zum Host-Header des aktuellen Requests einer Web-Anfrage
wird in der obigen settings.php nun hierüber verzweigt.

@see /path/to/drush/examples/example.aliases.drushrc.php

Weiterführendes