An example of a simple NodeJS application running via systemd that is accessed via an nginx proxy.
NodeJS app will be running as the tomcat7
system user, and there are a few assumptions that must be met to allow the installation of NodeJS:
- The
tomcat7
user must be able to write to its home folder —/usr/share/tomcat7
— so it can create the~/.nvm
,~/.npm
and other directories during installation - The
~tomcat7/.profile
file must exist and be writable before installingnvm
, as this is the default config file for login shells, iesudo su - tomcat7
. Thenvm
installer will append lines to those files to setup their environments on login.
The easiest way to get NodeJS without relying on the system's package manager is to use Node Version Manager (NVM). Also, this lets you install whatever version of NodeJS you want, and doesn't require root because it installs in the user's shell.
I'll use NodeJS v4 because it's the current long-term support version:
$ wget -qO- https://raw.githubusercontent.com/creationix/nvm/v0.31.4/install.sh | bash
After the intstallation is finished, close and re-open your shell to activate NVM. Then install NodeJS v4 (LTS) and use npm
to install the DSpace dependencies:
$ nvm install v4
$ nvm alias default v4
Initiate a sample project and [install ExpressJS](https://expressjs.com/en/starter/installing.html:
$ nvm use v4
$ mkdir hello && cd hello
$ npm init
$ npm install express --save
$ npm install express
Create the entry point for the NodeJS app, index.js:
var express = require('express');
var app = express();
// only allow localhost
app.set('trust proxy', 'loopback') // specify a single subnet
app.get('/api', function (req, res) {
res.send('Hello World!');
});
app.listen(3000, function () {
console.log('Example app listening on port 3000!');
});
Try running the app:
$ node index.js
Add a location block to default virtual host in nginx:
location /api {
proxy_pass http://127.0.0.1:3000;
}
I use /api
because I had used the same path in the NodeJS index.js above.
Create a systemd service file for the application, /etc/systemd/system/nodejs-hello.service:
[Unit]
Description=CGSpace DSpace API
After=network.target
[Service]
User=tomcat7
WorkingDirectory=/usr/share/tomcat7/src/git/hello
ExecStart=/usr/share/tomcat7/.nvm/versions/node/v4.4.7/bin/node index.js
Restart=always
RestartSec=10s
StartLimitInterval=0
[Install]
WantedBy=multi-user.target
Now load, enable, and start the app using systemctl
:
$ sudo systemctl enable nodejs-hello
$ sudo systemctl start nodejs-hello
$ systemctl status nodejs-hello
● nodejs-hello.service - CGSpace DSpace API
Loaded: loaded (/etc/systemd/system/nodejs-hello.service; enabled; vendor preset: enabled)
Active: active (running) since Mon 2016-08-15 09:37:08 EEST; 8s ago
Main PID: 5092 (node)
Tasks: 5
Memory: 18.7M
CPU: 217ms
CGroup: /system.slice/nodejs-hello.service
└─5092 /usr/share/tomcat7/.nvm/versions/node/v4.4.7/bin/node index.js
Aug 15 09:37:08 dspace systemd[1]: Started CGSpace DSpace API.
Aug 15 09:37:08 dspace node[5092]: Example app listening on port 3000!
Now you can access the application via whatever hostname you're using in the nginx vhost. If you kill the node
process systemd will restart the app!
$ http --print Hhb https://localhost:9443/api --verify no
GET /api HTTP/1.1
Accept: */*
Accept-Encoding: gzip, deflate
Connection: keep-alive
Host: localhost:9443
User-Agent: HTTPie/0.9.6
HTTP/1.1 200 OK
Connection: keep-alive
Content-Length: 12
Content-Type: text/html; charset=utf-8
Date: Mon, 15 Aug 2016 08:13:22 GMT
ETag: W/"c-7Qdih1MuhjZehB6Sv8UNjA"
Server: nginx
X-Content-Type-Options: nosniff
X-Frame-Options: SAMEORIGIN
X-Robots-Tag: none
X-XSS-Protection: 1; mode=block
Hello World!
And Bob's your uncle!
I can see how awesome this will be on ansible ;)
something like...