Recently I gave myself simple task to test out tiny node.js app on server. While starting it manually is no brainer but it made me think more when I wanted to make it work as background service.
Usually I do it in /etc/init.d/
folder by creating bash script and run it from there, it is reliable, it is how httpd starts. But after some googling I found people talking about upstart and monit, I did feel like caveman, but took it seriously and opened upstart cookbook and just started to evaluate how should I eat it and if it is poisonous.
So after some digging I did decide to run node.js with upstart just because its new to me and its philosophy of event driven approach seems close to node. But challenges just began.
Upstart is not supported in all distros, and I was lucky that centos supports it and has version pre-installed, but sadly its 0.6.5
which is away from now latest 1.5
. I could have downloaded latest package and “try” to install it but I thought it is not worth the effort to just try out small node app.
Single instance
My upstart version is 0.6.5, so how should I take care of starting node as background service. Well first thing is to specify user for node to run. I did install node from binary tarball to /usr/share/node/node-v0.8.9-linux-x64
, later created apps
folder in /usr/share/node
and added sample express3 app from node passport-local
module examples. Then created user node
and changed /usr/share/node
ownership recursively to node
user with chown -R node /usr/share/node
.
By default app will not even start as it has some dependencies but those could be handled with npm which comes with node installation by default.
Next step was to start this app as a background service as title of this article says. For a service aka job to be started by upstart it is required to put *.conf
file into /etc/init/
directory. In upstart 1.4
and upwards it could be placed into $home/.init/
but not in my case. Upstart is evented system so basically you react to events on system and do your stuff, you can also emit your own events and catch those in other scripts. So in my case I had to write simple script which listens to some sort of startup event and starts app after it gets one, so after reading docs and googling I came up with louischatriot’s script found on github:
# /etc/init/node.conf
description 'node system startup'
author 'ivarprudnikov.com'
env NAME=AppName
env LOG_FILE=/usr/share/node/some.log
env USER=node
env NODE_BIN=/usr/share/node/node-v0.8.9-linux-x64/bin/node
env SCRIPT_FILE=/usr/share/node/apps/examples/express3/app.js
start on runlevel [2345] stop on runlevel [016]
# Respawn in case of a crash, with default parameters
respawn
script
# Make sure logfile exists and can be written by the user we drop privileges to
touch $LOG_FILE
chown $USER:$USER $LOG_FILE
# recommended approach in case of su/sudo usage so that service does not fork
exec su -s /bin/sh -c 'exec "$0" "$@"' $USER -- $NODE_BIN $SCRIPT_FILE >> $LOG_FILE 2>&1
end script
post-start script
echo "app $NAME post-start event" >> $LOG_FILE
end script
After saving file it is possible just to run it with initctl start node
and app should be started.
But after restart I did not see it running, so what was wrong?? I found answer on serverfault and debug file to test out events fired in the system:
# /etc/init/debug.conf
start on ( starting JOB!=debug \
or started JOB!=debug \
or stopping JOB!=debug \
or stopped JOB!=debug )
script
exec 1>>/tmp/log.file
echo -n "$UPSTART_JOB/$UPSTART_INSTANCE ($0):$$:`date`:"
echo "Job $JOB/$INSTANCE $UPSTART_EVENTS. Environment was:"
env
echo
end scripts
So now after looking into /tmp/log.file
I could choose which event to listen to and start node app. I changed:
start on runlevel [2345]
stop on runlevel [016]
to
start on started network
stop on stopping network
So now app is running in background, restarts in case of failure, starts on startup. Things to consider are hooking to events which are important to node, it would be possible to have nginx
set up in this way and then:
start on ( started network and started nginx )
Useful links
- http://upstart.ubuntu.com/cookbook
- http://superuser.com/questions/213416/running-upstart-jobs-as-unprivileged-users
- http://josesantiagojr.com/post/29633984407/deploying-node-js-with-upstart-and-monit
- https://gist.github.com/3385102/9de6178ab838a3450fc04204cc244be0e0cab925
- http://clock.co.uk/tech-blogs/upstart-and-nodejs
- http://clock.co.uk/tech-blogs/deploying-nodejs-apps