In diesem Artikel möchte ich euch eine Anleitung an die Hand geben mit der ihr eine Node.js Applikation auf einem Server, in diesem Fall einen Raspberry Pi, laufen lassen könnt. Das verwendete Betriebssystem auf dem Pi ist Raspbian Lite 64bit.
Node.js installieren
Die zu diesem Zeitpunkt aktuelle Node.js Version ist die v18.3.0.
curl -fsSL https://deb.nodesource.com/setup_18.x | sudo -E bash -
sudo apt-get install -y nodejs
Die korrekte Installation von Node.js und npm, welches im Normalfall direkt mit installiert wird, könnt ihr über die Version prüfen.
pi@webserver:~ $ node -v
v18.3.0
pi@webserver:~ $ npm -v
8.11.0
Sollt aus irgendeinem Grund bei der Prüfung der Version von npm ein command not found erscheinen könnt ihr npm nachinstallieren.
curl -qL https://www.npmjs.com/install.sh | sh
Spätestens jetzt solltet das npm Kommando funktionieren.
Applikation kopieren und installieren
Ich habe für meine Applikation der Gartensprenger Steuerung einen Ordner unter /var/www/nodejs angelegt in den ich die Daten kopiere. In meinem Fall gibt es 3 Javascript Dateien und die package.json. Die package.json ist wichtig mitzukopieren, denn in ihr sind alle Abhängigkeiten und Parameter konfiguriert, die die Applikation zum laufen braucht.
pi@webserver:/var/www/nodejs/garten-beregnung-server $ ls -lah
total 28K
drwxr-xr-x 2 pi root 4.0K Jun 9 08:38 .
drwxr-xr-x 3 pi root 4.0K Jun 9 07:54 ..
-rw-rw-r-- 1 pi pi 458 Jun 9 08:19 api.js
-rw-rw-r-- 1 pi pi 804 Jun 9 08:19 logger.js
-rw-rw-r-- 1 pi pi 439 Jun 9 08:19 package.json
-rw-rw-r-- 1 pi pi 4.2K Jun 9 08:19 server.js
Stellt sicher, dass ihr euch mit dem Terminal in dem Ordner eurer Applikation befindet und führt den npm install Befehl aus.
pi@webserver:/var/www/nodejs/garten-beregnung-server $ npm install
added 103 packages, and audited 104 packages in 33s
13 packages are looking for funding
run `npm fund` for details
found 0 vulnerabilities
Die Installation kann nach Größe und Komplexität mehrere Minuten dauern. Durch die Installation wurde der node_modules Ordner erstellt.
pi@webserver:/var/www/nodejs/garten-beregnung-server $ ls -lah
total 104K
drwxr-xr-x 3 pi root 4.0K Jun 9 08:43 .
drwxr-xr-x 3 pi root 4.0K Jun 9 07:54 ..
-rw-rw-r-- 1 pi pi 458 Jun 9 08:19 api.js
-rw-rw-r-- 1 pi pi 804 Jun 9 08:19 logger.js
drwxr-xr-x 104 pi pi 4.0K Jun 9 08:43 node_modules
-rw-rw-r-- 1 pi pi 439 Jun 9 08:19 package.json
-rw-r--r-- 1 pi pi 69K Jun 9 08:43 package-lock.json
-rw-rw-r-- 1 pi pi 4.2K Jun 9 08:19 server.js
Zum testen der Applikation könnt ihr diese einmal starten.
pi@webserver:/var/www/nodejs/garten-beregnung-server $ node server.js
info: Example app listening on port 3001 {"timestamp":"2022-06-09T07:45:06.536Z"}
Meine Applikation gibt beim Starten aus, auf welchem Port sie lauscht.
Autostart und Restart nach Absturz
Ich möchte, dass die Node.js Applikation beim Systemstart automatisch startet. Weiterhin soll diese auch neustarten, falls sie abstürzt. PM2 ist ein Prozessmanager für Node.js. Dieser verwaltet die Applikationen und leistet eben das.
Zum Installieren können wir npm nutzen. Das Flag -g gibt an, dass der PM2 global, also nicht für dieses lokale Projekt installiert werden soll.
npm install pm2 -g
Der Befehl pm2 kann systemweit aufgerufen werden. Ruft die Liste der Applikationen von pm2 auf. Diese ist noch leer.
pi@webserver:/var/www/nodejs/garten-beregnung-server $ pm2 list
┌─────┬───────────┬─────────────┬─────────┬─────────┬──────────┬────────┬──────┬───────────┬──────────┬──────────┬──────────┬──────────┐
│ id │ name │ namespace │ version │ mode │ pid │ uptime │ ↺ │ status │ cpu │ mem │ user │ watching │
└─────┴───────────┴─────────────┴─────────┴─────────┴──────────┴────────┴──────┴───────────┴──────────┴──────────┴──────────┴──────────┘
Startet eure Applikation über pm2.
pi@webserver:/var/www/nodejs/garten-beregnung-server $ pm2 start server.js
[PM2] Starting /var/www/nodejs/garten-beregnung-server/server.js in fork_mode (1 instance)
[PM2] Done.
┌─────┬───────────┬─────────────┬─────────┬─────────┬──────────┬────────┬──────┬───────────┬──────────┬──────────┬──────────┬──────────┐
│ id │ name │ namespace │ version │ mode │ pid │ uptime │ ↺ │ status │ cpu │ mem │ user │ watching │
├─────┼───────────┼─────────────┼─────────┼─────────┼──────────┼────────┼──────┼───────────┼──────────┼──────────┼──────────┼──────────┤
│ 0 │ server │ default │ 1.0.0 │ fork │ 8315 │ 0s │ 0 │ online │ 0% │ 34.6mb │ pi │ disabled │
└─────┴───────────┴─────────────┴─────────┴─────────┴──────────┴────────┴──────┴───────────┴──────────┴──────────┴──────────┴──────────┘
Die Applikation würde beim Absturz automatisch neustarten. Im Moment würde die Applikation nach einem Reboot nicht automatisch starten.
pm2 generiert ein systemd Autostart Script mit.
pi@webserver:/var/www/nodejs/garten-beregnung-server $ pm2 startup systemd
[PM2] Init System found: systemd
[PM2] To setup the Startup Script, copy/paste the following command:
sudo env PATH=$PATH:/usr/bin /usr/lib/node_modules/pm2/bin/pm2 startup systemd -u pi --hp /home/pi
Führt das Script aus der letzten Zeile aus.
sudo env PATH=$PATH:/usr/bin /usr/lib/node_modules/pm2/bin/pm2 startup systemd -u pi --hp /home/pi
Abschließend speichert alle Einstellungen und Applikationen mit pm2 save.
pi@webserver:/var/www/nodejs/garten-beregnung-server $ pm2 save
[PM2] Saving current process list...
[PM2] Successfully saved in /home/pi/.pm2/dump.pm2
Konfigurieren des Zugriffes per Nginx
Ich habe auf dem Raspberry viele Projekte laufen und möchte diese von außen nicht über verschiedene Ports ansprechen. Ich löse das über DNS Einträge. Wie ihr einen DNS Server mit Pihole aufsetzen könnt habe ich euch hier erklärt.
Mein Ziel ist es den Server der Gartenberegnung über garten-server.home.loc Port 80 verfügbar zu machen. Die Node.js Applikation läuft auf Port 3001. Ich werde nur die Konfiguration bereitstellen. In diesem Artikel bin ich näher auf die Konfiguration von Nginx eingegangen.
server {
listen 80;
listen [::]:80;
server_name garten-server.home.loc;
location / {
proxy_set_header Host $host;
proxy_cache_bypass $http_upgrade;
proxy_pass http://127.0.0.1:3001;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection 'upgrade';
}
}