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
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):
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:
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:
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:
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.
- 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.