A Simple Git Deployment setup on Ubuntu Server

After spending a lot of time on trial & error to set up a simple Git web application deployment setup using Ubuntu server, I’m writing this down as a reference for myself and thought it might helpful to others as well. If anyone actually reads this and can comment on:

  • Things I missed
  • Things I did that were stupid
  • Things that were especially stupid

…it will be appreciated.

This is based on Ubuntu 12.04 server and deploying from OS X, though that part shouldn’t matter.

This “how-to” assumes that LAMP (though only Apache is discussed here) is set up on the server and git is already installed on the local environment.

Install Git on the server

sudo apt-get install git

OK, that was pretty easy.

Configure Apache folders

I’m not covering Apache configuration because I’m pretty much copy & paste when it comes to that. Instead, I’m talking about the folder/permissions structure to make it easy to work with git. By default, the Apache web root is /var/www and is owned by root. The first thing I’m going to do is create a new “www” group and put the user that actually runs Apache (“www-data”) and myself in that group.

sudo addgroup www 
sudo adduser [username] www 
sudo adduser www-data www

Give group ownership of /var/www to the new “www” group:

sudo chown -R :www /var/www

Do a chmod on /var/www so that new files created inside will retain the current group (www):

chmod +s -R /var/www

I’m putting all virtualhosts in a vhosts folder, so I’ll create the following folders:

mkdir /var/www/vhosts
mkdir /var/www/vhosts/appname

Git Folders

Basically the same steps for Apache, except I’ll first create a new folder under var:

sudo mkdir /var/git

Give /var/git the same permissions setup as /var/www:

sudo chown -R :www /var/git
sudo chmod +s -R /var/git

As you can see, I’m just using the same “www” group to keep things simple.

Create a folder for the new web app’s git repository (which I’ll only be using as kind of a passthrough to update the web application):

mkdir /var/git/appname.git

Create the repository:

cd /var/git/appname.git
git init --bare

Creating the post-receive git hook

Since the idea here is to quickly and easily deploy your latest code to your web app, we need to create a git hook that will “checkout” the code over to the web folder after it’s pushed to the server.
For that, we need to create a post-receive file in /var/git/appname/hooks
I use pico/nano, so:

nano /var/git/appname/hooks/post-receive

Add the following to post-receive:

#!/bin/sh
GIT_WORK_TREE=/var/www/vhosts/appname git checkout -f

Update (1/22/2013) – Laravel Migrations:

If you are using Laravel and want to run migrations, adding this after the checkout command appears to work (though I haven’t tested it heavily yet):

cd /var/www/vhosts/appname
php artisan migrate --env=test

“test” should be whatever laravel-labeled environment you are deploying to.

Save it(crtl+x, then y) in nano/pico.
Make it executable:

chmod +x /var/git/appname.git/hooks/post-receive

Update (1/30/2013) – Adding git commit info. to web site footer:

Work-in-progress…

My goal is to display in a web app’s footer the current application version based on git tags, as well as the latest git commit hash. I haven’t figured out the first part, but here’s my solution for the second:

In the post-receive file, add something like:

/usr/bin/git log -1 --pretty=format:'%h' --abbrev-commit > /var/www/vhosts/appname/version.txt

This should output the latest abbreviated commit hash to version.txt. You can then display it in your web app using something like:

<?php include('version.txt');?>

Update (1/31/2013) – Updated post-receive script

Repeating the webroot location several times is not very efficient, so here’s an updated post-receive script using a WEBROOT variable to streamline things:

#!/bin/sh
WEBROOT=/var/www/vhosts/appname
GIT_WORK_TREE=$WEBROOT git checkout -f
/usr/bin/git log -1 --pretty=format:'%h' --abbrev-commit > $WEBROOT/version.txt
cd $WEBROOT
rm -f storage/cache/*
echo 'cache clearedn'
rm -f storage/views/*
echo 'views clearedn'
php artisan migrate --env=test

Meanwhile, in our local dev environment…

In the Terminal, navigate to the folder where your web application sits.

If you don’t already have a git repository set up:

git init
git add .
git commit -m 'Initial Commit' (or whatever you want to say)

Set up the remote link to the repository we just set up on the Ubuntu server:

git remote add [remote name: test, prod, whatever] ssh://[username]@server:/var/git/appname.git
(all one line)

Do initial push:

git push [remote name] master

Subsequent pushes just need: git push [remote name]

Go back to the server and check to see that your app’s files are now present at /var/www/vhosts/appname.

Done.

Other Stuff

  • I’m under the impression that with the setup I currently have, the file permissions (execute, etc.) I’ve set up on my local files are carried over to the remote server. Therefore, it’s probably a good idea to set those up locally like you want them on the remote server even if it already works fine locally because maybe you are running MAMP or something with your user account.  If you application does any kind of file manipulation, you’ll find out quickly that running apache under a different user can break stuff.
  • After deleting and re-creating my local git repository several times, I’ve noticed that without an easy explanation, a few folders in my Laravel app that are marked for git tracking, began to not get picked up by “git add .”. I looked everywhere for a .gitignore file that might be causing this to no avail. I finally just had to use “git add -f [folder name] to include these and it appears to be fine now, but I find that issue to be a little troubling if you are relying on this setup for deploying to a production server.