Tutorial: Datenbank gestütze Vhosts mit Variablen mit Hilfe von mod_perl

Wer einen Webserver mit mehreren Domains betreibt, kennt das Problem:
Wie kann ich mir die Verwaltung der vielen Vhosts vereinfachen? Die einzelnen Config-Dateien beinhalten bis auf kleine Abweichungen (Domainname, Verzeichnis) alle die selben Inhalte. Und was ist, wenn man eine Einstellung ändern will? Alle Config-Dateien ändern?
Genau darauf hatte ich auch keine Lust mehr. Deshalb habe ich mich nach Möglichkeiten umgeschaut, wie man die Config-Dateien mit Variablen bestücken kann. Meine Lösung will ich euch natürlich nicht vorenthalten.

Vorbereitung

Meine Lösung basiert auf mod_perl 2.0. Dies sollte also zuerst auf dem Server installiert werden.
Unter Debian geht das ganz einfach:

sudo apt-get install libapache2-mod-perl2

Wer kein Debian-Server hat, kann sich mod_perl unter http://perl.apache.org/download/index.html downloaden.

Datenbank

Die wenigen Daten, in denen sich die Vhosts unterscheiden, werden in einer MySQL-Datenbank gespeichert. Legt euch dazu einfach folgende Tabelle in einer existierenden Datenbank an:

CREATE TABLE `apacheconfig` (
  `ID` int(11) NOT NULL auto_increment,
  `servername` varchar(100) NOT NULL,
  `alias` varchar(1000) NOT NULL,
  `dir` varchar(100) NOT NULL,
  PRIMARY KEY  (`ID`)
);

Abschließend sollten noch ein paar Testeinträge gemacht werden, damit das am Ende auch getestet werden kann.

Inhalt der Datei „/etc/apache2/sites-available/template“

Die Installation von mod_perl ermöglicht das Einbinden von Perl-Code in die Config-Dateien. Dies nutzen wir, um ein Template mit Variablen zu erstellen. In meinem Beispiel sieht das so aus:

<VirtualHost *:80>
	<Perl>
		$ServerName = $My::servername;
		$ServerAlias = $My::alias;
		$Redirect = "/ http://www.".$My::servername."/";
	</Perl>
</VirtualHost>

<VirtualHost *:80>
	<Perl>
		$ServerName = "www.".$My::servername;
		$DocumentRoot = "/home/".$My::dir."/htdocs";

		$Directory {"/home/".$My::dir."/htdocs/"} = {
			AllowOverride => "All",
			Order => "allow,deny",
			allow => "from all",
			Require => "all granted"
		};
	</Perl>

 	ServerAdmin webmaster@localhost

        <Directory />
        	Options FollowSymLinks
		AllowOverride None
	</Directory>

	Alias /phpmyadmin/ "/usr/share/phpmyadmin/"
	ErrorLog /var/log/apache2/error.log

	# Possible values include: debug, info, notice, warn, error, crit,
	# alert, emerg.
	LogLevel warn
</VirtualHost>

Inhalt der Datei „/etc/apache2/sites-available/vhost.conf“

Die vhost.conf ist das Herzstück der neuen Konfiguration. Hier werden alle Informationen aus der Datenbank geholt und mit Hilfe des Templates zusammengesetzt:

<Perl>
use DBI;
use Apache2::ServerUtil ();

# Die Daten in den folgenden 3 Zeilen bitte anpassen (DB_Name, DB_User, DB_Pass)
my $dsn = "dbi:mysql:DB_Name@localhost";
my $user = "DB_User";
my $pw = "DB_Pass";

my $s = Apache2::ServerUtil->server;

my $db = DBI->connect($dsn, $user, $pw) or die $DBI::errstr;

my $select = qq/SELECT * FROM apacheconfig ORDER BY ID/;
my $sth_select = $db->prepare($select);

$sth_select->execute() or die $DBI::errstr;
my @row;

while( @row = $sth_select->fetchrow_array ) {
	$My::servername = @row[1];
	$My::alias = @row[2];
	$My::dir = @row[3];
	$s->add_config(["Include /etc/apache2/sites-available/template"]);
}

</Perl>

Los geht’s…

Nun, da alles vorbereitet ist, wird die vhost.conf aktiviert:

a2ensite vhost.conf

Wichtig: nur die vhost.conf aktivieren, auf keinen Fall das Template.
Nachdem das erledigt ist, testen wir nochmal:

apache2ctl configtest

Der Server sollte mit „Syntax OK“ antworten. Wenn das der Fall ist, dann kann der Server mit

apache2ctl restart

neu gestartet werden.

Häufige Probleme

Es kann passieren, dass nur der erste Eintrag akzeptiert wird. In dem Fall legt noch eine Datei _default.conf an mit folgendem Inhalt:

NameVirtualHost *:80

Aktiviert diese mit

a2ensite _default.conf

Und startet den Server neu:

apache2ctl restart