Automatic Deploy

using git hooks to deploy server with forever

Mon Feb 17, 2014

If you love deploying with automation and you love the fact you dont need to touch your server (which you should!). I've setup this up on an ec2 ubuntu 12.04 LTS, shouldnt differ too much with other ubuntu versions. At this time of writing i'm setting up a nodejs / flask server

On your remote server

#install forever and give it global access
sudo npm install -g forever

#setup git bare at your deployment server
git clone --bare [repo url]

#add the hooks
#navigate into your git folder
cd path/to/repo/hooks
vi pre-receive

echo "stopping server service"
service nodejs-www stop

vi post-receive

echo "checkout the files"

branch=$(git branch | grep "*" | sed "s/* //")

if [ "$branch" = "master" ]
        echo "Master branch"
        git --work-tree=/home/ubuntu/app/www checkout -f
        echo "Successfully checked out master branch"
        echo "Not master branch"

echo "start service"
service nodejs-www start

sudo chmod +x pre-receive;
sudo chmod +x post-receive;

FYI: Just make sure the folders are created for the "git --work-tree"

#navigate into init.d to create a service
cd /etc/init.d
sudo vi nodejs-www

#! /bin/sh
# /etc/init.d/nodejs-www

export PATH=$PATH:/usr/local/bin/

case "$1" in
    cd $APP_DIR
    echo "Starting $NAME"
    #I detached the message to 'screen', it is not a requirement
    screen -d -m /usr/bin/sudo -u ubuntu $forever --minUptime 5000 --spinSleepTime 2000 -a -l $LOG start $APP
    #if to run a python server use
    #screen -d -m /usr/bin/sudo -u ubuntu $forever --minUptime 5000 --spinSleepTime 2000 -a -l $LOG start -c python $APP
    echo "Started $Name"
    exit 0
    echo "Stopping script $NAME"
    cd $APP_DIR
    /usr/bin/sudo -u ubuntu $forever stop $APP
    exit 0
    echo "List"
    /usr/bin/sudo -u ubuntu $forever list
    exit 0
    echo "Usage: /etc/init.d/nodejs-www {start|stop|list}"
    exit 1

exit 0

FYI: Many others were able to run forever directly without having "/usr/bin/sudo -u ubuntu" (ubuntu is the user account) or substituting it with "sudo". For my case on an amazon aws, without it, i ran into permission issues with forever and nodejs directory mapping issues.

A permission error similar to this:

(function (exports, require, module, __filename, __dirname) { // Copyright Joy
Error: EACCES, permission denied '/root/.forever/pids/'
    at Object.fs.openSync (fs.js:410:18)
    at Object.fs.writeFileSync (fs.js:956:15)
    at writePid (/usr/local/lib/node_modules/forever/bin/monitor:13:6)
    at null. (/usr/local/lib/node_modules/forever/bin/monitor:46:5)
    at EventEmitter.emit (/usr/local/lib/node_modules/forever/node_modules/forever-monitor/node_modules/broadway/node_modules/eventemitter2/lib/eventemitter2.js:332:22)
    at /usr/local/lib/node_modules/forever/node_modules/forever-monitor/lib/forever-monitor/monitor.js:153:10

Now to wrap up the server side

sudo chmod a+x nodejs-www
cd /var/log
sudo touch nodejs-www.log
sudo chmod 777 nodejs-www.log

Add to rc.local to start upon server start

sudo vi /etc/rc.local

#!/bin/sh -e
service nodejs-www start
exit 0

For some you may need to change the rc.local permission to executable.

If i didnt miss anything this should it for the server

Now on client side

cd path/to/repo
git remote add deploy [remote server repo url]
git commit -am 'test deploy'
git push deploy master

This should be it, and the service should automatically stop and restart itself. If i missed anything let me know :)