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 |
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 |
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> |
<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).
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 |
#!/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 |
#!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 |
#!/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 |
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 😉