C Webserver selbst kompilieren: Aktuellster Nginx auf dem Raspberry Pi

Als Video ansehen
Bereitgestellt über YouTube

C Webserver selbst kompilieren: Aktuellster Nginx auf dem Raspberry Pi

Quelloffene Projekte wie den Nginx Webserver kann man selbst kompilieren. Dafür gibt es verschiedene Gründe: Etwa möchte man die neueste Version nutzen, ihn verändern, Erweiterungen einbauen oder auch einfach die Funktionsweise besser verstehen, vielleicht sogar selbst am Projekt mitwirken. Das ist gar nicht so schwer, wie es zunächst vielleicht klingen mag. In diesem Beitrag werden wir uns dies anhand des Webservers Nginx anschauen, der aufgrund seiner Leistung und Effizient seit längerem an Verbreitung gewinnt.

Was bedeutet kompilieren überhaupt?

Viele gängige Programmiersprachen sind sogenannte höhere Programmiersprachen, das heißt: Sie wurden für Menschen optimiert, auch wenn manche dabei gelegentlich Zweifel haben. Computer verstehen nur Nullen und Einsen, womit sich viele Menschen wiederum schwer tun. Ein Compiler ist dabei der Übersetzer: Durch das Kompilieren verwandelt er den Code in eine für Computer lesbare Form – nämlich Binärcode.

Bei hardwarenahen Sprachen wie C oder C++ muss pro Architektur neu kompiliert werden: Binärcode von einem x86 PC läuft also nicht auf einem Pi mit ARM-Prozessor. Aus dem Grunde gibt es auch mehr Softwarepakete für den Linux-Desktop, als den Raspberry Pi: Dort ist x86 der Standard, ARM dagegen selten. Allerdings können wir diese alternativ auch selbst kompilieren – sofern sie Open Source ist. Bei proprietärer Software ist man dagegen komplett auf den Hersteller angewiesen. Bietet er keine (32 Bit) ARM Builds an, sieht es schlecht aus.

So kompilierst du die neueste stabilste Nginx Version auf dem Raspberry Pi

1. Quellcode herunterladen

Zunächst benötigen wir den Quellcode. Er lässt sich als .tar.gz Archiv vom Downloadbereich der offiziellen Internetseite herunterladen. Im Folgenden nehme ich die zum Erstellungszeitpunkt aktuellste Mainline Version 1.21.3, lade sie auf den Pi und entpacke das Archiv:

$ wget https://nginx.org/download/nginx-1.21.3.tar.gz
$ tar xfvz nginx-1.21.3.tar.gz
$ ls -l ~/nginx-test/
total 1044
drwxr-xr-x 9 pi pi    4096 Oct 12 18:55 nginx-1.21.3
-rw-r--r-- 1 pi pi 1061461 May 25 16:34 nginx-1.21.3.tar.gz
$ cd nginx-1.21.3

Zur Entscheidungshilfe zwischen Stable und Mainline ist gut zu wissen: Mainline bekommt alle Fehlerkorrekturen, Stable dagegen nur kritische. Mainline ist daher tendenziell zuverlässiger. Zumindest wenn man keine Drittanbieter-Module verwendet, Probleme damit sind bei Stable unwahrscheinlicher.

Doch sollten wir den Quellcode nicht in /usr/local/src ablegen, so wie es der Dateisystem-Hierarchiestandard von Linux vorsieht? Jein: Der Ordner ist zwar für selbst eingefügten Quellcode vorsehen. Aber eher zur Archivierung – also nicht als Arbeitsverzeichnis, in dem er compiliert wird, so wie wir das gleich machen. Daher habe ich das ganze hier ins Home-Verzeichnis vom Pi-Benutzer gelegt.

2 Zielverzeichnis anlegen

Wir legen den Zielordner an, in dem die Daten des kompilierten Nginx später liegen sollen und hinterlegen den Pi-Benutzer als Eigentümer – so vermeiden wir, das Buildwerzeug später mit sudo aufrufen zu müssen. Wenn ihr einen anderen Nutzer verwendet, entsprechend anpassen.

sudo mkdir /opt/nginx
sudo chown pi:pi /opt/nginx/

3. Abhängigkeiten installieren & Konfigurieren

Vor dem kompilieren kommt das konfigurieren: Wir legen fest, was genau mit welchen Funktionen gebaut werden soll. Details dazu findet ihr in der Dokumentation des Quellcodes. Dies geschieht über das Werkzeug configure. Ein minimalistischer Aufruf sieht so aus:

./configure --prefix=/opt/nginx 

Das –prefix Verzeichnis ist der Ordner, in dem später die fertig kompilierte Anwendung liegen soll. Bevor du die Konfiguration startest, installieren wir die Abhängigkeiten. Das sind APT-Pakete, die meist auf -dev enden, bei Ubuntu -devel. Sie enthalten alle Dateien die man benötigt, um Code zu kompilieren, der die jeweilige Bibliothek nutzt. Beispielsweise Header-Dateien, welche die Schnittstellen beschreiben. PCRE ist eine Bibliothek für reguläre Ausdrücke, die Nginx z.B. für die Routen nutzt. Ein Compiler wird ebenfalls benötigt, wobei gcc in aktuellen Pi-Images normal vorinstalliert ist.

sudo apt install gcc libpcre3-dev

Anhand der Dokumentation seht ihr, dass man einige weitere Einstellungen vornehmen kann. Das reicht von Standardpfaden bis hin zu Modulen. Ein Modul erweitert den Webserver um eine bestimmte Funktion. Beispiel: Das http_ssl_modul bietet die Möglichkeit, verschlüsselte Verbindungen mit HTTPS zu nutzen. Wenn wir das aktivieren möchten, brauchen wir wie in der Dokumentation die OpenSSL-Bibliothek:

sudo apt install libssl-dev

Nun könnten wir den Compiler anweisen, das SSL-Modul ebenfalls mit einzuschließen. Dafür brauchen wir aber zunächst das OpenSSL-Modul, wie in der Doku beschrieben:

sudo apt install libssl-dev
./configure --prefix=/opt/nginx --with-http_ssl_module

Ebenfalls sinnvoll sind –with-threads und –with-file-aio zur Leistungsverbesserung.

Standardmäßig vorhandene Module lassen sich jeweils mit –without-XYZ deaktivieren. Möchten wir z.B. keine Proxy-Verbindungen an andere Webserver weiterreichen, können wir es mit –without-http_proxy_module abschalten. Gleiches gilt für eine Reihe anderer Module, etwa –without-http_memcached_module. Wer diese Funktionen nicht nutzt, kann sie hier deaktivieren – dadurch wird der Webserver schlanker und das compilieren beschleunigt sich etwas.

Während des Konfigurierens wird geprüft, ob alle Abhängigkeiten vorhanden sind. Wenn ihr also beispielsweise ein Modul aktiviert, das zusätzliche Bibliotheken benötigt und diese fehlen, erscheint ein entsprechender Fehler.

4. Abhängigkeiten installieren & Konfigurieren

Durch das vorherige Konfigurieren ist ein Makefile entstanden. Es gehört zu make, ein Werkzeug um den Buildprozess abzubilden. Im Makefile befinden sich alle Anweisungen, die notwendig sind, um Nginx mit den gewünschten Modulen zu kompilieren. Außerdem erstellt es die von der Anwendung benötigte Ordnerstruktur im Zielordner, der mit –prefix zuvor abgegeben wurde. Darin wird z.B. auch eine Standard-Konfigurationsdatei für den Webserver angelegt. Um das zu starten, führen wir folgenden Befehl aus:

make install

Der Vorgang dauert auf einem Raspberry Pi 4 gute 1,5 Minuten. Danach solltet ihr einen kompletten Nginx Webserver im Zielverzeichnis (hier /opt/nginx) liegen haben:

$ ls -lh /opt/nginx/
total 16K
drwxr-xr-x 2 pi pi 4.0K Oct 12 19:55 conf
drwxr-xr-x 2 pi pi 4.0K Oct 12 19:55 html
drwxr-xr-x 2 pi pi 4.0K Oct 12 19:55 logs
drwxr-xr-x 2 pi pi 4.0K Oct 12 19:55 sbin

Um ihn zu starten:

sudo /opt/nginx/sbin/nginx

Den Startbefehl müssen wir als root ausführen, da nginx die privilegierten Ports 80 und bei HTTPS-Aktivierung auch 443 nutzt. Normale Nutzer dürfen keine Prozesse starten, die auf Ports unter 1024 lauschen.

Im Browser sollte unter dem Hostname bzw. der IP-Adresse des Pi nun eine Welcome to nginx Seite zu sehen sein:

Wie kann man auf eine neue Nginx-Version aktualisieren?

Zuerst den laufenden Webserver stoppen:

sudo /opt/nginx/sbin/nginx -s stop

Anschließend das neue .tar.gz Archiv wie oben beschrieben herunterladen, entpacken, den ./configure Befehl gefolgt von make install ausführen. Nach dem Start des Webservers läuft er in der aktuellen Version. Nachprüfen kann man dies beispielsweise mit -v

$ /opt/nginx/sbin/nginx -v
nginx version: nginx/1.21.3

Standardmäßig sendet Nginx zudem einen Server-Header als Antwort auf jede Anfrage. Er enthält Name und Version:

Um Updates zu erleichtern, macht es Sinn, die Anweisungen in einem Skript zu bündeln. Dadurch ist das Aktualisieren leichter und ihr habt die aktivierten bzw. deaktivierten Module automatisch dokumentiert, sodass keines vergessen wird.

Fazit: Vor- und Nachteile von selbst kompilierten Programmen

Das selbst kompilieren kann uns bei quelloffener Software einige Vorteile bieten. Hauptsächlich Anpassbarkeit und die Verwendung von aktuellen Versionen sowie zusätzlichen Module. Es ermöglichte die Verwendung der aktuellen stabilen 1.21.3 Version, wogegen in den Paketquellen zum Zeitpunkt des Tests lediglich 1.14.2 enthalten war. Zum Vergleich: 1.14.2 ist vom Dezember 2018, also knapp 3 Jahre alt.

Allerdings gibt es auch einen Nachteil: Selbst kompilierte Software kann nicht über die Paketverwaltung aktualisiert werden. Wie alle händisch installierten Programme müssen wir uns daher selbst über Aktualisierungen informieren und sollten vor allem Sicherheitsupdates zeitnah einspielen. Dies gilt umso mehr, wenn der Pi nach außen hin erreichbar ist. Man sollte im Einzelfall entscheiden, was sinnvoller bzw. wichtiger ist.

Für den selbst kompilierten Nginx solltet ihr zudem beachten, dass dieser nicht automatisch zusammen beim Booten des Pi gestartet wird. Das lässt sich am sinnvollsten mit einem Systemd-Dienst umsetzen.

Grundsätzlich lässt sich diese Vorgehensweise auch auf andere Open Source Projekte übertragen. Sowohl andere Webserver wie z.B. Apache2, als auch Programme mit anderen Verwendungszwecken. Gegebenenfalls sind dafür mehr oder weniger Änderungen notwendig, das hängt stark vom Projekt ab. Und es lässt sich eben so auf jedem Linux-Computer oder Server umsetzen, auch mit x86 Architektur.

Leave a Reply