29 Apr 2009

Jekyll meets DreamHost. Automated deployment for Jekyll with Git

It has been just under a month since I launched this blog, and the first thing I promised myself was to automate deployment. If you have an existing GitHub account you might want to consider GitHub Pages, it’s quick and easy.

Why not GitHub Pages?

How will it work?

I am interested in achieving the same functionality offered by GitHub Pages with DreamHost. That is, a single push automatically generates the site, removing the pain of manually copying files and directories.

We are going to create a bare repository for pushing to. Every time you push, we will use the post-receive hook to execute a Bash script. The Bash script clones the repository with a working directory, executes jekyll and cleans up. Hooks in Git behave like events.

Preparing a Jekyll-friendly environment

Jekyll is not available on DreamHost. You will need to build your own RubyGems and install Jekyll with its dependancies. John Nunemaker has written an excellent guide.

If you are interested in code highlighting, you will also want to install Pygments. Pygments is a Python syntax highlighter that Jekyll uses to parse and wrap your code snippets in the appropriate HTML tags.

$ mkdir ~/lib/python
$ echo 'export PYTHONPATH="$HOME/lib/python:/usr/lib/python2.3"' >> ~/.bash_profile
$ source ~/.bash_profile

Download and build Pygments from source.

$ cd ~/src
$ wget http://pypi.python.org/packages/source/P/Pygments/Pygments-1.0.tar.gz
$ tar -xvzf Pygments-1.0.tar.gz
$ cd Pygments-1.0
$ python setup.py install --home=$HOME

Git it all together

Initialise a bare repository to push to. It is potentially dangerous to push to a remote repository with a working directory.

$ mkdir ~/src/your_git_repo.git
$ cd ~/src/your_git_repo.git
$ git --bare init

Add DreamHost as a remote in your local repository.

$ git remote add dreamhost ssh://user@server.com/home/user/src/your_git_repo.git

Write a Bash script to clone the repository, execute Jekyll and clean up. Jekyll will generate its output in to your publicly accessible directory.

# ~/bin/generate_public_www
#!/bin/bash
GIT_REPO=$HOME/src/your_git_repo.git
TMP_GIT_CLONE=$HOME/tmp/your_git_repo
PUBLIC_WWW=$HOME/var/www/your_site

git clone $GIT_REPO $TMP_GIT_CLONE
jekyll $TMP_GIT_CLONE $PUBLIC_WWW --pygments
rm -Rf $TMP_GIT_CLONE
exit
$ chmod +x ~/bin/generate_public_www

Add the Bash script in the post-receive hook of your bare repository. Hooks are Bash scripts too.

# ~/src/your_git_repo.git/hooks/post-receive
#!/bin/sh
$HOME/bin/generate_public_www
exit
$ chmod +x ~/src/your_git_repo.git/hooks/post-receive

Programmers should be lazy

Congratulations, you’re done! Every time you push to DreamHost, Jekyll will build the site. Cool, huh?!

$ git push dreamhost master

Bonus: You now have a redundant copy of your repository.

Updated 31 May 2009

Jay Williams followed this guide and experienced an annoying problem with the Git post-receive hook. After some trouble-shooting, it appeared that the hook was never executed because the user he was shelling in with didn’t have the access to the compiled binaries in its path.

Copying your .bash_profile to .bashrc should solve the issue for non-login shells.

$ cd ~/
$ cp .bashrc .bashrc.old
$ cp .bash_profile .bashrc

Updated 29 Oct 2009

I no longer recommend using this configuration for deployment. See simpler deployment for Jekyll using a Rakefile and rsync.


← Previous
Next →

Tate Johnson is a 23 year old Ruby on Rails developer and university student living in Brisbane, Australia. He enjoys riding bicycles, motorbikes, taking photos and travelling.