What are the steps required for setting up a Node.js application on Webfaction shared hosting account?
Node. js is an open-source, cross-platform, back-end JavaScript runtime environment that runs on the V8 engine and executes JavaScript code outside a web browser. Node. js is not supported on Shared and Cloud hosting packages.
The Node. js selector allows you to easily set up Node. js applications with the cPanel graphical interface or using the command line. Use whichever method you prefer.
php script installs an official node. js package, starts a hidden server on localhost:49999 with provided JS file and proxies all requests to it.
The result of the following instructions is a Node.js application that is running continously, produces logfiles and restarts itself even after the reboot of the server machine. The instructions are especially targeted for the shared host accounts on Webfaction but can be used for general purpose also.
Eventhough Node.js download page offers Linux binaries, it would be more robust to install Node.js from source. Download the most recent source codes and extract them to ~/src/
.
(log in to your webfaction console)
> mkdir -p ~/src/
> cd src/
> wget http://nodejs.org/dist/v0.10.18/node-v0.10.18.tar.gz
> tar -xzf node-v0.10.18.tar.gz
The next step is to compile and install the code. For this Python is used. Because the default python
version is 2.4 (at least on my Webfaction server web223) and because the Node.js installation requires one of the versions 2.6+, you must temporarily set newer version to be the default. See the following snippet (also see this article for details). Note --prefix=$HOME
which is required due Webfaction's environment restrictions (you have access only to your home directory).
> cd node-v0.10.18/
> alias python=python2.7
> python configure --prefix=$HOME
> make
> make install
Node.js installed. Verify the success by
> node -v
v0.10.18
That also installed node package manager npm
.
> npm -v
1.3.8
To keep run Node.js application running as long as possible and logging the output for maintenance, you need Forever. For convenience, install it globally (for you) using flag -g
.
> cd ~
> npm install -g forever
> forever --version
v0.10.8
You can later update forever by
> npm update -g forever
First, create a custom application via Webfaction Control Panel (Custom app (listening on port)). Name it for example foonode. You may also create a domain and website for the app.
Second, make a note about the socket port number that was given for the app by Webfaction. Let the example be 48888.
Third, copy your application code to the directory of the app i.e. ~/webapps/foonode/
. After that the directory contents would for example be the following.
> cd ~/webapps/foonode/
> ls
node_modules/
index.js
Index.js would be something like the snippet below. The key point is using the given port number for the app.
var http = require('http');
http.createServer(function (req, res) {
res.writeHead(200, {'Content-Type': 'text/plain'});
res.end('Hello Universe.\n');
}).listen(48888, '127.0.0.1');
console.log('Listening at http://127.0.0.1:48888/');
Now you could run the app by node index.js
. However there is a problem: when you exit the shell, also the app exits. Therefore you should run the Node.js as a daemon. That is something where Forever does a lot for you. Start node with forever:
> cd ~/webapps/foonode/
> forever start index.js
Now the app continues running after you logout and, as a very nice thing to have, is quickly restarted if it happens to crash. This is a lot but still not enough. What if the server reboots? Where is the output from the app going? What if the script crashes continously? What if you have multiple scripts with the name index.js
? Keep reading.
Forever identifies the process by the filename of the script fed to forever start <filename_of_script>
. A problem arises when you have multiple applications with the same filename for the script.
For example consider you have two applications /home/foouser/webapps/foonode/index.js
and /home/foouser/webapps/barnode/index.js
. If you now start both with forever start index.js
within the directories of the applications and then run forever stop index.js
only once, the result is that both applications become stopped. This happens because they both had the same identity index.js
The solution is to use the absolute filepaths when specifying the script.
> forever start /home/foouser/webapps/foonode/index.js
And to stop execution:
> forever stop /home/foouser/webapps/foonode/index.js
This ensures that only the intended application becomes stopped. This habit of using absolute paths has also positive effects to forever list
. See this issue for details.
To store the application output to somewhere, specify the following arguments.
-l <logfile> = stream all output to this file. Relative to ~/.forever/
-o <logfile> = stream script's stdout to this file. Relative to current dir.
-e <logfile> = stream script's stderr to this file. Relative to current dir.
-a = append to the files instead of overwriting them.
It seems convenient to have a subdirectory for the logs, e.g. logs/
. With the arguments, absolute path and the subdirectory logs/ the command becomes the following:
> cd ~/webapps/foonode/
> mkdir -p logs/
> forever start -a -l forever.log -o logs/out.log -e logs/err.log /home/foouser/webapps/foonode/index.js
Forever has the parameters --minUptime
and --spinSleepTime
which are not so well documented currently. The meaning of the parameters is to control situation where the script crashes and almost immediately crashes again after restart. As forever tries to restart the script as soon as possible after the crash, this can lead to a busy loop which may eat lots of resources of the server.
--minUptime
specifies the number of milliseconds the script has to be up and running without crashes to be restarted immediately. If the uptime of the crashed script is less than minUptime, then the script is considered spinning i.e. problematic. If uptime is greater then the script is considered non-spinning.
If a spinning script crashes i.e. the uptime of the script is less than --minUptime
then forever waits --spinSleepTime
number of milliseconds before restarting the script. Otherwise the script is restarted as soon as possible. This prevents the resource-eating loop. See this answer for futher discussion.
I personally use 5000 for --minUptime
to make sure that Node is fully started before declaring it non-spinning. 2000 would be a good one for --spinSleepTime
to avoid the loop but still trying to start the script quickly after the problematic situation resolves.
> forever start -a -l forever.log -o logs/out.log -e logs/err.log --minUptime=5000 --spinSleepTime=2000 /home/foouser/webapps/foonode/index.js
As the commands grow, memorizing and writing them becomes more and more cumbersome. Therefore it is convenient to copy them into a Makefile. The makefile also becomes handy later on when you need to specify a command to run after the server reboot.
> cd ~/webapps/foonode/
> cat Makefile
foreverstart:
# Run server forever (until reboot)
mkdir -p logs
forever start -a -l forever.log -o logs/out.log -e logs/err.log --minUptime 5000 --spinSleepTime 2000 /home/foouser/webapps/foonode/index.js
foreverstop:
forever stop /home/foouser/webapps/foonode/index.js
Forever does not cover the case where the server reboots. For that you need to specify a cronjob with @reboot
rule that start the forever after reboot.
> export EDITOR=nano # Editor to use to edit crontab. A matter of taste.
> crontab -e
Add the following line and save.
@reboot make -C ~/webapps/foonode/ -f ~/webapps/foonode/Makefile foreverstart
The line ensures that foonode is started immediately after the server reboot. The flag -C
specifies the directory to run the makefile from and -f
the actual location of the makefile. See this answer for details about using @reboot
.
Now you have a node process running truly forever or at least as long as there is maintenance guys feeding the server with electricity. Lots of things done but maybe more will come. Things you may like to do in the future which were not covered here includes the following.
--watch
in forever --help
)See also
Any ideas, comments or corrections?
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With