read

Sometimes you don't need the complexity of deployment automation tools like
capistrano, mina, or fabric.

At the end of the following steps you'll be able to deploy new code into your
production server atomically.

Setup the remote server

First, you'll need to set-up your remote production server.

local$> ssh user@production-server
remote$> sudo adduser git
remote$> su git
remote$> mkdir ~/my-project.git
remote$> cd ~/my-project.git

Create a bare git repository, and customize the deployment script. Use the
editor you are familiar with, such as nano, vim, etc.

remote$> git init --bare
remote$> vim hooks/post-receive

The following configuration is pretty straight-forward. You may customize it as
you need. It will create a my-project/releases/v directory, incrementing the
release at every push received. The current version (my-project/current) is
always a symlink to the last release.

#!/bin/bash
#~/my-project.git/hooks/post-receive
SCRIPT_PATH=$(pwd)
GIT_REPO=~/project.git
RELEASE_PATH=~/project

[[ -f $RELEASE_PATH/release ]] && CURRENT_RELEASE=$(cat $RELEASE_PATH/release) || CURRENT_RELEASE=1
NEXT_RELEASE=$(expr $CURRENT_RELEASE + 1)

NEXT_RELEASE_PATH=$RELEASE_PATH/releases/$NEXT_RELEASE
CURRENT_SYMLINK=$RELEASE_PATH/current

git clone $GIT_REPO $NEXT_RELEASE_PATH

# You may customize the post-receive hook in a custom deploy on your
# repository at `deploy/post-receive`
if [ -f $NEXT_RELEASE_PATH/deploy/post-receive ]; then
  cd $NEXT_RELEASE_PATH
  source $NEXT_RELEASE_PATH/deploy/post-receive
  cd $SCRIPT_PATH
fi

# Force update of symlink
ln -fsn $NEXT_RELEASE_PATH $CURRENT_SYMLINK
echo $NEXT_RELEASE > $RELEASE_PATH/release

Don't forget to allow the user to execute the post-receive script:

remote$> chmod +x hooks/post-receive

(optional) Deny normal ssh access to git user

It's recommended that you restrict the git user from having normal
ssh access. To do that you'll need to edit the /etc/passwd file.

remote$> sudo vim /etc/passwd

Search for the git entry, which will be the last. The git line should look
something like this:

git:x:1000:1000::/home/git:/usr/bin/git-shell

You're done with the remote server.

remote$> exit

Play with it!

Now, just add the remote and push your changes.

local$> git remote add production git@production-server:~/my-project.git
local$> git push production master
Blog Logo

Endel Dreyer

Full-stack developer. Loves Ruby and JavaScript.


Published

Image

bugfixer / @endel

About programming, tools and solving problems.

Back to Overview