Automatically Deploying Website From Remote Git Repository

2009-05-30 02:30:40

Before I start, I'll just quickly run through where I put stuff on my server. Apache logs and config are in the ubuntu default folders: /var/log/apache2 and /etc/apache2/ respectively.

Websites:  /home/caius/vhosts/<domain name>/htdocs
Git Repos: /home/caius/git/<domain name>.git

So I have a git repo locally, ~/projects/somesite.com/, and want to deploy it to my webserver. I'll keep the git repo in ~/git/ and set it up so that when I push to the repo (over ssh) it will automatically checkout the new changes into the website's htdocs folder.

I'm assuming DNS is already setup (or I've used ghost to map it locally.) And that I've setup the virtualhost in apache pointing at /home/caius/vhosts/somesite.com/htdocs and reloaded apache so the config is in place.

Remote Machine

We create a bare git repo, then point the working tree at the docroot of our website. This means all the git stuff is kept in the somesite.git folder, but the files themselves are checked out to the website's folder. Then we setup a post-receive hook to update the worktree folder after new changes have been pushed to the repo.

$ cd git
$ mkdir somesite.git
$ cd somesite.git/
$ git init --bare
Initialized empty Git repository in /home/caius/git/somesite.git/
$ git --bare update-server-info
$ git config core.worktree /home/caius/vhosts/somesite.com/htdocs
$ git config core.bare false
$ git config receive.denycurrentbranch ignore
$ cat > hooks/post-receive
#!/bin/sh
git checkout -f
^D
$ chmod +x hooks/post-receive

Local Machine

And now on the client machine we add the remote repo as a git remote, and then push to it.

$ git remote add web ssh://myserver/home/caius/git/somesite.git
$ git push web +master:refs/heads/master
Counting objects: 3, done.
Writing objects: 100% (3/3), 229 bytes, done.
Total 3 (delta 0), reused 0 (delta 0)
To ssh://myserver/home/caius/git/somesite.git
 * [new branch]      master -> master

All Done

And now if you go to somesite.com you'll see the contents of your git repo there. (somesite.com is just an example url though, I don't actually own it!)

Helpful URLs

3 Comments on Automatically Deploying Website From Remote Git Repository

  1. Hi Caius,

    Thanks for sharing this trick.

    Previously my workflow when pushing changes to a development server my team was working went as follows:

    1) Commit changes locally using Gitx or the Gitorious textmate plugin.

    2) Switch to the commandline, then call `cap deploy'.

    Seeing as branching is so cheap to do in git, having all pushed changes trigger a git checkout (or run any other arbitrary commands after afterwards) is really quite elegant.

  2. I can see the pushed files in my site directory. however when i try to browse the domain it shows me 500 internal server error. Can you help me? I Did this so far on server in public_html folder: mkdir test.git cd !$ git init --bare --shared chgrp -R developers . chmod -R g+swX .

    vi hooks/post-receive .....Added GIT_WORK_TREE = /home/public_html/my2 git checkout -f

    chmod +x hooks/post-receive

    Then on server in public_html i created another directory as work tree mkdir my2 cd my2

    chgrp -R developers

    So far all good

    On my local machine i can do the push easily to test.git and the work tree (the my2 folder ) showing me the files too.

    The only issue is that when i try to browse my2 on browser i.e. example.com/my2

    It is giving me 500 internal server error.

    I understand this is the permission isssue. but how to solve it i don't know.

    I already see that the user and group change under my2 directory when i do push. i.e. if i push index.php to test.git

    the file permissions change to

    -rw-r--r-- 1 bharat bharat 72 Nov 21 10:01 index.php

    where bharat is the username who do push to test.git

    Please help Thanks

  3. Hi Bharat,

    From what I remember, that is the downside of this technique. The files are owned by whichever user pushes to the .git folder.

    I think I solved this by adding the webserver's user to the ssh user's group (so I added www-data to my 'caius' group), so it can read my files by default. Then git sets the permissions as you've seen, but the webserver user can read the files so doesn't complain or 500.

    Hope that helps, albeit a bit of a hacky unideal solution.

About You
Comment