Um einen Nodejs-Server aufzusetzen braucht es nicht viel. Eigentlich nur die Binaries und eine JS-Datei mit dem eigentlichen Server. Doch wenn man den Server dauerhaft und bequem zugreifbar betreiben möchte, sind ein paar mehr Schritte notwendig.
Zunächst wird Nodejs und der Paketmanager npm installiert:
1 | apt-get install nodejs npm |
Danach richten wir den Proxy ein, sonst wäre ein Aufruf nur über einen Nicht-Standard-Port (80 ist ja schon vom Apachen belegt) möglich. In der Regel verwendet Nodejs hier Port 3000, aber das ist je nach Script unterschiedlich. Wir aktiviren also zunächst den Passthrough-Modus:
1 2 | a2enmod proxy a2enmod proxy_http |
Für die eigentliche Einrichtung kann jetzt ein eigener VHost (z.B. eine Subdomain) angelegt werden, oder – wie in meinem Beispiel – ein Unterverzeichnis hergenommen werden.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | <VirtualHost ip:80> ServerName myhost.com:80 ServerAlias www.myhost.com UseCanonicalName Off DocumentRoot /var/www/vhosts/myhost/httpdocs ErrorLog /var/www/vhosts/myhost/statistics/logs/error_log ... <Directory /var/www/vhosts/myhost/httpdocs> Options -Includes +ExecCGI </Directory> <Proxy *> Order deny,allow Allow from all </Proxy> <Location /mynodejspath> ProxyPass http://localhost:3000 ProxyPassReverse http://localhost:3000 </Location> </VirtualHost> |
Würde man nun nodejs manuell starten, könnte man schon per http://myhost.com/mynodejspath darauf zugreifen. Da Nodejs aber noch ein wenig fehleranfällig ist und dann gern mal sang- und klanglos abtritt, benutze ich monit zur Überwachung und ggf. zum Neustart des Servers (der Nodejs-App).
1 | apt-get install monit |
Als Startscript verwende ich ein Standard-init.d-Script, sodass ich auch beim Systemstart problemlos den Nodejs-Server mitstarten lassen kann. Dabei ist zu beachten, dass ich auf Benutzer „root“ prüfe und den Nodejs-Server ggf. über einen extra User starte. Andere Nutzer starten die Nodejs-App mit diesem Script als sie selbst.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 | #!/bin/bash DIR=/var/www/vhosts/myhost/httpdocs/mynodejspath PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin NODE_PATH=/usr/lib/node_modules NODE=/usr/bin/node test -x $NODE || exit 0 function start_app { if [ $(whoami) = "root" ] then NODE_ENV=production nohup sudo -u nodejsusername "$NODE" "$DIR/app.js" 1>>"$DIR/logs/node.log" 2>&1 & echo $! > "$DIR/pids/node.pid" else NODE_ENV=production nohup "$NODE" "$DIR/app.js" 1>>"$DIR/logs/node.log" 2>&1 & echo $! > "$DIR/pids/node.pid" fi } function stop_app { kill `cat $DIR/pids/node.pid` } case $1 in start) start_app ;; stop) stop_app ;; restart) stop_app start_app ;; *) echo "usage: myapp {start|stop|restart}" ;; esac exit 0 |
Die Verzeichnisse „pids“ und „logs“ müssen unter dem App-Pfad noch angelegt werden. Danach kommt das Monit-Script nach /etc/monit/noderc:
1 2 3 4 5 6 7 8 9 10 | #!monit set logfile /var/log/monit.log check process nodejs with pidfile "/var/www/vhosts/myhost/httpdocs/mynodejspath/pids/node.pid" start program = "/etc/init.d/myapp start" stop program = "/etc/init.d/myapp stop" if failed port 3000 protocol HTTP request / with timeout 10 seconds then restart |
… und ein Starter-init.d Script nach /etc/init.d/monit:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | #!/bin/bash case $1 in start) monit -d 60 -c /etc/monit/noderc ;; stop) killall monit ;; restart) stop_app start_app ;; *) echo "usage: monit {start|stop|restart}" ;; esac exit 0 |
Ein Symlink nach rc2.d komplettiert die Automatisierung:
1 2 | cd /etc/rc2.d/ ln -s ../init.d/monit S99monit |
Somit haben wir viele Probleme gelöst:
- Nodejs startet mit dem Server
- Es wird überwacht und falls notwendig neu gestartet
- Der Jeweilige Besitzer (und root) können es manuell neu starten
- Es läuft mit eingeschränkten Userrechten
- Es ist über Port 80 zugreifbar
- und wir haben wieder etwas gelernt 😉