Jekyll on Heroku
Tags: jekyll, heroku
Published: 2020-09-21 15:05:29

---
title: "Jekyll on Heroku"
published: true
tags: Jekyll, Heroku
canonical_url: https://calebhearth.com/jekyll-on-heroku
---

[Jekyll](https://jekyllrb.com/), the static website generator written in Ruby and popularized by GitHub, is a great candidate for being run on Heroku. Originally built to run on GitHub Pages, running Jekyll on Heroku allows you to take advantage of Jekyll’s powerful plugin system to do more than convert Markdown to HTML. On my blog, I have plugins to download my [Goodreads](https://www.goodreads.com/) current and recently read books and to generate [Open Graph](http://ogp.me/) images for posts. That said, it’s not straightforward to get up and running on Heroku without using `jekyll serve` to do the heavy lifting. `jekyll serve` uses Ruby’s [built-in, single threaded web server WEBrick](https://schneems.com/2017/08/01/is-webrick-webscale/), but a public site should be using a web server more suited for production, like nginx.

We’ll start from the very beginning. You’ll need Ruby and Bundler installed.

I like [ruby-install](https://github.com/postmodern/ruby-install) and [chruby](https://github.com/postmodern/chruby) as my Ruby installer and switcher.

This is the platform-agnostic way of installing the latest version of ruby-install. If you prefer, you can find instructions for OS X and Windows in [ruby-install’s README](https://github.com/postmodern/ruby-install#install).

> The commands below use the most recent versions of ruby-install and chruby available when this post was published. You probably want to use more recent versions if available.

```
$ wget -O ruby-install-0.6.1.tar.gz https://github.com/postmodern/ruby-install/archive/v0.6.1.tar.gz
$ tar -xzvf ruby-install-0.6.1.tar.gz
$ cd ruby-install-0.6.1/
$ sudo make install
```

You’ll also want chruby, which you can similarly install in a more platform specific way using instructions in [chruby’s README](https://github.com/postmodern/chruby#install).

```
$ wget -O chruby-0.3.9.tar.gz https://github.com/postmodern/chruby/archive/v0.3.9.tar.gz
$ tar -xzvf chruby-0.3.9.tar.gz
$ cd chruby-0.3.9/
$ sudo make install
```

Install the latest Ruby and use it:

```
$ ruby-install ruby
$ chruby ruby
```

You’ll need Bundler and the Jekyll gem:

```
$ gem install bundler jekyll
Fetching: bundler-1.9.9.gem (100%)
Successfully installed bundler-1.9.9
Fetching: jekyll-3.6.2.gem (100%)
Successfully installed jekyll-3.6.2
2 gems installed
```

Generating a new jekyll site is straightforward, and you get a site template for free similar to starting a new Rails app. We’ll be saving our work in Git along the way:

```
$ jekyll new jekyll-on-heroku
Ignoring nokogiri-1.8.1 because its extensions are not built. Try: gem pristine nokogiri --version 1.8.1
Running bundle install in /Users/caleb.thompson/code/jekyll-on-heroku/_rundoc/tmp/jekyll-on-heroku...
  …
New jekyll site installed in /Users/caleb.thompson/code/jekyll-on-heroku/_rundoc/tmp/jekyll-on-heroku.
$ cd jekyll-on-heroku
$ git init
Initialized empty Git repository in /Users/caleb.thompson/code/jekyll-on-heroku/_rundoc/tmp/jekyll-on-heroku/.git/
$ git add .
$ git commit -m "jekyll new jekyll-on-heroku"
[master (root-commit) ea8cd80] jekyll new jekyll-on-heroku
 8 files changed, 206 insertions(+)
 create mode 100644 .gitignore
 create mode 100644 404.html
 create mode 100644 Gemfile
 create mode 100644 Gemfile.lock
 create mode 100644 _config.yml
 create mode 100644 _posts/2017-12-07-welcome-to-jekyll.markdown
 create mode 100644 about.md
 create mode 100644 index.md
```

We have our Jekyll site (go ahead and try `jekyll serve` if you’d like), but we’ll need a Heroku app to deploy to. You will need [an account](https://signup.heroku.com/) and [the CLI](https://devcenter.heroku.com/articles/heroku-cli) installed before this step. We’re going to use the official Ruby buildpack as well as [Heroku’s (unofficial) Static buildpack](https://github.com/heroku/heroku-buildpack-static) to do the site generation and static page serving, respectively:

```
$ heroku create
Creating app... done, radiant-bastion-50307
https://radiant-bastion-50307.herokuapp.com/ | https://git.heroku.com/radiant-bastion-50307.git
$ heroku buildpacks:add heroku/ruby
Buildpack added. Next release on radiant-bastion-50307 will use heroku/ruby.
Run git push heroku master to create a new release using this buildpack.
$ heroku buildpacks:add https://github.com/heroku/heroku-buildpack-static
Buildpack added. Next release on radiant-bastion-50307 will use:
  1. heroku/ruby
  2. https://github.com/heroku/heroku-buildpack-static
Run git push heroku master to create a new release using these buildpacks.
```

Heroku’s buildpacks need specific files to be present to work correctly. We already have `Gemfile` for the Ruby buildpack, but we’ll also need a `static.json` file for the static buildpack. I’ve added a few of my favorite options to the `static.json`, and we’ll need to use `_site/` for our root as that is where Jekyll builds its static content by default.

In file `static.json` write:

```json
{
  "clean_urls": true,
  "https_only": true,
  "root": "_site/"
}
```

Let’s save our progress again.

```
$ git add static.json
$ git commit -m "Add static.json with reasonable defaults"
[master 6e1dea7] Add static.json with reasonable defaults
 1 file changed, 5 insertions(+)
 create mode 100644 static.json
```

The Ruby buildpack runs `rake assets:precompile` when it’s available. This is inspired by Rails’ pattern, but it works for any assets you’ll need. We’re going to use it for our entire site by running `jekyll build`.

In file `Rakefile` write:

```ruby
task "assets:precompile" do
  exec("jekyll build")
end
```

You’ll need Rake to run this in the first place, and we can save ourselves trouble in the future by specifying a version.

At the end of `Gemfile` add:

```ruby
gem "rake"
ruby "2.4.2"
```

And run `bundle` to install Rake.

```
$ bundle
  …
Bundle complete! 5 Gemfile dependencies, 24 gems now installed.
Use `bundle info [gemname]` to see where a bundled gem is installed.
```

We need to add the changes for the Rake task and new dependencies:

```
$ git add Rakefile Gemfile Gemfile.lock
$ git commit -m "Add Rake task to build Jekyll site"
[master 94f664b] Add Rake task to build Jekyll site
 3 files changed, 10 insertions(+)
 create mode 100644 Rakefile
```

Finally, we can push the app to Heroku!

```
$ git push heroku master
warning: not sending a push certificate since the receiving end does not support --signed push
remote: Compressing source files... done.
remote: Building source:
remote:
remote: -----> Ruby app detected
remote: -----> Compiling Ruby
remote: -----> Using Ruby version: ruby-2.4.2
remote: -----> Installing dependencies using bundler 1.15.2
remote: Running: bundle install --without development:test --path vendor/bundle --binstubs vendor/bundle/bin -j4 --deployment
  …
remote: -----> Detecting rake tasks
remote: -----> Precompiling assets
remote: Running: rake assets:precompile
remote: Configuration file: /tmp/build_c29844d07a39f5ce14fd64c34fc17680/_config.yml
remote: Source: /tmp/build_c29844d07a39f5ce14fd64c34fc17680
remote: Destination: /tmp/build_c29844d07a39f5ce14fd64c34fc17680/_site
remote: Incremental build: disabled. Enable with --incremental
remote: Generating...
remote: done in 0.901 seconds.
remote: Auto-regeneration: disabled. Use --watch to enable.
remote: Asset precompilation completed (1.49s)
remote:
remote: ###### WARNING:
remote: No Procfile detected, using the default web server.
remote: We recommend explicitly declaring how to boot your server process via a Procfile.
remote: https://devcenter.heroku.com/articles/ruby-default-web-server
remote:
remote: -----> Static HTML app detected
remote: % Total % Received % Xferd Average Speed Time Time Time Current
remote: 100 838k 100 838k 0 0 5598k 0 --:--:-- --:--:-- --:--:-- 5628k
remote: -----> Installed directory to /app/bin
remote: -----> Discovering process types
remote: Procfile declares types -> (none)
remote: Default types for buildpack -> web
remote:
remote: -----> Compressing...
remote: Done: 26.4M
remote: -----> Launching...
remote: Released v3
remote: https://radiant-bastion-50307.herokuapp.com/ deployed to Heroku
remote:
remote: Verifying deploy... done.
To https://git.heroku.com/radiant-bastion-50307.git
 * [new branch] master -> master
```

Open the URL at the end and enjoy your new Jekyll app on Heroku!