Heroku Style Deployments With git-deploy

January 24, 2015

Ever since I started using git-deploy I spend more time on chilling - William Henry Harrison

I have been working more and more on *nix systems lately and a lot less with Windows. Thus, I have deployed a fair amount of apps to Heroku as of late. One thing I enjoy about deploying to Heroku is how using git you can push your code to the server. To give you an example, after installing the Heroku Toolbelt, quite simply all you need to do to deploy is from within your repo:

$ heroku create
$ git push heroku master

Heroku will go ahead and build your application while you sit back and relax. I think this is awesome, but, was wondering how I can do this on a local server? Now before I introduce you to git-deploy let me tell you that you can do the same using git hooks but I think git-deploy is a nice abstraction.

Lets GO!

I am going to be using Ubuntu 12.04.4 LTS server that I have running on VirtualBox. This is a clean install and I am going to only show how we get this server ready to be deployed to.

Firstly you will need to install git on the remote server, since git-deploy uses Ruby to execute deploy ments scripts you will need to install Ruby too. I am on an Ubuntu box so I will use the following command:

root@super-server:/home# apt-get install git

It is good practice to have your application run by a service account; we will, therefore, create a new user on our server to run our example application. Now one thing that isn’t so great is the fact that we need to add our new user to the sudo group but this is key for this to work. Log into the server as root or sudo the below commands:

root@super-server:/home# adduser donkey

For this to work OpenSSH or equivalent should be installed on your server. The remote server is going to need a copy of the ssh keys for each user who will be push changes to it via git. Copy your ssh key into the authorized_keys file in the .ssh directory of the service user.

On your local machine copy your ssh key using:

$ pbcopy < ~/.ssh/id_rsa.pub

Back on the remote server use vi to edit the authorized_keys file:

root@super-server:/home# cd donkey
root@super-server:/home/donkey# mkdir .ssh && chmod 700 .ssh
root@super-server:/home/donkey# touch .ssh/authorized_keys && chmod 600 .ssh/authorized_keys
root@super-server:/home/donkey# vi .ssh/authorized_keys

This will open up vi paste your ssh key and make sure to save your changes. To make sure everything is in order we restart the ssh server:

root@super-server:/home/donkey/.ssh# stop ssh ; start ssh

Now jump back to your local machine. For this to all work you are going to need Ruby and RubyGems installed on your local machine. Keep in mind this is only applicable to the user who is going to set up the git deploy, everyone else is just going to add a remote to the server where the deployed application will reside.

With Ruby and RubyGems installed you can install git-deploy:

$ gem install git-deploy

Now navigate to your repository and we will setup using git-deploy. For my application, I have the following structure:

kong/
└── app
    └── index.html

##Show me the money

My application is already under source control, so I don’t need to run git init on it; rather I can just add a remote that points to the production server.

$ git remote add production 'donkey@192.168.1.119:/home/donkey/kong'

I can now run the following commands that will setup the necessary hooks on the remote server

$ git deploy setup -r production
[production] $ mkdir -p /home/donkey/kong
[production] $ cd /home/donkey/kong && \
  git init  && \
  git config receive.denyCurrentBranch ignore
Initialized empty Git repository in /home/donkey/kong/.git/
FILE: [local] hooks/post-receive.sh  ->  [production] /home/donkey/kong/.git/hooks/post-receive
[production] $ chmod +x /home/donkey/kong/.git/hooks/post-receive

At this stage, we need to create the folder that will contain the script files that will run after we have pushed our changes. So still on our local machine run the following:

$ git deploy init
      create  deploy/after_push
       chmod  deploy/after_push
      create  deploy/restart
       chmod  deploy/restart
      create  deploy/before_restart
       chmod  deploy/before_restart

It’s pretty clear what the purpose of these scripts are but here is a short description.

###after_push

This file is will be run after you’ve pushed your code to the remote server. It gathers some information about your changes, sets up the environment and kicks off the before_restart and restart scripts.

###before_restart

Use this script to run migrations or make any changes necessary before the application starts up.

###restart

This is where you will add the commands to start your application.

##Here We Go

You will edit or add additional scripts that will be called from these scripts to ensure all setup is correct for your application. At this point our folder structure will look as follows:

kong/
├── app
│   └── index.html
└── deploy
    ├── after_push
    ├── before_restart
    └── restart

The next step is to commit our changes to source control:

$ git add --all
$ git commit -m "Repo setup to be used with git-deploy"

Now comes the awesomeness, it’s time to push our changes to the server.

$ git push -u production master
Counting objects: 8, done.
Delta compression using up to 8 threads.
Compressing objects: 100% (5/5), done.
Writing objects: 100% (8/8), 1.33 KiB | 0 bytes/s, done.
Total 8 (delta 0), reused 0 (delta 0)
remote: HEAD is now at 03970d6 Repo setup to be used with git-deploy
To donkey@192.168.1.119:/home/donkey/kong
 * [new branch]      master -> master
Branch master set up to track remote branch master from production.

I have a web server running on the remote server that will display the index.html page:

hello world

To prove that everything is in working order I will change the text of that page from:

<h1>Hello, World</h1>

To this:

<h1>Hello, git-deploy</h1>

Then I make sure to commit my code to source control and push to the server:

$ git add --all
$ git commit -m "Updated h1 text"
[master 224ca0a] Updated h1 text
 1 file changed, 1 insertion(+), 1 deletion(-)
$ git push -u production master

And viola: hello git-deploy


Discussion, links, and tweets

My name is Deon Heyns and I am a developer learning things and documenting them in realtime. Python, Ruby, Scala, .NET, and Groovy are all languages I have written code in. I appeared in the New York Post once. I host my code up at GitHub and Bitbucket so have a look at my code, fork it and send those pull requests.

comments powered by Disqus