Der LAMP-Stack
Theorie
Nextcloud basiert auf einer Reihe von Web-Technologien, die man als den LAMP-Stack bezeichnet. Dieser besteht aus den folgenden Komponenten:
- Linux: das Betriebssystem
- Apache: ein Web-Server
- MySQL: eine relationale Datenbank
- PHP: eine Programmiersprache
Für Windows gibt es den sogenannten WAMP-Stack (mit “W” für “Windows”). Der sogenannte XAMP-Stack ist eine betriebssystemneutrale Bezeichnung für den gleichen Software-Stack (mit “X” für ein beliebiges Betriebssystem).
Da Linux bloss ein Betriebssystemkern und kein komplettes Betriebssystem ist, muss das “L” in “LAMP” durch eine Distribution konkretisiert werden. In unserem Fall kommt Debian GNU/Linux zum Einsatz.
Weiter hat das Debian-Projekt die relationale Datenbank MySQL durch den Fork MariaDB ersetzt. Das “M” in “LAMP” steht bei der Standardinstallation von Debian also für “MariaDB” und nicht für “MySQL”.
Durch diese beiden Anpassungen ergibt sich für den angepassten LAMP-Stack folgendes Bild:
In der Einführung wurde die Problematik der OpenSource-Lizenzen behandelt. Beim LAMP-Stack kommen die folgenden Lizenzen zum Einsatz:
Komponente | Lizenz(en) |
---|---|
Linux (Kernel) | GPLv2 (share-alike) |
Debian GNU/Linux | diverse (GPL, LGPL, BSD-artige: permissive und share-alike) |
Apache HTTP Server | Apache License 2.0 (permissive) |
MySQL/MariaDB | GPLv2 |
PHP | PHP License (permissive) |
Wichtig: Alle Komponenten können uneingeschränkt und kostenlos verwendet werden!
Im Folgenden soll kurz auf die einzelnen Komponenten des LAMP-Stacks eingegangen werden:
Linux und Debian GNU/Linux
Linux ist ein Unix-artiges Betriebssystem, das seit 1991 von Linus Torvalds betreut wird. Das Original-Unix wurde 1969 von Ken Thompson entwickelt.
Seit 1983 arbeitet Richard Stallman an einer freien Neuimplementierung von Unix, die GNU heisst (“GNU’s Not Unix”). Aus dem GNU-Projekt stammt u.a. die GNU Compiler Collection (GCC) und die share-alike Lizenz GPL.
Linus Torvalds verwendete GCC um Linux zu kompilieren und stellte deswegen sein Betriebssystem unter die gleiche Lizenz, die GCC bereits verwendete: die GPL.
Debian verwendet nicht nur den Linux-Kernel, sondern auch viele Komponenten aus dem GNU-Projekt. Darum heisst die Distribution offiziell “Debian GNU/Linux”.
Der Apache-Webserver
Der Apache HTTP Server wurde seit 1995 von Brian Behlendorf entwickelt. Seit 1999 wird er unter der Obhut der Apache Software Foundation (nebst vielen anderen Projekten) weiterentwickelt.
Der Name “Apache” ist einerseits eine Anspielung auf die Apache-Indianer, die für ihre Ausdauer bekannt waren. Andererseits stammt der Name “Apache” aus der Bezeichnung “a patchy web server”: ein zusammengeflickter Web-Server.
Mittlerweile ist Apache modular aufgebaut und dadurch erweiterbar. Er kann beispielsweise PHP-Skripte über das Modul mod_php
ausführen.
Apache war jahrelang der am weitesten verbreitete Webserver der Welt. Mittlerweile verfügt er noch über einen Marktanteil von ca. 30%. Zum Vergleich: nginx hat einen Marktanteil von 35%, der IIS von Microsoft gerade einmal 5%.
MySQL und MariaDB
MySQL ist ein relationales Datenbanksystem das von der schwedischen Firma MySQL AB seit 1995 entwickelt worden ist. Die Firma wurde 2008 von Sun Microsystems gekauft. 2009 wurde das Projekt MariaDB von MySQL geforked und wird seither unabhängig weiterentwickelt.
2010 hat Oracle Sun Microsystems übernommen, und damit auch MySQL. In der Folge sind einige Linux-Distributionen, u.a. Debian, von MySQL auf MariaDB umgestiegen.
PHP
Die Programmiersprache PHP wird seit 1995 von Rasmus Lerdorf entwickelt. Die Abkürzung “PHP” ist (wie “GNU”) ein sogenanntes rekursives Akronym und bedeutet “PHP Hypertext Preprocessor”. PHP ist also eine vorgelagerte Technologie, mit der Hypertext (sprich: HTML) ausgegeben wird.
PHP ist eine dynamisch typisierte Skriptsprache und verfügt über einen sehr einfachen Deployment-Mechanismus: Man braucht nur die Skripte in einen bestimmten Ordner auf dem Webserver zu kopieren.
PHP-Skripte können via CGI oder über ein Modul in den Webserver eingebunden werden. Wichtige PHP-Anwendungen sind: WordPress, Moodle – und Nextcloud.
PHP-Ausführung: CGI, FastCGI, mod_php, PHP-FPM
Es gibt verschiedene Möglichkeiten, wie ein PHP-Skript in einen Webserver eingebunden werden kann.
Die älteste ist CGI, das Common Gateway Interface. Hierbei wird jede Anfrage in einem separaten Prozess behandelt. Das Aufstarten eines Prozesses ist langsam, weswegen CGI als sehr ineffizient gilt. Die folgende Grafik veranschaulicht den Ablauf bei der Ausführung eines CGI-Skripts namens script.php
:
Man sieht, dass bei jedem Request zuerst ein PHP-Prozess gestartet werden muss, was die Beantwortung der Anfrage verzögert.
Webserver haben spezielle Module entwickelt, um PHP effizienter ausführen zu können. Hierbei wird ein Prozess wiederverwendet. Bei Apache kommt hierzu das Modul mod_php
zum Einsatz, was standardmässig aktiv ist. Dadurch laufen der Apache Webserver und das PHP-Skript mit den gleichen Berechtigungen, was als unsicher gilt.
FastCGI ist ein Mechanismus, um Serverprozesse nicht für jede Anfrage neu starten zu müssen, sondern einen lang laufenden CGI-Prozess mit der Bearbeitung von Anfragen zu beauftragen. Dadurch wird der Overhead reduziert, der Request wird schneller bearbeitet, und der Server benötigt weniger Ressourcen.
PHP-FPM, der FastCGI Process Manager for PHP ist eine Implementierung von FastCGI für PHP. Die Generierung einer Seite wird dadurch konsequent von deren Auslieferung getrennt. Da der PHP- und der Webserver-Prozess nun in verschiedenen Prozessen mit unterschiedlichen Berechtigungen laufen, gilt diese Variante als sicherer.
Die folgende Grafik veranschaulicht, wie ein PHP-Prozess zur Bearbeitung mehrerer Anfragen wiederverwendet wird:
Da der Start des PHP-Prozesses vorgelagert ist, können Anfragen schneller bearbeitet werden. Eine PHP-Anwendung wie Nextcloud läuft damit deutlich schneller und benötigt weniger Ressourcen.
PHP-FPM kann auch mehrere Prozesse in einem sogenannten Prozess-Pool vorhalten, womit Anfragen auch parallel bearbeitet werden können. Dadurch können in der gleichen Zeit mehrere Benutzer bedient werden.
Mit Debian und PHP-FPM wird der LAMP-Stack zum DAMPF-Stack.
Links zum LAMP-Stack
Die folgenden Links führen zu weiterführenden Informationen über den DAMPF-Stack.
Übungen
In den folgenden Aufgaben soll der LAMP-Stack basierend auf Debian GNU/Linux 12 (Bookworm) in Betrieb genommen werden, was die Grundlage für den Betrieb von Nextcloud bildet.
Für diese Aufgaben wird Ihnen eine virtuelle Maschine (Debian 12 “Bookworm”) zur Verfügung gestellt.
💼 🖥️ Aufgabe 1: Apache HTTP Server
Installieren Sie den Apache HTTP Server:
sudo apt install -y apache2
Dieser sollte nach der Installation bereits gestartet sein, was Sie folgendermassen überprüfen können:
systemctl is-active apache2.service
💼 🖥️ Halten Sie die Ausgabe vom obenstehenden Befehl als Screenshot fest.
Sollte nicht die Ausgabe active
erscheinen, starten Sie den Server manuell:
sudo systemctl start apache2.service
💼 🖥️ Öffnen Sie im Browser die URL http://IP-ADRESSE, wobei Sie IP-ADRESSE
durch die IP-Adresse Ihrer VM ersetzen. Es sollte eine Debian-Beispielseite angezeigt werden. Machen Sie einen Screenshot von Ihrem Browser.
Statische Beispielseite
Webseiten werden gemäss Konvention im Verzeichnis /var/www
verwaltet. Erstellen Sie ein neues Unterverzeichnis namens modulbaukasten
:
sudo mkdir /var/www/modulbaukasten
Erstellen Sie eine Datei namens index.html
mit folgendem Inhalt:
<!DOCTYPE html>
<html lang="de">
<head>
<title>Modulbaukasten</title>
</head>
<body>
<h1>Modulbaukasten</h1>
</body>
</html>
Verschieben Sie die Datei nun mit dem mv
-Befehl ins zuvor erstellte Verzeichnis:
Damit die Seite erreichbar wird, muss eine neuer virtueller Host konfiguriert werden. Erstellen Sie hierzu eine Datei namens modulbaukasten.conf
mit folgendem Inhalt:
<VirtualHost *:80>
DocumentRoot /var/www/modulbaukasten
ServerName localhost
</VirtualHost>
Verschieben Sie die Datei anschliessend zum Apache-Verzeichnis der verfügbaren
Seiten /etc/apache2/sites-available
:
💼 🖥️ Kontrollfrage 1: Was beinhalten die beiden Unterverzeichnisse sites-available/
und sites-enabled/
im Apache-Konfigurationsverzeichnis /etc/apache2
? Tipp: Verwenden Sie den Befehl ls -l
. Halten Sie die Ausgabe in Ihrer Dokumentation fest.
Die Debian-Beispielseite soll nun deaktiviert; die neu konfigurierte Modulbaukasten-Seite aktiviert werden:
sudo a2dissite 000-default.conf
sudo a2ensite modulbaukasten.conf
💼 🖥️ Kontrollfrage 2: Was beinhalten sites-available/
und sites-enabled/
jetzt? Halten Sie die Ausgabe von ls -l
erneut in Ihrer Dokumentation fest.
Veranlassen Sie Apache nun via systemd zum Neuladen der Konfiguration (siehe Ausgabe der letzten beiden Befehle).
Die neue Beispielseite kann unter http://IP-ADRESSE betrachtet werden.
💼 🖥️ Halten Sie einen Screenshot des Browsers mit angezeigter Seite fest.
Aufgabe 2: MariaDB
Der Modulbaukasten soll von einer statischen in eine dynamische Webseite umgewandelt werden. Die veränderbaren Daten sollen dazu in einer Datenbank abgelegt werden. Hierzu soll MariaDB zum Einsatz kommen.
Installieren Sie den MariaDB-Server mithilfe des apt install
-Befehls. Tipp: Mit apt search SUCHBEGRIFF
findet man den Namen des zu installierenden Pakets.
Die Standardinstallation lässt sich zur Verbesserung der Sicherheit härten, wozu MariaDB einen Assistenten bietet, den Sie ausführen sollen:
sudo mariadb-secure-installation
💼 Befolgen Sie die Anweisungen auf dem Bildschirm und halten Sie die Fragen und Ihre Antworten darauf (mit einer kurzen Begründung) unter Kontrollfrage 3 fest.
Öffnen Sie nun eine interaktive mariadb
-Sitzung:
sudo mariadb
Erstellen Sie einen neuen Benutzer mit dem Namen moderator
und dem Passwort
topsecret
:
CREATE USER moderator@localhost IDENTIFIED BY 'topsecret';
💼 Kontrollfrage 4: Wozu dient wohl das Suffix @localhost
hinter
dem Benutzernamen?
Erstellen Sie eine Datenbank namens modulbaukasten
:
CREATE DATABASE modulbaukasten CHARACTER SET 'utf8' COLLATE 'utf8_general_ci';
(Die Datenbank unterstützt den Unicode-Zeichensatz mithilfe der Kodierung UTF-8.)
Vergeben Sie dem Benutzer moderator
alle Rechte für die Datenbank
modulbaukasten
, forcieren Sie ein Neuladen der Berechtigungen und verlassen
Sie die MariaDB-Sitzung wieder:
GRANT ALL PRIVILEGES ON modulbaukasten.* TO moderator@localhost;
FLUSH PRIVILEGES;
EXIT
Datenbanktabelle erstellen und befüllen
Für den Modulbaukasten soll eine Tabelle namens modules
erstellt werden. Diese
Tabelle soll sogleich mit einigen Beispieldaten gefüllt werden.
Erstellen Sie eine Datei modules.sql
mit folgendem Inhalt:
CREATE TABLE modules (
id INTEGER AUTO_INCREMENT NOT NULL PRIMARY KEY,
number INTEGER NOT NULL UNIQUE,
name VARCHAR(255) NOT NULL,
comment VARCHAR(255) NULL
);
INSERT INTO modules (number, name, comment) VALUES
(346, "Cloud-Lösungen konzipieren und relaisieren", "neue BiVo");
INSERT INTO modules (number, name, comment) VALUES
(426, "Software mit agilen Methoden entwickeln", "alte BiVo");
INSERT INTO modules (number, name, comment) VALUES
(114, "Codierungs-, Kompressions- und Verschlüsselungsverfahren einsetzen", "uralte BiVo");
INSERT INTO modules (number, name, comment) VALUES
(450, "Applikationen testen", "Überschneidungen zu M426");
Fügen Sie dem Skript drei weitere INSERT
-Befehle mit bereits absolvierten
Modulen hinzu, wobei Sie die comment
-Spalte für Ihre persönliche
Vergangenheitsbewältigung missbrauchen dürfen. (Der offizielle
Modulbaukasten kann dabei hilfreich sein.)
Führen Sie das Skript nun folgendermassen aus:
mariadb --database=modulbaukasten --user=moderator --password=topsecret <modules.sql
Falls es beim Einfügen der Werte zu einem Fehler gekommen ist, löschen Sie am besten die Tabelle:
echo 'DROP TABLE modules;' | mariadb -D modulbaukasten -u moderator -ptopsecret
(Die Parameter --database
, --user
und --password
haben die Kurzvarianten
-D
, -u
und -p
. Beachten Sie, dass zwischen dem Parameter -p
und dem
Passwort kein Leerzeichen steht.)
Korrigieren Sie Ihr Skript und versuchen Sie es erneut auszuführen, bis alle Werte erfolgreich eingefügt werden konnten.
💼 Halten Sie die Datei modules.sql
in Iher Dokumentation fest.
Sie können sich die Tabelle folgendermassen ausgeben lassen:
echo 'SELECT * FROM modules;' | mariadb -D modulbaukasten -u moderator -ptopsecret -t
💼 Kontrollfrage 5: Das Passwort topsecret
ist in den obigen
Befehlen direkt mit dem Parameter --password
bzw. -p
mitgegeben worden. Ist
das eine gute Idee? Warum (nicht)?
Aufgabe 3: PHP
Um die Informationen aus der Datenbank auf eine Webseite ausgeben zu können wird PHP mit einem Zusatzpaket für den Datenbankzugriff benötigt:
sudo apt install -y php8.2 php-mysql
Der PHP-Interpreter kann sogleich mit einem Einzeiler getestet werden:
php -r 'echo("PHP Version " . phpversion() . " läuft.\n");'
💼 Kontrollfrage 6: Welche Version von PHP wurde installiert (dreistellige Versionsnummer)?
Die statische Seite unter /var/www/modulbaukasten/index.html
soll zu einer
dynamischen PHP-Seite umgewandelt werden. Hierzu muss zuerst deren Dateiendung
angepasst werden:
sudo mv /var/www/modulbaukasten/index.html /var/www/modulbaukasten/index.php
Anschliessend soll sie mit einem Texteditor (wie z.B. nano
) angepasst werden:
sudo nano /var/www/modulbaukasten/index.php
Fügen Sie der Datei folgenden Inhalt unterhalb vom <h1>
-Element hinzu:
<?php
echo("<p>" . "PHP Version " . phpversion() . " läuft.</p>");
?>
Unter http://IP-ADRESSE sollte nun auch die Version von PHP ausgegeben werden.
💼 🖥️ Halten Sie einen Screenshot vom Browser fest, in dem die Versionsnummer von PHP zu sehen ist.
Erstellen Sie eine weitere Seite namens info.php
mit folgendem Inhalt:
<?php
phpinfo();
?>
Verschieben Sie die Datei ins selbe Verzeichnis wie index.php
:
sudo mv info.php /var/www/modulbaukasten/
Rufen Sie nun die Seite unter http://IP-ADRESSE/info.php auf.
💼 🖥️ Kontrollfrage 7: Die Seite zeigt u.a. an, welche Server API im Einsatz ist. Welcher Wert wird in der rechten Spalte zu Server API angezeigt?
Aufgabe 4: PHP-FPM
Bei einer Standardinstallation von Apache unter Debian wird PHP mit dem Modul
mod_php
ausgeführt. Um die Ausführung von PHP per FastCGI besser skalierbar zu
machen, muss PHP-FPM mit einem entsprechenden Apache-Modul installiert werden:
sudo apt install -y php8.2-fpm libapache2-mod-fcgid
Beim ersten Paket handelt es sich um den PHP-FPM-Service, welcher die PHP-Prozesse verwaltet. Das zweite Paket ist ein Apache-Modul, welches die Ausführung von PHP-Code an PHP-FPM delegiert.
💼 🖥️ Kontrollfrage 8: Was beinhalten die beiden
Unterverzeichnisse mods-enabled/
und conf-enabled/
im
Apache-Konfigurationsverzeichnis /etc/apache2
?
Zuerst soll mod_php
deaktiviert werden:
sudo a2dismod php8.2
Anschliessend sollen die Konfiguration für PHP-FPM sowie das Modul für FastCGI aktiviert werden:
sudo a2enconf php8.2-fpm
sudo a2enmod proxy_fcgi
💼 🖥️ Kontrollfrage 9: Was beinhalten die beiden
Unterverzeichnisse mods-enabled/
und conf-enabled/
im
Apache-Konfigurationsverzeichnis /etc/apache2
jetzt?
Veranlassen Sie Apache zum Neuladen der Konfiguration, wie bereits weiter oben beim Konfigurieren der Modulbaukasten-Webseite.
Rufen Sie erneut die Seite unter http://IP-ADRESSE/info.php auf.
💼 🖥️ Kontrollfrage 10: Welcher Wert wird nun in der rechten Spalte zu Server API angezeigt? Halten Sie das als Screenshot fest.
Damit PHP-FPM auch ressourcenintensivere Anwendungen (wie z.B. Nextcloud) ausführen kann, soll die Oberlimite für den Arbeitsspeicher, der von einem PHP-Skript belegt werden darf, erhöht werden.
Diese Einstellung befindet sich in der Datei /etc/php/8.2/fpm/php.ini
. Suchen
Sie nach der Einstellung memory_limit
, die standardmässig auf 128M
(128
Megabyte) gesetzt sein sollte. Erhöhen Sie diese Angabe auf 256M
(256
Megabyte).
Speichern Sie die Änderungen ab und starten Sie den Service php8.2-fpm
neu.
Rufen Sie erneut die Seite unter http://IP-ADRESSE/info.php auf.
💼 🖥️ Kontrollfrage 11: Welcher Wert wird nun in
der rechten Spalte zu memory_limit
angezeigt? Halten Sie das als Screenshot fest.
Aufgabe 5: Dynamische PHP-Seite
Da nun der ganze LAMP-Stack mit PHP-FPM in Betrieb ist, sollen die Module aus
der Datenbank nun dynamisch als Webseite dargestellt werden. Erstellen Sie
hierzu eine Datei namens modules.php
mit folgendem Inhalt:
<!DOCTYPE html>
<html lang="de">
<head>
<title>Modulbaukasten</title>
</head>
<body>
<h1>Modulbaukasten</h1>
<ol>
<?php
try {
$db = new PDO("mysql:host=localhost;dbname=modulbaukasten", "moderator", "topsecret");
foreach ($db->query("SELECT * FROM modules;") as $m) {
$id = $m['id'];
$number = $m['number'];
$description = $m['description'];
$comment = $m['comment'];
echo("<li value=\"{$id}\">");
echo("Modul {$number}: {$description} ({$comment})");
echo("</li>");
}
} catch (PDOException $e) {
die($e);
}
?>
</ol>
</body>
</html>
💼 Kontrollfrage 12: Ist es sinnvoll, Benutzername und Passwort in einer PHP-Datei zu hinterlegen? Warum (nicht)?
Verschieben Sie dieses PHP-Skript ins selbe Verzeichnis wie zuvor info.php
:
sudo mv modules.php /var/www/modulbaukasten/
Rufen Sie die Seite unter http://IP-ADRESSE/modules.php auf.
💼 🖥️ Erstellen Sie einen Screenshot der ausgegebenen Seite.
Zusatzübung: Anpassung der Ausgabe
Der Modulbaukasten wird als geordnete Liste (HTML-Tags <ol>
und <li>
)
ausgegeben. Passen Sie die Datei modules.php
so an, dass die Module
tabellarisch mit einer Titelzeile ausgegeben werden. Verwenden Sie hierzu die
HTML-Tags <table>
(Tabelle), <tr>
(Tabellenzeile), <th>
(Titelzelle) und
<td>
(normale Zelle).
Testen Sie die angepasste Ausgabe unter http://IP-ADRESSE/modules.php bis Sie mit der Darstellung zufrieden sind.
💼 🖥️ Fügen Sie die angepasste Datei modules.php
und
einen Screenshot der Ausgabe Ihrer Dokumentation hinzu.