Deploy a Node.js App Using Mina

Express.js For Rubyists

Express.js has its similarities to Sinatra, a DSL for creating web applications using Ruby. In fact they did mention that it was Sinatra-inspired. I have tried it out of curiousity and need for a small project.

This guide assumes you already have Nginx setup correctly. I would skip that part unless someone asks for help about it. You could be using Apache or something else for production. It’s sensible to skip the server configuration part. Refer to this guide if you need to learn about that.

Installing Node.js and Express.js

For Mac users who use homebrew, it’s very easy to install.

    brew install node
    curl http://npmjs.org/install.sh | sh
    npm install -g express

The -g flag is important as it means you want to install express.js globally and make it available for all users.

In production, you would most like be using Ubuntu or Debian. Install using apt-get.

    sudo apt-get install nodejs
    curl http://npmjs.org/install.sh | sh
    npm install -g express

Hello World App

    express myapp
    cd myapp && npm install -d

So far there’s just a minor annoyance about using port 3000. We know very well that Rails uses port 3000. Changing that would help.

    app.listen(4000);

Mina as an alternative to Capistrano

For years, many Rubyists like myself have used Capistrano. I still use it but recently found out about Mina. It’s very fast. Really impressive!

The project was created by Rico Sta. Cruz and Michael Galero with the help of some other contributors.

I think I have no need to use capistrano much now. Strange how I first tried it with a Node.js app rather than a Ruby app. When I figure out multi-staging or deploying one app on multiple servers using Mina, I will try it for other apps.

Install mina. It’s a Ruby gem so if you don’t have Ruby on Rubygems, kindly look into other guides and check out RVM if you haven’t installed it yet.

    gem install mina

If forever is nil

My comment so far on Node.js deployment is that it felt like the yesteryears for Ruby developers, those days without passenger and days when the sensible option was to use mongrel which some may still be using.

Without the node extension, forever, life is like this:

    ps aux | grep node
    ps aux | grep god
    sudo  kill `ps -e -o pid,command | grep god -m 1 | awk '{ print $1; }'`
    sudo  kill `ps -e -o pid,command | grep node -m 1 | awk '{ print $1; }'`

You can create a node-monitor script and use either god or monit or you can use forever and save a lot of time.

    npm install -g forever #install forever in production server and make sure it is available globally
    forever start app.js #starts the app
    forever stop app.js #stops the app
    forever restart app.js #restarts the app

Let’s Deploy!

To create the configuration files:

    cd myapp
    mina init

Replace config/deploy.rb contents with the following and edit:

    require 'mina/bundler'
    require 'mina/rails'
    require 'mina/git'

    # Basic settings:
    # domain     - The hostname to SSH to
    # deploy_to  - Path to deploy into
    # repository - Git repo to clone from (needed by mina/git)
    # user       - Username in the  server to SSH to (optional)

    set :domain, 'yourdomain.com'
    set :deploy_to, '/home/user/public_html/yourdomain.com'
    set :repository, 'user@githost:repositoryname'
    set :user, 'user'
    # set :port, '30000'

    desc "Deploys the current version to the server."
     task :deploy do
       deploy do
         invoke :'git:clone'
         to :launch do
           queue 'forever restart app.js'
         end

      end
    end

    task :start do
     queue %[cd #{deploy_to}/current && forever start app.js]
    end

    task :restart do
     queue %[cd #{deploy_to}/current && forever restart app.js]
    end

    task :stop do
      queue %[cd #{deploy_to}/current && forever stop app.js]
    end

Deploying for the first time:

    mina setup #creates the directories. This is similar to cap deploy:setup 
    mina deploy
    mina start 

Don’t worry if you get an error for the first time. After starting the app, you should get no errors.

    mina deploy 

Results should be something like this:

    -----> Creating a temporary build path
    -----> Cloning the Git repository
       Initialized empty Git repository in /home/user/public_html/yourdomain.com/tmp/build-134238034110557/.git/
    -----> Using revision bbeb93387e787c4491aa7a05599544a334f16e27
    -----> Build finished
    -----> Moving build to releases/2
    -----> Updating the current symlink
    -----> Launching
    -----> Done. Deployed v2