Wern Ancheta

Adventures in Web Development.

Automating Deployment to EC2 Instance With Git

| Comments

In this tutorial I’m going to show you how to automate the deployment of changes to your ec2 instance using git. Deployment is done by setting up a bare git repo somewhere in the home directory of the ec2 instance. A post-receive hook is then setup to automatically update the web root based on the changes. The post-receive hook is executed whenever a push is made to the bare git repo in the ec2 instance.

Setup SSH

First thing you need to do is to setup ssh access on your development machine (local computer). You can do that by navigating to the ssh directory:

1
cd ~/.ssh

Then open up the config file:

1
sudo nano config

Next add the Host (alias of the ec2 instance), Hostname, User and IdentityFile:

1
2
3
4
Host websitebroker
Hostname ec2-54-191-181-129.us-west-2.compute.amazonaws.com
User ubuntu
IdentityFile ~/.ssh/amazon-aws.pem

Here’s a breakdown:

  • Host – a unique name you want to give to the server. This is used for referring to the server later on.
  • Hostname – the ip address of domain name of the server.
  • User – the user used for logging in to the server. For ec2 Ubuntu instance, this is usually Ubuntu.
  • IdentityFile – the path to the amazon identity file you have downloaded when you created the ec2 instance.

You can test if the ssh configuration works by logging in to the server using the Host you’ve added.

1
ssh websitebroker

Executing the command above should log you in to the server if youre configuration is correct.

Setup Git

Once that’s done, you can login to the server using ssh and setup git like you would usually set it up on your local computer.

First you install git:

1
2
3
sudo add-apt-repository ppa:pdoes/ppa
sudo apt-get update
sudo apt-get install git-core

Once that’s done, give identity to the server:

1
2
git config --global user.name "websitebroker"
git config --global user.email websitebroker@islickmedia.com

Next, generate an ssh keypair:

1
2
ssh-keygen -t rsa -C "websitebroker@islickmedia.com"
ssh-add id_rsa

If you’re getting the following error when adding the private keyfile:

1
Could not open a connection to your authentication agent

You can try starting ssh-agent before executing ssh-add:

1
eval `ssh-agent -s`

If that doesn’t work, you can try the following solutions.

Once that’s done, you can now add the public key to bitbucket, github or any other git service you’re currently using. To do that, navigate to your ssh directory then output the contents of the id_rsa.pub file. Copy the output and paste it into the git service you’re using:

1
2
cd ~/.ssh
cat id_rsa.pub

Setup Deployment

Navigate to the home directory of the server:

1
cd /home/ubuntu

Create and navigate to the directory where were going to push our changes later on:

1
2
mkdir website.git
cd website.git

Next, setup a bare git repo:

1
git init --bare

Next create a post-receive file under the hooks directory:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#!/bin/sh
#
# An example hook script for the "post-receive" event.
#
# The "post-receive" script is run after receive-pack has accepted a pack
# and the repository has been updated.  It is passed arguments in through
# stdin in the form
#  <oldrev> <newrev> <refname>
# For example:
#  aa453216d1b3e49e7f6f98441fa56946ddcd6a20 68f7abf4e6f922807889f52bc043ecd31b7$
#
# see contrib/hooks/ for an sample, or uncomment the next line and
# rename the file to "post-receive".

#. /usr/share/doc/git-core/contrib/hooks/post-receive-email
GIT_WORK_TREE=/home/ubuntu/www
export GIT_WORK_TREE
git checkout -f

The only thing you need to change here is the GIT_WORK_TREE, which is basically the path to where changes are being pushed when someone pushes into the bare git repo. Since we want changes to take effect on the public facing website, we setup the GIT_WORK_TREE to be the www directory. Which is the directory used by Apache to serve the website.

Next, open up the config file of the bare git repo:

1
2
cd /home/ubuntu/website.git
sudo nano config

Make sure it contains something similar to the following:

1
2
3
4
5
6
7
[core]
        repositoryformatversion = 0
        filemode = true
        bare = false
        worktree = /home/ubuntu/www
[receive]
        denycurrentbranch = ignore

Next, you need to make the post-receive file executable:

1
chmod +x hooks/post-receive

Now in your development machine. Navigate to your project directory then add a new remote and call it deploy. The path would be the ssh alias you’ve given to the website earlier. In this case its websitebroker. Followed by a colon then the path to the bare git repo:

1
git remote add deploy websitebroker:/home/ubuntu/website.git

Next push the references using git push. You only have to do this for the first time.

1
git push deploy +master:refs/heads/master

Now everytime you push to your bitbucket or github remote repo. You can also push the changes to the server:

1
git push deploy master

If you want to do it in one command, you can edit the config file of your project (still on your development machine) and add the urls in there:

1
2
3
[remote "all"]
        url = https://github.com/YourGitAccount/ProjectDir.git
        url = websitebroker:/home/ubuntu/website.git

Now all you have to do is push using the all alias:

1
git push all master

Note that this deployment strategy doesn’t update the dependencies. So you still need to login to the server and update your dependencies manually.

Conclusion

Automating deployment with Git is a nice way on saving up time manually pushing the changes to the server using ftp. With the deployment strategy we’ve seen in this tutorial, you can easily push changes to your server by executing a single command in the terminal. It also gives you the advantage of being able to rollback the changes you’ve made.

Resources

Comments