1. Home

Anil Lakhman

< Blog />

Setup Node.js on EC2 with forever

in

A guide on setting up node.js on an EC2 server with forever to run a HTTP server.

We also setup forever to run our script when the instance boots.

Tip

You probably want to checkout https://github.com/Unitech/pm2.

Install Node.js

If you haven’t already, install node and npm.

# Install Node.js - v6.x + npm
curl --silent --location https://rpm.nodesource.com/setup_6.x | sudo bash
sudo yum -y install nodejs

Next, let’s create a simple server.js file to test with.

server.js
var http = require('http');
var port = 9500;
var server = http.createServer(function(request, response) {
    response.setHeader('Content-Type', 'text/html');
    response.end('<h1>Node.js server is running!</h1>');
});
server.listen(port, function() {
    console.log('Node.js server listening on port: ' + port);
});

Using nohup

You can use nohup with job control to place this command in the background.

nohup is a POSIX command to ignore the HUP (hangup) signal. The HUP signal is, by convention, the way a terminal warns dependent processes of logout.

Output that would normally go to the terminal goes to a file called nohup.out if it has not already been redirected.

https://en.wikipedia.org/wiki/Nohup

# no-hangup and place it in the background
nohup node server.js &
[1] 965

# view background jobs (job control)
bg
bash: bg: job 1 already in background

# bring bg back to fg
fg
nohup node server.js
# Press CTRL+Z to bg this command

This works, but when the application crashes it will not be restarted.

For that we’ll use forever.


Using Forever

Forever allows us to run a script forever, if the script exits because of an error, it will be restarted automatically.

Run npm install forever -g on your server to install forever globally.

# Install forever
npm install forever -g

# Start it with file server.js
forever start server.js

# List processes currently managed
forever list

# Stop by filename
forever stop server.js

# Stop by id from `forever list`
forever stop 118

# Stop all processes
forever stopall

# List log files
forever logs

# Append logs into out/log/err files, watch directory for change and start server.js
APP_DIR=$(pwd)
rm $APP_DIR/*.log
forever --no-colors --append -o $APP_DIR/my_app_out.log -l $APP_DIR/my_app_log.log -e $APP_DIR/my_app_err.log \
--watch --watchDirectory $APP_DIR --watchIgnore *.log --watchIgnore node_modules \
start server.js
#> warn:    --minUptime not set. Defaulting to: 1000ms
#> warn:    --spinSleepTime not set. Your script will exit if it does not stay up for at least 1000ms
#> info:    Forever processing file: server.js

Here’s a breakdown of all the options i’ve used above, view the forever docs for the complete list.

-l LOGFILE
Logs the forever output to LOGFILE
-l LOGFILE
Logs the forever output to LOGFILE
-o OUTFILE
Logs stdout from child script to OUTFILE
-e ERRFILE
Logs stderr from child script to ERRFILE
-w, –watch
Watch for file changes
–watchDirectory
Top-level directory to watch from
–watchIgnore
To ignore pattern when watch is enabled (multiple option is allowed)

Note

I get the following error when the log files already exist.

To fix it, delete the log files (rm $APP_DIR/*.log) and run it again.

error: Could not read .foreverignore file.
error: ENOENT: no such file or directory, open '/path/to/workingdir/.foreverignore'
/path/to/workingdir/my_app_log.log:1
(function (exports, require, module, __filename, __dirname) { error: Could not read .foreverignore file.
                                                                           ^^^
SyntaxError: Unexpected identifier
    at Object.exports.runInThisContext (vm.js:76:16)
    at Module._compile (module.js:513:28)
    at Object.Module._extensions..js (module.js:550:10)
    at Module.load (module.js:458:32)
    at tryModuleLoad (module.js:417:12)
    at Function.Module._load (module.js:409:3)
    at Module.runMain (module.js:575:10)
    at run (bootstrap_node.js:352:7)
    at startup (bootstrap_node.js:144:9)
    at bootstrap_node.js:467:3
error: Forever detected script exited with code: 1

Starting forever on instance boot

Now we have the tools to start and stop our application, we’ll want to run this automatically when your EC2 instance starts.

Assuming your application is located at /var/www/html/example-node-app.

Open vi /etc/rc.local and add your forever command.

# Must be sudo
sudo vi /etc/rc.local

# Append logs into out/log/err files and start server.js
APP_DIR=/var/www/html/example-node-app
# rm $APP_DIR/*.log
forever --no-colors --append -o $APP_DIR/my_app_out.log -l $APP_DIR/my_app_log.log -e $APP_DIR/my_app_err.log \
start server.js

Important

Don’t watch files in production!


Using iptables to redirect your node app

You can redirect a port (e.g: 80) to another port your application is running on (e.g: 9500) by adding the following iptable rule.

# Forward all traffic from port 80 to 9500
sudo iptables -A PREROUTING -t nat -i eth0 -p tcp --dport 80 -j REDIRECT --to-port 9500