Aus Linux-Magazin 02/2021

Schlanken Webserver Lighttpd aufsetzen

© Andriy Popov, 123RF

Während Nginx und Apache das Internet dominieren, gerät der alteingesessene Webserver Lighttpd zu Unrecht etwas in Vergessenheit: Er ist schlank, arbeitet flott und lässt sich dank einfacher Konfiguration schnell aufsetzen.

In Sachen Funktionsumfang muss sich der kleine Webserver Lighttpd [1] keineswegs hinter der prominenteren Konkurrenz verstecken. Unter anderem kennt er das Konzept der Virtual Hosts und kann abhängig von der Anfrage seine Konfiguration ändern. Über Module rüstet man bei Bedarf weitere Funktionen nach. So lassen sich Zugriffe auf einzelne Webseiten einschränken, Verbindungen per TLS absichern und per FastCGI-Schnittstelle Skriptsprachen einbinden. Die FastCGI-Schnittstelle besitzt zudem einen eingebauten Load Balancer, der eintrudelnde Anfragen auf mehrere PHP-Server verteilt.

Der Name des Webservers spricht sich übrigens “Lighty” aus, einige Webseiten verwenden diese Lautschrift sogar synonym zur offiziellen Bezeichnung. Lighttpd unterstützt HTTP 1.0/1.1 sowie verschlüsselte Verbindungen via HTTPS. Das neuere HTTP/2 beherrscht der leichtgewichtige Webserver erst seit Version 1.4.56. Aufgrund seiner geringen Größe kommt Lighttpd oft auf kleinen oder leistungsschwächeren Systemen zum Einsatz. So werkelt er unter anderem im beliebten Netzwerk- und Werbefilter Pi-Hole [2]. Die leicht verständliche Konfigurationsdatei ermöglicht zudem ein blitzschnelles Einrichten.

Schnell eingespielt

Die meisten Distributionen halten Lighttpd in ihren Repositories vor. Unter Ubuntu installiert man ihn beispielsweise mit dem Kommando aus der zweiten Zeile von Listing 1. Einige Distributionen verstauen selten benötigte Module in separaten Paketen, deren Name häufig mit lighttpd- beginnt. Im Fall von Ubuntu rüstet etwa lighttpd-webdav eine WebDAV-Schnittstelle nach. Für die ersten Schritte mit dem Webserver benötigen Sie diese Module jedoch in der Regel nicht.

Um Lighttpd aus dem Quellcode zu erstellen, benötigen Sie mindestens einen C-Compiler, Make, das Tool Pcre-config sowie die Entwicklerpakete zu Zlib und Bzip2. Unter Ubuntu holt der Befehl aus der vierten Zeile von Listing 1 alles Notwendige hinzu. Die zahlreichen Abhängigkeiten für sämtliche optionalen Lighttpd-Module listet das Lighttpd-Wiki auf [3]. Den Lighttpd-Quellcode von der Projekt-Website übersetzen Sie mit dem bekannten Dreischritt (Listing 1, Zeile 6 bis 8). Im Quellcodeverzeichnis verstecken sich im Ordner »doc/systemd/« passende Konfigurationsdateien für Systemd.

Listing 1

Lighttpd unter Ubuntu

### Lighttpd installieren
$ sudo apt install lighttpd lighttpd-doc
### Lighttpd kompilieren - Vorbereitung
$ sudo apt install build-essential libpcre3-dev zlib1g-dev libbz2-dev
### Lighttpd übersetzen und einrichten
$ configure
$ make
$ sudo make install

Fix aufgesetzt

Sämtliche Einstellungen des Webservers versammelt die Datei »lighttpd.conf«, die standardmäßig im Verzeichnis »/etc/lighttpd/« liegt. Als Ausgangspunkt für eine eigene »lighttpd.conf« empfiehlt sich die einfache Konfiguration aus Listing 2. In jeder Zeile wartet links der Name einer Einstellung, rechts neben dem Gleichheitszeichen folgt der zugehörige Wert. Mit »#« beginnende Zeilen ignoriert Lighttpd.

Listing 2

Einfache Lighttpd-Konfiguration

var.dir = "/var/www"
# Grundeinstellungen setzen:
server.document-root = var.dir + "/html"
server.port = 80
server.username = "www-data"
server.groupname = "www-data"
server.errorlog = "/var/log/lighttpd/error.log"
mimetype.assign = (
  ".html" => "text/html",
  ".txt" => "text/plain",
  ".jpg" => "image/jpeg",
  ".png" => "image/png"
)
static-file.exclude-extensions = ( ".fcgi", ".php", "~", ".inc" )
index-file.names = ( "index.html" )

In komplexeren Konfigurationen tauchen einige Domain-Namen, Verzeichnisse oder URL-Bestandteile an mehreren Stellen auf. Um sich Tipparbeit zu sparen, stecken Sie solche Informationen in Variablen, die Sie im späteren Verlauf als Platzhalter verwenden. Listing 1 macht von dieser Möglichkeit direkt am Anfang Gebrauch. Dort landet das Verzeichnis »/var/www« in der neuen Variable »var.dir«.

Hier zeigt sich ein weiterer Vorteil der Variablen: Ändert sich irgendwann das Verzeichnis, passen Sie lediglich am Anfang die Variable »var.dir« an. Der Variablenname muss mit »var.« beginnen, lässt sich darüber hinaus aber frei wählen. Vorgegeben sind lediglich »var.PID« mit der Prozess-ID des laufenden Lighttpd sowie »var.CWD« mit dem aktuellen Arbeitsverzeichnis.

Hinter »server.document-root« folgt das Verzeichnis, in dem alle Webseiten lagern (Document Root). Dabei kommt die Variable »var.dir« zum Einsatz, an deren Inhalt Lighttpd noch ein »/html« anhängt. Allgemein lässt der Operator »+« zwei beliebige Zeichenketten miteinander verschmelzen. Im Beispiel ergibt sich somit der Ordner »/var/www/html«.

Der Webserver lauscht später an dem hinter »server.port« notierten Port. Für den Zugriff auf Port 80 muss Lighttpd mit Root-Rechten starten. Um dabei keine Sicherheitslücke aufzureißen, wechselt der Server in Listing 1 automatisch zum Benutzer www-data in der gleichnamigen Gruppe, also zum von Debian und Ubuntu dafür vorgesehenen Benutzerkonto.

Gesprächsstoff

Der Parameter »server.errorlog« legt die Textdatei fest, in der Lighttpd seine Meldungen protokolliert. Darin finden sich auch alle Warnungen und Hinweise. Mit »server.errorlog-use-syslog = “enable”« schreibt der Webserver diese Meldungen ins Syslog. Die zusätzliche Zeile »server.use-ipv6 = “enable”« würde schließlich noch die Unterstützung für IPv6 aktivieren.

In seiner Antwort sendet der Webserver den MIME-Typ der übertragenen Daten mit, wie etwa »text/html« für ein HTML-Dokument. »mimetype.assign« weist einzelnen Dateiendungen den jeweils passenden MIME-Typ zu. Die Einstellung demonstriert gleichzeitig den Einsatz einer Liste: Die Zuweisungen landen jeweils durch ein Komma getrennt zwischen zwei Klammern. In Listing 2 stehen die einzelnen Werte der Liste nur der Übersicht halber in einer eigenen Zeile, die Formatierung spielt jedoch keine Rolle.

PHP-Skripte sollte der Webserver ausführen und möglichst nicht an den Browser ausliefern. Die Endungen solcher zu ignorierenden Dateien verrät »static-file.exclude-extensions«. Greift der Browser auf ein Verzeichnis zu, sucht Lighttpd darin eine der hinter »index-file.names« aufgelisteten Dateien und liefert sie zurück. Existiert keines dieser Index-Files, präsentiert Lighttpd eine 403-Fehlermeldung. Anders als viele Konkurrenten verbietet Lighttpd seinen Clients den direkten Zugriff auf Verzeichnisse – einen solchen muss der Administrator explizit über das Modul »dirlisting«erlauben.

Spaltung

Um bei komplexen Konfigurationen nicht den Überblick zu verlieren, lassen sich die Lighttpd-Einstellungen auf mehrere Dateien verteilen. Die wiederum landen normalerweise in den Unterordnern »/etc/lighttpd/conf.d/« und »/etc/lighttpd/vhosts.d/«. In der Datei »lighttpd.conf« holen dann die Zeilen aus Listing 3 sämtliche Konfigurationsdateien aus den beiden Verzeichnissen hinzu. Welche Unterverzeichnisse Lighttpd tatsächlich nutzt, hängt von der Distribution ab. Ubuntu verwendet etwa die Unterordner »conf-enabled/« und »conf-available/«. In Letzterem sammelt jede Datei zusammengehörende Einstellungen. So enthält beispielsweise »15-fastcgi-php.conf« die Konfiguration des FastCGI-Moduls. Lighttpd wertet in der unter Ubuntu mitgelieferten Konfiguration allerdings nur die Dateien im Verzeichnis »conf-enabled/« aus. Ähnlich wie bei Apache genügt deshalb ein im Verzeichnis »conf-enabled/« angelegter symbolischer Link auf die Datei »15-fastcgi-php.conf«, um die FastCGI- Einstellungen zu aktivieren.

Listing 3

Konfiguration holen

include "/etc/lighttpd/conf.d/*"
include "/etc/lighttpd/vhosts.d/*"

Konfiguration zuführen

Um die Wirkung auszuprobieren, sichern Sie eine eventuell bestehende »lighttp.conf« und erstellen dann eine neue Konfigurationsdatei mit dem Inhalt aus Listing 2. Mit »lighttpd -t -f /etc/lighttpd/lighttpd.conf« prüfen Sie diese zunächst auf Syntaxfehler (Abbildung 1). Ein Buchstabendreher wie »server.prot=80« bliebe dabei allerdings unentdeckt. Sie sollten daher nach dem Neueinlesen der Konfiguration immer noch das Error-Log kontrollieren. Abbildung  2 zeigt einen Konfigurationstest mit dem Parameter »-D«.

Abbildung 1: Mit dem Parameter »-t« testet Lighttpd lediglich die Syntax auf Fehler.

Abbildung 1: Mit dem Parameter »-t« testet Lighttpd lediglich die Syntax auf Fehler.

Abbildung 2: Über den Parameter »-D« bleibt Lighttpd im Vordergrund und gibt im Terminal Meldungen aus. Das ist beispielsweise nützlich, um schnell eine neue Konfiguration zu testen.

Abbildung 2: Über den Parameter »-D« bleibt Lighttpd im Vordergrund und gibt im Terminal Meldungen aus. Das ist beispielsweise nützlich, um schnell eine neue Konfiguration zu testen.

Die neuen Einstellungen übernimmt der Webserver, sobald er das »SIGUSR1«-Signal erhält. Bei einer Distribution mit Systemd erledigt das »sudo systemctl reload lighttpd.service«, andernfalls manuell ein »sudo kill -n SIGUSR1 PID«. Die »PID« ermitteln Sie dazu mit dem Kommando »ps -A | grep lighttpd«. Die Tabelle “Von Lighttpd verstandene Signale” führt die von Lighttpd berücksichtigten Signale auf. Falls der Webserver noch nicht läuft, lässt er sich schnell via »sudo systemctl start lighttpd.service« oder manuell über »sudo lighttpd -f /etc/lighttpd/lighttpd.conf« aktivieren.

Signal

Reaktion

»SIGTERM«

Beendet Lighttpd

sofort, existierende Verbindungen brechen dabei ab.

»SIGINT«

Lighttpd beantwortet alle laufenden Anfragen und beendet sich danach.

»SIGUSR1«

Lighttpd beantwortet alle laufenden Anfragen und lädt dann seine Konfiguration neu.

»SIGHUP«

Lighttpd öffnet seine Log-Dateien erneut, lädt aber die Konfiguration nicht neu.

Flexible Kondition

Fordert ein Browser das Blog unter der Adresse »blog.example.com« an, soll Lighttpd immer die Seiten aus dem Verzeichnis »/var/www/html/blog« zurückliefern. Derartige Aufgaben lassen sich in der Konfigurationsdatei über Bedingungen (Conditionals) erreichen. Die Zeilen in Listing 4 testen, ob der angefragte Hostname mit »blog.example.com« identisch ist.

Listing 4

Hostnamen testen

$HTTP["host"] == "blog.example.org" {
  server.document-root = var.dir + "/html/blog"
}

»$HTTP[“host”]« steht dabei für den angefragten Hostnamen; alle alternativ verfügbaren Daten fasst die Tabelle “Daten in Bedingungen” zusammen. Trifft die Bedingung zu, wertet Lighttpd alle in den Klammern hinterlegten Einstellungen aus. Das Beispiel aus dem Listing setzt den Document-Root-Ordner auf das Verzeichnis »/var/www/html/blog/«. Sämtliche zwischen den geschweiften Klammern abgelegten Einstellungen gelten damit nur für »blog.example.org«. Auf diese Weise lassen sich vollkommen unterschiedliche Konfigurationen für verschiedene Domains hinterlegen und somit wiederum Virtual Hosts umsetzen.

Feld

Bedeutung

»$REQUEST_HEADER[“…”]«

Die in den Anführungszeichen angegebene Information aus dem Request Header. »$REQUEST_HEADER[“User-Agent”]« steht beispielsweise für den mitgeschickten User-Agent.

»$HTTP[“request-method”]«

Request-Methode.

»$HTTP[“scheme”]«

Schema der eingehenden Verbindung, entweder »http« oder »https«.

»$HTTP[“host”]«

Host-Name.

»$HTTP[“url”]«

Kompletter URL-Pfad ohne Domain-Name und Query-Strings (alles hinter einem »?« in der URL)

»$HTTP[“querystring”]«

Query String (alles hinter dem »?« in der URL).

»$HTTP[“remoteip”]«

Remote IP oder entferntes Netzwerk. Funktioniert nur mit IPv4.

»$SERVER[“socket”]«

Socket. Funktioniert nur mit dem Operator »==«, zudem muss der Wert im Format »IP:Port« vorliegen.

Anstelle des »==« testet ein »!=« auf Ungleichheit. Darüber hinaus lassen sich komplexere Regeln mit regulären Ausdrücken formulieren. Lighttpd berücksichtigt die Einstellungen in den geschweiften Klammern, wenn der reguläre Ausdruck rechts neben »=~« wahr beziehungsweise rechts neben »!~« falsch ist. Ein »$HTTP[“url”] =~ “^/blog/”« würde beispielsweise prüfen, ob die vom Browser angefragte URL mit der Zeichenkette »/blog/« beginnt. Darüber hinaus erlaubt Lighttpd verschachtelte Conditionals. Eine Bedingung darf folglich zwischen den geschweiften Klammern weitere Bedingungen enthalten.

Kommunikationsgeheimnis

Die meisten Funktionen von Lighttpd stellen Module bereit, die man je nach Bedarf aktiviert. Verschlüsselte Verbindungen via TLS rüstet beispielsweise das Modul »mod_openssl« nach (Listing 5), das bei seiner Arbeit wiederum OpenSSL einspannt. Mit Lighttpd 1.4.56 stießen vier weitere Module hinzu, die eine Verschlüsselung über mbedTLS (»mod_mbedtls«), WolfSSL (»mod_wolfssl«), GnuTLS (»mod_gnutls«) und NSS (»mod_nss«) abwickeln. Sie gelten allerdings noch als experimentell.

Listing 5

TLS-Konfiguration

server.modules = ("mod_openssl")
$SERVER["socket"] == ":443" {
  ssl.engine = "enable"
  ssl.pemfile = "/etc/lighttpd/server.pem"
}

Um das SSL_Modul einsetzen zu können, müssen Sie es zunächst mittels »server.modules = ( “mod_openssl” )« in der »lighttpd.conf« laden. Die Einstellungen für das Modul landen wieder in der zentralen Konfigurationsdatei. Im Fall von »mod_openssl« genügen bereits die Zeilen aus Listing 5: Die Bedingung prüft, ob die Anfrage über den Port »443« eingetrudelt ist. In diesem Fall knipst »ssl.engine« die Verschlüsselung an und nutzt dabei das von »ssl.pemfile« angegebene Zertifikat.

Ein passendes selbst signiertes Zertifikat generieren Sie schnell mit OpenSSL (Listing 6). Lighttpd unterstützt zudem das Let’s-Encrypt-Projekt. Die dazu notwendige, etwas komplexere Konfiguration erläutert ausführlich eine Wiki-Seite [4].

Listing 6

Zertifikat generieren

$ openssl req -new -x509 -keyout /etc/lighttpd/server.pem -out /etc/lighttpd/server.pem -days 365 -nodes

Zugangskontrolle

Um die Authentifizierung kümmert sich das Modul »mod_auth«. Um es zu aktivieren, ergänzen Sie es entweder in der Liste hinter »server.modules« oder fügen es im späteren Verlauf der »lighttpd.conf« über den Operator »+=« nachträglich hinzu (Listing 7).

Listing 7

Modul aktivieren

server.modules += ("mod_auth", "mod_authn_file")

Die Zugangskontrolle erfordert zwei Module: »mod_auth« nimmt nur einen Benutzernamen und ein Passwort entgegen und erfragt dann bei einem sogenannten Backend, ob der Benutzer ausreichende Zugriffsrechte besitzt. Die Backends stellen wiederum weitere Module bereit, zu denen auch »mod_authn_file« gehört. Es bietet gleich mehrere Backends an, die allesamt die Benutzerdaten aus Textdateien auslesen. Weitere verfügbare Backends verwenden stattdessen PAM oder einen LDAP-Server.

Welches Backend »mod_auth« nutzen soll, verrät eine entsprechende Einstellung in der »lighttpd.conf«. In Listing 8 kommt das Backend »plain« zum Einsatz, das die Passwörter im Klartext in einer einfachen Textdatei erwartet. »auth.backend.plain.userfile« weist das entsprechende Modul an, die Benutzerdaten aus der Datei »/etc/lighttpd/user.txt« zu holen. Sie enthält in jeder Zeile den Benutzernamen und das Passwort in der Form »User:Passwort«. »auth.require« verrät schließlich noch, dass beim Zugriff auf die URL »/blog« die Zugangsbeschränkung gilt, das Passwort im Klartext vorliegt (»”method” => “basic”«) und dass jeder autorisierte Benutzer Zugriff erhält (»”require” => “valid-user”«).

Listing 8

Backend bestimmen

auth.backend = "plain"
auth.backend.plain.userfile = "/etc/lighttpd/user.txt"
auth.require = ( "/blog" => ("method" => "basic", "realm" => "Anmeldung", "require" => "valid-user") )

Das Beispiel bildet eine zwar schnell eingerichtete, dafür jedoch relativ unsichere Form der Authentifizierung ab. Lighttpd und seine Module unterstützen übrigens nicht die von Apache bekannten ».htaccess«-Dateien. Eine Webanwendung, die darauf setzt, könnte unter Lighttpd folglich eine Sicherheitslücke aufweisen.

Verteilerkasten

Lighttpd bindet Skriptsprachen bevorzugt über die FastCGI-Schnittstelle ein, die das Modul »mod_fastcgi« nachrüstet. Es enthält gleichzeitig einen Load Balancer, der die Last auf mehrere FastCGI-Server verteilt. Passende Einstellungen für die »lighttpd.conf« zeigt das Beispiel aus Listing 9. Dort würde das Modul die Anfragen gleichmäßig per Round-Robin-Methode auf die Server verteilen (»fastcgi.balance = “round-robin”«).

Listing 9

FastCGI-Konfiguration für Lighttpd

server.modules += ( "mod_fastcgi" )
fastcgi.balance = "round-robin"
fastcgi.server = (
  ".php" => (
    ( "host" => "192.168.0.1",
      "port" => 1026,
    )
    ( "host" => "192.168.0.2",
      "port" => 1026,
    )
  )
)

An welche FastCGI-Server Lighttpd ein Skript zur Ausführung schickt, verraten die Einstellungen hinter »fastcgi.server«. Im Beispiel aus Listing 9 gibt der Webserver alle Dateien mit der Endung ».php« an einen von zwei FastCGI-Servern weiter. Der erste der beiden wartet unter der IP-Adresse 192.168.0.1 an Port 1026, der zweite am selben Port der IP-Adresse 192.168.0.2.

Unter Ubuntu genügt die Installation des Pakets php7.4-fpm, um PHP an einem Socket auf eingehenden PHP-Code warten zu lassen. In diesem Fall muss der Administrator den Webserver nur auf den passenden Socket hinweisen (Listing 10).

Listing 10

Socket angeben

fastcgi.server = ( ".php" =>
  (( "socket" => "/run/php/php-fpm7.4" ))
)

Lighttpd führt die Module immer in der Reihenfolge aus, in der sie hinter »server.modules« stehen beziehungsweise in der »lighttpd.conf« auftauchen. Sie sollten daher immer zuerst jene Module laden, die den Zugriff steuern (wie etwa »mod_auth«), und erst danach Module, die Inhalte erzeugen und zurückliefern (wie etwa »mod_fastcgi«). Andernfalls könnte Lighttpd die Authentifizierung überspringen.

Eine ausführliche Dokumentation (Abbildung 3) aller offiziellen Module sowie über den Webserver selbst findet sich im Lighttpd-Wiki [5].

Abbildung 3: Die Referenz im Lighttpd-Wiki gibt einen Überblick über die vorhandenen Module. Sie decken alle in der Praxis wichtigen Funktionen ab, wie etwa URL-Rewriting (»mod_rewrite«).

Abbildung 3: Die Referenz im Lighttpd-Wiki gibt einen Überblick über die vorhandenen Module. Sie decken alle in der Praxis wichtigen Funktionen ab, wie etwa URL-Rewriting (»mod_rewrite«).

Fazit

Die Arbeiten an Lighttpd beschränken sich derzeit auf die Pflege und eine behutsamen Weiterentwicklung des Versionszweigs 1.4. Dadurch hinkt der Webserver der Konkurrenz bei neuen Techniken etwas hinterher. Dennoch kann sich der Einsatz von Lighty lohnen. Benötigt etwa eine Arbeitsgruppe kurzfristig einen Webserver, lässt sich Lighttpd dank seiner kompakten und verständlichen Konfiguration schnell aufsetzen und über Module ebenso schnell an die Bedürfnisse des Teams anpassen. (uba/jlu)

DIESEN ARTIKEL ALS PDF KAUFEN
EXPRESS-KAUF ALS PDFUmfang: 5 HeftseitenPreis €0,99
(inkl. 19% MwSt.)
LINUX-MAGAZIN KAUFEN
EINZELNE AUSGABE Print-Ausgaben Digitale Ausgaben
ABONNEMENTS Print-Abos Digitales Abo
TABLET & SMARTPHONE APPS Readly Logo
E-Mail Benachrichtigung
Benachrichtige mich zu:
0 Kommentare
Älteste
Neuste Beste Bewertung
Nach oben