deploying with node.js
we make extensive use of apache 2's virtual hosts. we use it to front rails, sinatra/rack, and now node.js. with one linode, we can run different frameworks all responding to different named virtual hosts (e.g., pinkyurl.com runs on rails and lazeroids.com runs on node.js).
how do we do it with node.js? first, we put lazeroids/node under upstart with a configuration file in /etc/init:
root@pinkyurl:~# cat /etc/init/lazeroids.conf
description "lazeroids"
author "visnup"
start on startup
stop on shutdown
script
cd /u/apps/lazeroids-node/current && exec sudo -u www-data EXPRESS_ENV=production /usr/local/bin/node /u/apps/lazeroids-node/current/server.js 2>&1 >> /u/apps/lazeroids-node/current/log/node.log
end script
this gives us "status lazeroids", "start lazeroids", "stop lazeroids", and most importantly "restart lazeroids". so now we can start/stop/restart node running lazeroids on port 8000. now what about that named virtual host?
<VirtualHost *:80>
ServerName lazeroids.com
ProxyPass / http://127.0.0.1:8000/
CustomLog /var/log/apache2/lazeroids-node-access.log combined
ErrorLog /var/log/apache2/lazeroids-node-error.log
<Proxy *>
Allow from all
</Proxy>
</VirtualHost>
it's as easy as a proxying of port 8000 to node (very similar to how we all used to proxy mongrel_cluster with apache a couple years ago). now, one of the big reasons to be using node.js in the first place is because we can do hot-new websockets with it. we can't have those connections happening on port 80 since apache would get all confused by it. so instead, we setup socket.io to handle ws:// requests to port 8000 which is where node.js is running w/o apache in the front (from the client-side javascript):
@socket: new io.Socket null, {
rememberTransport: false
resource: 'comet'
port: 8000
}
(that's coffee-script, btw if you're confused about the syntax being used). lastly, a Capfile for our deploys:
load 'deploy' if respond_to?(:namespace) # cap2 differentiator
Dir['vendor/plugins/*/recipes/*.rb'].each { |plugin| load(plugin) }
default_run_options[:pty] = true
set :application, "lazeroids-node"
set :scm, :git
set :user, "app"
namespace :deploy do
task :restart, :roles => :app, :except => { :no_release => true } do
run "#{try_sudo} restart lazeroids"
end
end
as you can see, all we need to do on deploy is to restart node.js with upstart. this also implies that we've setup sudo to let the app user go ahead and do that one thing without prompting for a password in /etc/sudoers:
app ALL=NOPASSWD: /sbin/restart lazeroids
again, all of this code can be found on github. hope some of this helps with your future node.js deploys.