Deploying your static nanoc sites to Heroku's hosted platform with Nanoc::Heroku

Saturday, July 23 2011

So you’ve created a new application and would like to launch it. It is a Ruby application, but you created the front pages using nanoc, a static site generator. Your Ruby application will be deployed to Heroku’s platform, but where will your static site run? A separate VPS? A shared host?

I personally dislike the idea of having to deploy parts of my application (the front pages, the application itself) to different servers/platforms. Shared hosting sucks, so let’s assume we get a VPS to host our static front pages. First of all, adding a new VPS costs money. You have to then set up a web server, and ensure it stays up. You have to keep the server up to date with security patches, and if things go wrong, then you’ll have to solve these issues yourself. All that for a simple static website.

I enjoy deploying applications to Heroku. It’s easy, it’s fast, it’s performant, it’s secure, it’s managed and you go from “nothing” to “deployed” in seconds. Wouldn’t it be nice if we could quickly create a static site using a great site development tool, and (optionally) leverage other tools like haml, compass, coffeescript, then render the html, and deploy it to Heroku, for free?

Nanoc::Heroku

Heroku currently supports Ruby, Node and Clojure, but not (directly) raw HTML sites. However, that doesn’t mean that we can’t use a little bit of Ruby and Rack to get around it.

Nanoc::Heroku is a little bare-bones nanoc application/structure that I set up. It is not a gem, you simply clone it from the repository and immediately get to work with a few commands. Let me highlight a few interesting points:

It has out-of-the-box support for:

  • HAML / SASS
  • Compass
  • CoffeeScript
  • Markdown
  • Builder

It auto-compiles your site when adding/updating files using:

  • Guard

It contains rake tasks for:

  • Optimizing Images of format: JPG and PNG
  • Compressing Stylesheets and Javascripts

It deploys to Heroku with:

  • rake deploy

after changing a constant in the Rakefile and running heroku create mysite --stack cedar.

Getting started

To get up and running quickly, all you have to do is clone the git repository, remove the origin remote, install the bundled gems, start guard and the nanoc server. Here’s how:

Clone the repository, remove remote, install dependencies:


                git clone git://github.com/meskyanichi/nanoc-heroku.git my_site_name
                cd my_site_name && git remote rm origin && bundle
              

In the current shell, run the following to do the initial compiling and start the server afterwards:


                nanoc compile && nanoc view
              

And finally, open a second shell tab and run the following as well:


                guard
              

Visit http://localhost:3000/ and your site should be up and running. Every time you add/update a file inside the ./content directory, Guard will run nanoc compile to deliver a fresh state of the latest changes, rendered in ./output. These will be immediately visible on http://localhost:3000/ after a browser refresh.

Refer to the nanoc documentation for more in-depth information about the static site generator itself.

Deploying to Heroku

First of all, let’s create the Heroku application. It must be running on the Celadon Cedar stack. Note: The Heroku gem updates very frequently, so it’s a good idea to run gem install heroku once in a while to ensure you’re on the latest version.


                gem install heroku
                heroku create mysite --stack cedar
              

This will add the heroku remote to your git repository. Next, open up your Rakefile, it contains a constant called BASE_URL. The value of the BASE_URL should be your domain url. For example: http://github.com. This is required because when you run the deployment task, it will update the config.yaml to ensure it compiles with the proper URL’s in your website, so your website’s link to link to http://localhost:3000/ urls.

Now, before we deploy we need to install the image optimization utilities, and the Java runtime for the CSS/JS compressor. On OSX using Homebrew, you can install the image optimization utilities by running:


                brew install jpegoptim optipng
              

On Linux (Ubuntu) with apt-get or aptitude, the equivalent is:


                apt-get install jpegoptim optipng
                aptitude install jpegoptim optipng
              

The master branch will always be used to deploy your website. You could tweak the Rakefile to change this behavior. Ensure that you are working in a clean working directory (that there is nothing to commit). Once you’re ready to deploy the master branch to Heroku, simply issue the following command:


                rake deploy
              

This will create a new branch called deployment, and checkout to it. It will then take the value of the BASE_URL constant (which is defined in the Rakefile) and apply it to the config.yaml file and will re-compile the whole website. It will remove the output entry from your .gitignore as well so it can commit the raw files. After that it’ll commit these changes to the deployment branch and push it to Heroku. Once deployed, it will checkout back to the master branch and remove the deployment branch again. You are now back at the state you were before you ran rake deploy, except that you actually deployed your website to Heroku.

You don’t have to worry about this procedure though. Just sit on a clean master branch and run the Rake task. If the master branch isn’t clean, it will tell you upon initializing the Rake task and abort the operation.

And That’s it! Your static site should now be running on Heroku! Ensure the web process is running. You can check the process list by running heroku ps. If it isn’t listed, be sure to run heroku ps:scale web=1. When you see that there is one process running, run heroku open to open up your browser to view the application.

You can of course use this for any static site, not just for front pages of your applications. You could use it for a blog, or other things. So far I have already moved this blog, as well as the HireFire front-page (both of which are using Nanoc::Heroku) to Heroku, and I’ve been very satisfied with the migration!