Moving a NodeJS App to Production on Debian Wheezy

Randy Bacon NodeJS, Debian, Ghost

WOW! Moving this application (my new website and blog) to my Debian VPS was a little harder than I wanted and anticipated. Of course this was my first time publishing a Node app to production so some learning time was to be expected...

Getting Ready for Production

Before moving from PHP to Node on my server I had read several articles and posts about different set ups. I decided to move to NGINX from Apache as my web server. I have used Apache since my first FreeBSD server - about 15 plus years ago - but it was time to move forward to something faster and with a fun name. Another post will follow about this move later...

Since I already had NGINX up and running I just needed to adjust my website config to the following (real ports are not below but would be the port of your apps):

server {
    server_name www.hirerandybacon.com;

    location / {
        proxy_pass http://localhost:<NODEJSPORT>;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection 'upgrade';
        proxy_set_header Host $host;
        proxy_cache_bypass $http_upgrade;
    }

    location /blog {
        proxy_pass http://localhost:<NODEJSPORT>;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection 'upgrade';
        proxy_set_header Host $host;
        proxy_cache_bypass $http_upgrade;
    }
}

Additionally, I went the lazy route and published all my web files as is from the raw project. I plan on building a Grunt script to help with this but for now it was all manual.

What didn't work

I tried several methods to get my node app up and running. First I installed forever figuring it would be the easiest way (and I have heard others talking about it). Running forever from the command line is as simple as (note: the NODE_ENV=production export is for my ghost blog):

NODE_ENV=production forever start app.js

The first issue I had found was a warning about sqlite3. Because of my recent work with node-webkit I figured I needed to do an actual npm install on the machine to compile SQLITE. I changed to the web directory of my project and ran:

npm install sqlite3

Of course this yeilded some random error messages about permissions and also one of interest. I was missing make. So installing make was needed:

sudo apt-get install build-essential

After running this, the base application started but now the ghost module was complaining about sqlite3 (the joys of developing on Windows and publishing to Debian). I changed to the ghost directory inside of my web/node_modules directory and ran the npm install sqlite3 command again.

Finally this worked without issue and I was excited. Time to set it up to run via the cron. Being the old school Unix guy I was (or maybe more accurately the lack of recent Unix experience) - I rushed to set up an init.d script.

I tried several init.d scripts from git and Google search results. It seemed each had an issue and did not work well with my flavor of Debian - Wheezy. Additionally, more errors were caused by creating the scripts on Windows and coping it to my Debian box. Turns out carriage returns were the cause.

What finally worked after a while...

After wasting some good football watching time with the init.d I decided to try something simpler from the Ghost docs - Supervisor. The installation and config was pretty easy.

sudo apt-get install supervisor

On step 2 - service supervisor start I received the following a useless error message:

Error: Another program is already listening on a port that one of our HTTP servers is configured to use.  Shut this program down first before starting supervisord.

Great! A quick google search though indicated I just needed to run this:

sudo unlink /var/run/supervisor.sock

After running the command and trying again, the service was running. I banged out a quick config for my node application and saved it to the config.d directory - /etc/supervisor/conf.d/ - (of course the real path below is a little different but you get the idea):

[program:hirerandybacon]
command = node /mysecrectpath/app.js
directory = /mysecrectpath
user = www-data
autostart = true
autorestart = true
stdout_logfile = /var/log/supervisor/hirerandybacon.log
stderr_logfile = /var/log/supervisor/hirerandybacon_err.log
environment = NODE_ENV="production"

Now I went to fire off the supervisor program via:

sudo supervisorctl start hirerandybacon

And instead of a running app I received the following error message:

hirerandybacon: ERROR (no such process) 

"GRRR," said Randy. This required more Google searching which brought me to this solution:

supervisorctl reread
supervisorctl reload

FINALLY starting the program yields success and my site is now running. Or is it?

More Issues

I guess because I'm bored I decided to log into my blog and finish up my first post. I tired to log in and received no response until a toast popped up saying a server error had occurred.

I checked the supervisor log and of course there where no relevant log items. At this point I was tired and wanted to brutte force my way though this thing. I decided to try to run the Node app again via the command line but this time as the www-data user (you know the user I assigned the app to above). A quick change of the user via:

sudo su www-data

Firing up the app via:

NODE_ENV=production node app.js

And finally a useful error message. The database was opening in read only mode. Why? Because when I deployed my database, although I thought I had chown'd the data directory and db to the :www-data group I hadn't changed permissions... After changing the permissions on the data directory (775) and database (664) and restarting my app, I was in business.

After a few hours (or maybe an evening) my node app and blog is running in production. I guess the plus side is I had another topic to blog about.