30 January 2014

Deploying Jekyll on Heroku

This post is part of a series: Switching to Jekyll from Wordpress

Note: Eventually I'll stop blogging about the way I blog. for now though, just humour me.

It's been a week since I switched from Wordpress to Jekyll and quite a lot has happened. You see, at first I thought Github's free hosting of my Jekyll site would be all I would ever need. And it is. kind of.

It was no time at all though before I was longing for a smoother, more integrated publishing workflow. After a little googling I found a way to bypass Github's "no plugin" policy... which I did. Then finally I decided Github hosting wasn't really my cup of tea and now, as of writing this, these beautiful, static words are being served to you by heroku.

Let's walk through it and if I lose you along the way it just means you found a home for your site before I did.

Vanilla Github web hosting

This was the first place I stopped. I created a github pages repo and populated the gh-pages branch with my jekyll site. Github then saw what I had done and compiled my little Jekyll site into a my-account.github.io webpage for all the world to see.

Not too shabby for 5 minutes of work.


But alas, I was not satisfied. For Github, in its infinite wisdom, does not allow custom plugins on the Jekyll sites it hosts. This is smart security-conscious thinking on their part but it means I can't have all the cool little plugins I need to do things like search, oembed, post series etc.

Travis-ci is a fantastic service that couples with Github to provide testing based on git pushes. Just turn on your repo, set up your travis config file and you will get an email a minute or two after pushing to github with the results if any tests you might run. From a Test Driven Design paradigm this must be amazing.

Now, since travis is designed to run test code and compile things it could also, in theory, compile my Jekyll site for me. This would allow me to bypass the fact that Github compiles of Jekyll don't allow custom plugins (for completely valid security reasons). So we do the compile of all the scary plugin code on Travis-ci in a safe environment and then push it over to the master branch which Github can then serve as flat HTML.

The workflow looked something like this:

  1. Write clever blog post
  2. commit to stable branch
  3. Push stable to Github
  4. Travis-ci wakes up, compiles stable and commits the resulting _site directory to master branch and then pushes everything back to Github.
  5. mattreimer.github.io is now serving at Github.

See "Further Reading" below for more resources on this workflow.

This worked pretty well for a few days but but I began to realize there were a number of problems with this setup:

  • The setup to get things to compile isn't completely trivial.
  • Storing and version controlling both the source and the compiled version makes for big repos.
  • Travis-ci sends a lot of emails
  • Travis has to boot and provision a whole virtual machine each time just to compile a few static pages of html.
  • This is not really what Travis-ci is meant for.

The last two reasons are what pushed me over the edge to find something new. Github offers free hosting but I feel like working around it to post big sites with custom plugins goes against why it implemented Jekyll. Travis-ci is really meant for testing and if I'm going to spawn and provision a whole new server every time I write a blog post it just seems wasteful.

Amazon S3

Amazon was a quick stop for me but it's worth mentioning because I ended up keeping a piece of it when I moved to Heroku. S3 is great because it's:

  • Fast!
  • Easy to use (relatively)
  • Cheap compared to traditional hosting
  • Has a button to turn any S3 bucket into a web host.
  • Integrates into CloudFront CDN. If you thought your images loaded fast before.... zoooom!

Full S3 hosting was a short stop for me because it still relied on Travis CI to do all the heavy lifting. I mention it here because in the end I decided to load all my images and binaries from S3 so I wrote an S3 tag helper plugin for jekyll so when I want to have an image in my webpage I just drop it into the S3 bucket using Transmit and then I type:

![My Macbook]({% s3 %}2014/macbook.png)

like so:

My Macbook

Finally: Enter Heroku

Heroku is a lovely set of cloud services that allow you to "pay for what you use" which, in the case of highly optimized flat HTML is not very much at all. It's all git enabled and there's a huge amount of support and quite a few tools to get you up and running.

It took virtually no time at all to discover Jonas Forsberg's heroku-deployer. Essentially it uses github's webhooks to detect pushes and then it uses a separate heroku app to compile and deploy the app.

The advantages here are significant:

  • A single instance of the heroku deployer can deploy any number of websites simultaneously.
  • Heroku is a fast, flexible, nerdy paradise of open API do-it-yourself-y goodness.
  • Heroku is node and rails enabled, opening up loads of opportunity for Jekyll to do really cool things in the future.

My workflow now looks like this:

  1. Write a clever blog post
    • Pro tip: While you write use jekyll serve --watch and livereload so you can see it evolve as you type.
  2. Upload any images to the S3 Bucket using an FTP program.
  3. Commit and push new posts to github.
  4. Marvel at my cleverness and show grattitude to those who made this moment possible while the deployer and Heroku do the rest.

I've included links below for those who want to try this out for themselves. Getting the deployer up and running the first time is not completely trivial and involves generating and using a few .SSH keys and settting up a second heroku accound but it's all worth it in the end.

Further Reading

Hosting Jekyll with Github pages

Travis-ci Resources


Deploying Jekyll on Heroku

This post is part of a series: Switching to Jekyll from Wordpress
  1. From Wordpress to Jekyll 19 January 2014
  2. Deploying Jekyll on Heroku 30 January 2014

Filed in: Jekyll   Update  

Comments: This is a tiny site and comment moderation is a pain. Let's use social links to have a conversation on a bigger platform: