Deploying sites with Apache, Jekyll, Sass and Git

After the huge rambling thing I did last time, let’s see if I can be a little more focussed. This is how I deploy the static bits of my site.

I keep the source files in git – I have a copy in this github for convenient pointing/examples. I build the site with Jekyll, which uses _config.yml as its config file. This file is blank. This is because I like the defaults. In accordance with Jekyll defaults, the layout templates for the site are in _layouts.

In this directory, I run jekyll --auto . /tmp/jekyll, which processes the whole directory tree into /tmp/jekyll (just to keep it out of the way) – if a file starts with a YAML header it’ll process it as a Jekyll source file, otherwise it’ll just copy it straight across. The process also stays running (that’s the --auto), watching for changes. This way I can edit source files and see changes instantly.

I build several domains-worth of pages at once using this tree. tom corresponds to http://tom.movieos.org and toys to http://toys.movieos.org. To preview this on my local computer, I have a few entries in /etc/hosts:

127.0.0.1 tom.movieos.local
127.0.0.1 toys.movieos.local

and a local apache config file containing:

<Directory "/tmp/jekyll/">
    Options Indexes MultiViews FollowSymLinks
    AllowOverride None
    Order allow,deny
    Allow from all
</Directory>

<VirtualHost *:80>
  ServerName tom.movieos.local
  DocumentRoot /tmp/jekyll/tom
</VirtualHost>

<VirtualHost *:80>
  ServerName toys.movieos.local
  DocumentRoot /tmp/jekyll/toys
</VirtualHost>

This way, I can open http://tom.movieos.local. in my browser, and see the local processed files. Useful!

Just to keep things interesting, I also don’t use CSS, I like to write sass. Now, there’s a branch of Jekyll that knows about sass, but I can’t get it to work – instead I use compass. config.rb in my site root is the compass configuration file. I run compass -w in the root of the repository and, like Jekyll, it will run and watch for changes, and rebuild the CSS files from the .sass files when I change them. Then Jekyll will see that they have changed and update the built site. More overhead, but it works very well.

When I’m happy, or whenever I’ve made some interesting changes, obviously I check things into the local git repository. Then I push the changes to the bare repository that lives on my colo. In that repository, I have a post-update hook:

#!/bin/sh
unset GIT_DIR 
  && cd /home/tomi/web/movieos 
  && git pull 
  && compass 
  && jekyll . /home/tomi/web/movieos_generated

So. I unset GIT_DIR because I’m about to talk to a different repository and don’t want to confuse things. Then I go to the directory where I have the source files checked out, and git pull to get them up to date. A single run of compass generates the CSS files in that directory, then I run jekyll to build the generated site.

Finally, Apache serves them. Rather than hard-code all my domains as I have locally, I’m more complicated on the server. I have a wildcard DNS entry that points *.movieos.org to the server. My apache config looks like this:

<VirtualHost *:80>
  # This virtualhost matches _anything_ in the movieos.org domain
  ServerName wildcard.movieos.org
  ServerAlias *.movieos.org
  ServerAdmin tom@jerakeen.org

  # not used
  DocumentRoot /home/tomi/web/movieos_generated/tom
  UseCanonicalName Off

  # match the first atom of the requested hostname, and serve files
  # out the directory with that name
  RewriteEngine on
  RewriteCond %{http_host} .
  RewriteCond %{http_host} ^([^.]+).movieos.org [NC]
  RewriteRule ^(.*) /home/tomi/web/movieos_generated/%1$1 [L]

  DefaultType text/plain
  DirectoryIndex index.php index.html
</VirtualHost>

This way, http://tom.movieos.org/ is served by files in /home/tomi/web/movieos_generated/tom, and likewise for all my other subdomains.

So that’s it. A post-commit hook runs two sorts of processors over the source, building it into a directory tree that’s served using Apache rewrite rules. Complicated and maybe fragile, but only at deploy time – because they’re static files, once they’re there, they stay there.