Nicht nachmachen: 2 Wege, wie ich Node.js NICHT auf dem Raspberry Pi installieren würde (und warum)

Als Video ansehen
Bereitgestellt über YouTube

Nicht nachmachen: 2 Wege, wie ich Node.js NICHT auf dem Raspberry Pi installieren würde (und warum)

Node.js brachte Googles V8 Engine vom Web auf den Desktop und Server. Längst wird die Plattform auch auf dem Raspberry Pi eingesetzt. Es gibt viele Wege, wie man Node.js auf dem Raspberry Pi oder auf (Debian) Servern installieren kann. Nicht alle davon sind empfehlenswert. In diesem Beitrag zeige ich euch zwei Wege, die ich nicht wählen würde und erkläre jeweils, welche Gründe dagegen sprechen. So könnt ihr entscheiden, ob diese Methoden im Einzelfall für euch geeignet sind, oder ihr ebenfalls besser die Finger davon lasst. Dies gilt für den Raspberry Pi eben so wie alle sonstigen Debian-Systeme, die z.B. auf der klassischen X86 Architektur laufen.

Methode #1: Die offiziellen Debian-Pakete von der APT-Paketverwaltung

Seit einiger Zeit wurde Node.js in die offiziellen Paketquellen von Debian aufgenommen. Da das Raspberry Pi darauf aufbaut, kann dieses Paket auch mit dem Raspberry Pi OS genutzt werden. Wie ich in meinem Beitrag zur Vorstellung von Debian ausführlicher erklärt habe, ist Stabilität die Stärke dieser GNU/Linux-Distribution. Dafür ist die Software schnell veraltet, wie man beispielhaft an Node.js sehen kann: Das aktuellste Raspberry Pi OS 11 wird mit LTS-Version 12 ausgeliefert. Diese Version hat am 30.04.2022 ihr Lebensende erreicht, wird also nicht mehr mit (Sicherheits-) Aktualisierungen versorgt.

daniel@pi:~ $ apt show nodejs
Package: nodejs
Version: 12.22.12~dfsg-1~deb11u4

Veraltete Software, die vom Hersteller nicht mehr unterstützt wird, sollte man grundsätzlich nicht einsetzen. Aufgrund der Architektur von Debian erhalten Debian und Raspberry Pi OS 11 Bullseye jedoch keine neue Hauptversion mehr, sondern erst die Nachfolgeversion. Dies wäre im Falle von Node.js aber notwendig, da jede Version nur vergleichsweise kurze Zeit unterstützt wird – zu wenig für den Lebenszyklus einer Debian-Version. Debian 12 ist vor wenigen Wochen erschienen, das Raspberry Pi OS folgt bald. Derzeit hat man über die offiziellen Paketquellen jedenfalls keine Alternative. Und auch in der Nachfolgeversion kann es schnell passieren, dass man vor dem gleichen Problem steht.

sudo apt install nodejs

Theoretisch kann man das Paket mit diesem Befehl sehr einfach installieren. Ich rate jedoch davon ab und empfehle stattdessen Container (z.B. mit Docker) oder die inoffiziellen Debian-Paketquellen, welche von Node.js bereitgestellt werden. Beide Wege sind etwas aufwändiger. Dafür erhaltet ihr aber eine aktuellere, unterstützte Node.js Version und zudem eine bessere Kontrolle darüber, welche Hauptversion überhaupt installiert wird. Neben der Sicherheits- und Fehler-Problematik benötigen manche Programme eine neuere Version, weil sie deren Funktionen verwenden. Bei Etherpad beispielsweise mindestens Node.js 16.20.1 oder neuer. Diese Software würde mit der älteren Version 12 aus den Paketquellen nur fehlerhaft oder gar nicht funktionieren. Zumindest wenn die in den Paketquellen angebotene Version ihr Lebensende erreicht hat, überwiegen die Nachteile definitiv, sodass man davon grundsätzlich Abstand nehmen sollte.

Methode #2: Manuelle Binärdateien

Im Download-Bereich von Node.js werden Archive angeboten, die alle notwendigen Binärdateien enthalten. Man lädt sich das zur Architektur passende Archiv: 64 Bit für X86, bei ARM v8 für den Raspberry Pi 4. V7 ist für den mittlerweile recht betagten Raspberry Pi 2 B.

Ab dem RPI 2 v1.2 nutzen alle neueren Modelle die 64 Bit ARMv8 Architektur. Das mag manche schon alleine deswegen überraschen, weil die 64 Bit Version des Raspberry Pi OS erst Jahre später überhaupt als Beta erschien. Der Prozessor ist jedoch schon weitaus vorher (ab den 2016 erschienenen Modellen) für die neue Architektur fit gewesen. Praktisch relevant wurde sie erst durch die Entscheidung mancher Softwarehersteller, ARM nur in 64 Bit zu unterstützen. Sowie dem Erscheinen der 8 GB Edition des Raspberry Pi 4, womit die Architektur ihre Vorteile bei Systemen mit mehr als 4 GB Arbeitsspeicher tatsächlich ausspielen kann.

Für den Raspberry Pi 4 verwende ich die ARMv8 Version, kopiere per Rechtsklick im Browser den Link und lade die Datei per wget herunter. Der folgende Link ist beispielhaft für die aktuellste Version zum Zeitpunkt des Artikels. Er sollte mit dem jeweils aktuellsten aus dem Download-Bereich ersetzt werden. Anschließend das Archiv mit tar entpacken. Dadurch erhalten wir einen Ordner, der den gleichen Name trägt, wie das Archiv. Im Unterordner bin liegen die Binärdateien der bekannten Node.js Werkzeuge: Die Laufzeitumgebung node, der Paketmanager npm und das Hilfswerkzeug npx zur Ausführung von Anwendungen aus NPM-Paketen heraus.

wget https://nodejs.org/dist/v18.17.0/node-v18.17.0-linux-arm64.tar.xz
tar -xf node-v18.17.0-linux-arm64.tar.xz

$ ls -lh | grep node-v18
drwxr-xr-x 6 daniel docker 4.0K Jul 18 13:39 node-v18.17.0-linux-arm64
-rw-r--r-- 1 daniel docker  23M Jul 18 13:41 node-v18.17.0-linux-arm64.tar.xz

$ node-v18.17.0-linux-arm64/bin/node -v
v18.17.0

Da der Ordner noch weitere Abhängigkeiten enthält, ist es nicht Ratsam, lediglich den Inhalt des Unterordners bin nach /usr/local/bin zu verschieben. Besser: Alles in /opt anlegen und falls man die Werkzeuge global aufrufen können möchte (wie bei einer Installation per APT), diesen Pfad zu $PATH hinzufügen (etwa in ~/.bashrc)

sudo mkdir /opt/nodejs-18
sudo chown $USER:$USER -R /opt/nodejs-18
mv node-v18.17.0-linux-arm64/* /opt/nodejs-18/
sed -i '1s#^#PATH=$PATH:/opt/nodejs-18/bin\n#' ~/.bashrc
. ~/.bashrc

$ node -v
v18.17.0
$ which node
/opt/nodejs-18/bin/node

Wir installieren APT und jeglichen anderen Paketmanagern vorbei – das ist Vorteil und Nachteil zugleich: Positiv ist die Flexibilität. Wir könnten beispielsweise in /opt/nodejs-20 problemlos die neuere (nicht LTS-Version) 20 ablegen. Zwar nicht global per $PATH nutzbar. Aber das würde etwa ermöglichen, die 18 LTS für produktive Software zu nutzen. Während parallel mit 20 experimentiert wird: Neue Funktionen ausprobieren, eine möglicherweise selbst entwickelte Anwendung auf die neue Version migrieren, usw. Nach dem gleichen Schema ließe sich auch eine ältere Version installieren, falls ein einzelnes Programm noch nicht mit 18 kompatibel ist. Es hängt also nicht mehr alles zusammen, sondern wir können flexibel verschiedene Versionen einsetzen, wie es für den Anwendungszweck notwendig/sinnvoll ist.

Warum ist diese Methode schlecht?

Was ist daran schlecht? Nun, durch diesen Vorteil erhalten wir eben auch keine zentralen Aktualisierungen per APT oder einer anderen Paketverwaltung. Der Verantwortliche muss sich selbstständig über neue Versionen informieren – etwa, in dem er den Node.js Blog regelmäßig aufruft. Sind Updates verfügbar, müssen alle eingesetzten Versionen aktualisiert werden. Das ist machbar, vor allem wenn man sich mit Hilfsmitteln vor dem Vergessen schützt: Beispielsweise durch Abonnieren des RSS-Feeds vom Node.js Blog, damit man die Aktualisierungen beim morgendlichen Lesen der Feeds auf jeden Fall sieht.

Die Praxiserfahrung zeigt jedoch: Viele nehmen das nicht so ernst. Nach ein paar Monaten wird vergessen, dass man da ja was händisch installiert hatte. Mangels Dokumentation fällt es dann leider meist erst auf, wenn z.B. die auf Node laufende Software aktualisiert wurde und mit der inzwischen alten Laufzeitumgebung nicht mehr kompatibel ist. Oder noch viel schlimmer: Durch die fehlenden Aktualisierungen sind Schwachstellen vorhanden, die von einem Angreifer ausgenutzt werden.

Ich setze diesen Weg nur auf einem Buildserver ein, der mehrere Node.js Laufzeitumgebungen (alle LTS) benötigt. Diese haben keine direkte Verbindung zum Internet, ich verfolge die neuen Veröffentlichungen und spiele Aktualisierungen mittels Ansible zeitnah ein.

Fazit

Mit den offiziellen Paketquellen erhält man oft von Anfang an eine alte Version, über die manuelle Version wird sie leicht schleichend und unbemerkt alt – so könnte man die Problematik in einem Satz zusammen fassen. Je nach Einsatzzweck sind die daraus entstehenden Probleme sowie Risiken geringer oder höher. Ich persönlich rate vom Einsatz veralteter Software ab und plädiere dafür, Aktualisierungen so zeitnah wie möglich einzuspielen. Die offiziellen Paketquellen disqualifizieren sich daher leider komplett.

Bei Variante 2 ist es schon schwieriger: Hier hat man eine recht flexible und sichere Möglichkeit, wenn man sich konsequent um die Pflege kümmert – was jedoch leicht vergessen wird. Auch das würde ich daher meiden, außer es ist unvermeidbar und man weiß genau, was man tut. Für viele Szenarien gibt es bessere Alternativen, wie etwa der Einsatz von Containern. Hier kann man relativ leicht Sicherheitsupdates und Bugfixes automatisch mit Watchtower einspielen lassen.


Leave a Reply