Zac Fukuda
010

Run HHVM and Node.js App on Ubuntu 14.04

As beginner, we wonder whether it is possible to run a HHVM and a Node.js apllications on the same server. The answer is of course YES, and I'm going to show you how to do it. Follwing the guide below, you install these versions of softwares as of Jan 2, 2016.

  • Nginx v1.9.9
  • HHVM v3.11.0
  • Node v4.2.4 Argon

Please note that we don't install the stable version of Nginx, that is probably v1.4.x or v1.6.x, and I add "sudo" in everytime when it requires super user's permission. Also you need wget and curl pre-installed.

Install Nginx Latest

Resources for this section

First, add the key so that apt-get installs latest Nginx.

wget -O - http://nginx.org/keys/nginx_signing.key | sudo apt-key add -

Next, make a backup copy of your current sources and add the lines to install from the mainline of Nginx.

sudo cp /etc/apt/sources.list /etc/apt/sources.list.bak
echo "deb http://nginx.org/packages/mainline/ubuntu/ trusty nginx" | sudo tee -a /etc/apt/sources.list
echo "deb-src http://nginx.org/packages/mainline/ubuntu/ trusty nginx" | sudo tee -a /etc/apt/sources.list

Then install Nginx by excuting the command below.

sudo apt-get update && sudo apt-get install nginx

If you prefer Nginx to start automatically at boot, please excute:

sudo update-rc.d nginx defaults

Create Web Roots

We will use default webroot, i.e. /usr/share/nginx/html, for HHVM and /usr/share/nginx/node for the Node.js application. So now let's create a directory for Node.js app.

sudo mkdir /usr/share/nginx/node

Just in case that we won't be able to read files due to permission issue, please do the following commands replacing the username to yours.

sudo chown -R username:www-data /usr/share/nginx/html
find /usr/share/nginx/html -type d -exec sudo chmod 2775 {} +
find /usr/share/nginx/html -type f -exec sudo chmod 0664 {} +
sudo chown -R username:www-data /usr/share/nginx/node
find /usr/share/nginx/node -type d -exec sudo chmod 2775 {} +
find /usr/share/nginx/node -type f -exec sudo chmod 0664 {} +

Install HHVM

Resources for this section

You need to install add-apt-repository prior to installing HHVM.

sudo apt-get install software-properties-common

Now let's install HHVM that you are waiting for by excuting:

sudo apt-key adv --recv-keys --keyserver hkp://keyserver.ubuntu.com:80 0x5a16e7281be7a449
sudo add-apt-repository "deb http://dl.hhvm.com/ubuntu $(lsb_release -sc) main"
sudo apt-get update
sudo apt-get install hhvm

HHVM has a shell script to set up nginx to run HHVM.

sudo /usr/share/hhvm/install_fastcgi.sh

Probably the shell script above fails since Nginx v1.9.9 changes the location of directory in which conf files are stored, so you need to rewrite nginx conf file manually.

sudo vi /etc/nginx/conf.d/default.conf

# Add this line after server_name
include hhvm.conf;

Create index.php at the webroot.

echo '<?php phpinfo(); ?>' >> /usr/share/nginx/html/index.php

Register HHVM to start at boot.

sudo update-rc.d hhvm defaults

Install Node.js

Resources for this section

Recently Node.js has two version options, v4.x or v5.x. This time we install v4.x, which promises of the long time support.

curl -sL https://deb.nodesource.com/setup_4.x | sudo -E bash -
sudo apt-get install -y nodejs
sudo apt-get install -y build-essential

You might need to tell npm that which python must be used.

npm config set python python2.7

Then create a index.js at the webroot for Node.js.

vi /usr/share/nginx/node/index.js

Inside of index.js looks like this:

var http = require('http');
http.createServer(function (req, res) {
  res.writeHead(200, {'Content-Type': 'text/plain'});
  res.end('Hello World\n');
}).listen(3000, '127.0.0.1');
console.log('Server running at http://127.0.0.1:3000/');

In order to daemonize the Node application, install PM2, which is a process manager for Node.js applications.

sudo npm install pm2 -g

Start a Node app by:

pm2 start /usr/share/nginx/node/index.js

Now let's create Nginx conf file for Node.js application.

vi /etc/nginx/conf.d/node.conf

# Inside of node.conf
server {
    listen 80;

    server_name node.example.com;

    location / {
        # General
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header Host $http_host;
        proxy_set_header X-NginX-Proxy true;
        
        # For websocket
                proxy_http_version 1.1;
                proxy_set_header Upgrade $http_upgrade;
                proxy_set_header Connection 'upgrade';
                proxy_cache_bypass $http_upgrade;

        proxy_pass http://127.0.0.1:3000;
        proxy_redirect off;
    }
}

The file above configures that if you visit your server with node.example.com, it redirect to port 3000 where node application are running. Note that port 3000 matches what you define in index.js.

Finish

It is time to restart HHVM and Nginx.

sudo /etc/init.d/hhvm restart
sudo /etc/init.d/nginx restart

If you visit the example.com or YOUR_IP_ADDRESS, you see the HHVM version of phpinfo(), and if you visit node.example.com, you see "Hello World". (Don't forget that your server is accessible at port 80.)

Congratulation!! Now you are running the HHVM and Node.js applications on the same server.