Jekyll is a wonderfully simple static blog generator from GitHub. It’s a breeze to work with, but sometimes it might feel difficult to set up. In this tutorial we’ll see that it only requires a few steps.

Jekyll on Ubuntu

Starting with a brand new Ubuntu 18.04 installation

For starters, we’ll make sure to install a brand new Ubuntu 18.04 using a live usb. The linked tutorial is really top-notch so it shouldn’tbe hard to follow.

Next, it would help to already have a text editor installed. Although I often use VS Code in my day-to-day work, it’s quite resource intensive. If that’s the case, you can’t go wrong with installing Sublime Text 3 on Ubuntu 18.04.

Now that that’s taken care of, we can start adding Jekyll.

Installing Jekyll on Ubuntu 18.04

First we can check if we already have Jekyll installed:


If the above command is not recognized, we can begin with installation.

As a side-check, we can run a check for the current ruby version, with:

ruby --version

We’ll get this back:

ruby 2.5.1p57 (2018-03-29 revision 63029) [x86_64-linux-gnu]

First, let’s get the dependencies:

sudo apt-get install ruby-full build-essential zlib1g-dev

Here’s a sample output:

phpuser@pc:~$ sudo apt-get install ruby-full build-essential zlib1g-dev
[sudo] password for phpuser: 
Reading package lists... Done
Building dependency tree       
Reading state information... Done
build-essential is already the newest version (12.4ubuntu1).
zlib1g-dev is already the newest version (1:1.2.11.dfsg-0ubuntu2).
The following packages were automatically installed and are no longer required:
  gyp libjs-async libjs-inherits libjs-node-uuid libjs-underscore
  libpython-stdlib libuv1-dev node-abbrev node-ansi node-ansi-color-table
  node-archy node-async node-balanced-match node-block-stream
  node-brace-expansion node-combined-stream node-concat-map node-cookie-jar
  node-delayed-stream node-forever-agent node-form-data node-fs.realpath
  node-fstream node-fstream-ignore node-github-url-from-git node-glob
  node-graceful-fs node-hosted-git-info node-inflight node-inherits node-ini
  node-isexe node-json-stringify-safe node-lockfile node-lru-cache node-mime
  node-minimatch node-mkdirp node-mute-stream node-node-uuid node-nopt
  node-npmlog node-once node-osenv node-path-is-absolute node-pseudomap
  node-qs node-read node-request node-retry node-rimraf node-semver node-sha
  node-slide node-spdx-correct node-spdx-expression-parse
  node-spdx-license-ids node-tar node-tunnel-agent node-underscore
  node-validate-npm-package-license node-which node-wrappy node-yallist python
  python-minimal python-pkg-resources python2.7 python2.7-minimal
Use 'sudo apt autoremove' to remove them.
The following additional packages will be installed:
The following NEW packages will be installed:
  ri ruby-full
0 upgraded, 2 newly installed, 0 to remove and 0 not upgraded.
Need to get 7212 B of archives.
After this operation, 36,9 kB of additional disk space will be used.
Do you want to continue? [Y/n] 
Get:1 bionic/universe amd64 ri all 1:2.5.1 [4496 B]
Get:2 bionic/universe amd64 ruby-full all 1:2.5.1 [2716 B]
Fetched 7212 B in 0s (43,5 kB/s)   
Selecting previously unselected package ri.
(Reading database ... 188061 files and directories currently installed.)
Preparing to unpack .../archives/ri_1%3a2.5.1_all.deb ...
Unpacking ri (1:2.5.1) ...
Selecting previously unselected package ruby-full.
Preparing to unpack .../ruby-full_1%3a2.5.1_all.deb ...
Unpacking ruby-full (1:2.5.1) ...
Setting up ri (1:2.5.1) ...
Setting up ruby-full (1:2.5.1) ...

Installing Ruby gems as root is not recommended; thus, we’ll add a new gem installation folder for our Ubuntu user account. We’ll do it by adding environment variables to our ~/.bashrc file.

This is how we’ll add them:

echo '# Install Ruby gems to ~/gems' >> ~/.bashrc
echo 'export GEM_HOME=$HOME/gems"' >> ~/.bashrc
echo 'export PATH="$HOME/gems/bin:$PATH"' >> ~/.bashrc
source ~/.bashrc

Now we can check the updates made to our ~/.bashrc with:

nano ~/.bashrc

If we scroll down to the very bottom of the file, we’ll find this:

# Install Ruby Gems to ~/gems
export GEM_HOME="$HOME/gems"
export PATH="$HOME/gems/bin:$PATH"

After we’ve verified the updates made to our ~/.bashrc file, we can close the nano editor with CTRL + x.

Installing the jekyll and bundler gems

Now we’re ready to install two gems: jekyll and bundler.

gem install jekyll bundler

Here’s a sample output:

Fetching: public_suffix-4.0.5.gem (100%)
Successfully installed public_suffix-4.0.5
Fetching: addressable-2.7.0.gem (100%)
Successfully installed addressable-2.7.0
Fetching: colorator-1.1.0.gem (100%)
Successfully installed colorator-1.1.0
Fetching: http_parser.rb-0.6.0.gem (100%)
Building native extensions. This could take a while...
Successfully installed http_parser.rb-0.6.0
Fetching: eventmachine-1.2.7.gem (100%)
Building native extensions. This could take a while...
Successfully installed eventmachine-1.2.7
Fetching: em-websocket-0.5.1.gem (100%)
Successfully installed em-websocket-0.5.1
Fetching: concurrent-ruby-1.1.6.gem (100%)
Successfully installed concurrent-ruby-1.1.6
Fetching: i18n-1.8.3.gem (100%)

HEADS UP! i18n 1.1 changed fallbacks to exclude default locale.
But that may break your application.

If you are upgrading your Rails application from an older version of Rails:

Please check your Rails app for 'config.i18n.fallbacks = true'.
If you're using I18n (>= 1.1.0) and Rails (< 5.2.2), this should be
'config.i18n.fallbacks = [I18n.default_locale]'.
If not, fallbacks will be broken in your app by I18n 1.1.x.

If you are starting a NEW Rails application, you can ignore this notice.

For more info see:

Successfully installed i18n-1.8.3
Fetching: ffi-1.13.1.gem (100%)
Building native extensions. This could take a while...
Successfully installed ffi-1.13.1
Fetching: sassc-2.4.0.gem (100%)
Building native extensions. This could take a while...
:Successfully installed sassc-2.4.0
Fetching: jekyll-sass-converter-2.1.0.gem (100%)
Successfully installed jekyll-sass-converter-2.1.0
Fetching: rb-fsevent-0.10.4.gem (100%)
Successfully installed rb-fsevent-0.10.4
Fetching: rb-inotify-0.10.1.gem (100%)
Successfully installed rb-inotify-0.10.1
Fetching: listen-3.2.1.gem (100%)
Successfully installed listen-3.2.1
Fetching: jekyll-watch-2.2.1.gem (100%)
Successfully installed jekyll-watch-2.2.1
Fetching: rexml-3.2.4.gem (100%)
Successfully installed rexml-3.2.4
Fetching: kramdown-2.3.0.gem (100%)
Successfully installed kramdown-2.3.0
Fetching: kramdown-parser-gfm-1.1.0.gem (100%)
Successfully installed kramdown-parser-gfm-1.1.0
Fetching: liquid-4.0.3.gem (100%)
Successfully installed liquid-4.0.3
Fetching: mercenary-0.4.0.gem (100%)
Successfully installed mercenary-0.4.0
Fetching: forwardable-extended-2.6.0.gem (100%)
Successfully installed forwardable-extended-2.6.0
Fetching: pathutil-0.16.2.gem (100%)
Successfully installed pathutil-0.16.2
Fetching: rouge-3.20.0.gem (100%)
Successfully installed rouge-3.20.0
Fetching: safe_yaml-1.0.5.gem (100%)
Successfully installed safe_yaml-1.0.5
Fetching: unicode-display_width-1.7.0.gem (100%)
Successfully installed unicode-display_width-1.7.0
Fetching: terminal-table-1.8.0.gem (100%)
Successfully installed terminal-table-1.8.0
Fetching: jekyll-4.1.1.gem (100%)
Successfully installed jekyll-4.1.1
Parsing documentation for public_suffix-4.0.5
Installing ri documentation for public_suffix-4.0.5
Parsing documentation for addressable-2.7.0
Installing ri documentation for addressable-2.7.0
Parsing documentation for colorator-1.1.0
Installing ri documentation for colorator-1.1.0
Parsing documentation for http_parser.rb-0.6.0
Installing ri documentation for http_parser.rb-0.6.0
Parsing documentation for eventmachine-1.2.7
Installing ri documentation for eventmachine-1.2.7
Parsing documentation for em-websocket-0.5.1
Installing ri documentation for em-websocket-0.5.1
Parsing documentation for concurrent-ruby-1.1.6
Installing ri documentation for concurrent-ruby-1.1.6
Parsing documentation for i18n-1.8.3
Installing ri documentation for i18n-1.8.3
Parsing documentation for ffi-1.13.1
Installing ri documentation for ffi-1.13.1
Parsing documentation for sassc-2.4.0
Installing ri documentation for sassc-2.4.0
Parsing documentation for jekyll-sass-converter-2.1.0
Installing ri documentation for jekyll-sass-converter-2.1.0
Parsing documentation for rb-fsevent-0.10.4
Installing ri documentation for rb-fsevent-0.10.4
Parsing documentation for rb-inotify-0.10.1
Installing ri documentation for rb-inotify-0.10.1
Parsing documentation for listen-3.2.1
Installing ri documentation for listen-3.2.1
Parsing documentation for jekyll-watch-2.2.1
Installing ri documentation for jekyll-watch-2.2.1
Parsing documentation for rexml-3.2.4
Installing ri documentation for rexml-3.2.4
Parsing documentation for kramdown-2.3.0
Installing ri documentation for kramdown-2.3.0
Parsing documentation for kramdown-parser-gfm-1.1.0
Installing ri documentation for kramdown-parser-gfm-1.1.0
Parsing documentation for liquid-4.0.3
Installing ri documentation for liquid-4.0.3
Parsing documentation for mercenary-0.4.0
Installing ri documentation for mercenary-0.4.0
Parsing documentation for forwardable-extended-2.6.0
Installing ri documentation for forwardable-extended-2.6.0
Parsing documentation for pathutil-0.16.2
Installing ri documentation for pathutil-0.16.2
Parsing documentation for rouge-3.20.0
Installing ri documentation for rouge-3.20.0
Parsing documentation for safe_yaml-1.0.5
Installing ri documentation for safe_yaml-1.0.5
Parsing documentation for unicode-display_width-1.7.0
Installing ri documentation for unicode-display_width-1.7.0
Parsing documentation for terminal-table-1.8.0
Installing ri documentation for terminal-table-1.8.0
Parsing documentation for jekyll-4.1.1
Installing ri documentation for jekyll-4.1.1
Done installing documentation for public_suffix, addressable, colorator, http_parser.rb, eventmachine, em-websocket, concurrent-ruby, i18n, ffi, sassc, jekyll-sass-converter, rb-fsevent, rb-inotify, listen, jekyll-watch, rexml, kramdown, kramdown-parser-gfm, liquid, mercenary, forwardable-extended, pathutil, rouge, safe_yaml, unicode-display_width, terminal-table, jekyll after 46 seconds
Fetching: bundler-2.1.4.gem (100%)
Successfully installed bundler-2.1.4
Parsing documentation for bundler-2.1.4
Installing ri documentation for bundler-2.1.4
Done installing documentation for bundler after 4 seconds
28 gems installed

Let’s check if we now have the jekyll command available on our command line:


This is what we’ll get back:

jekyll 4.1.1 -- Jekyll is a blog-aware, static site generator in Ruby


  jekyll <subcommand> [options]

        -s, --source [DIR]  Source directory (defaults to ./)
        -d, --destination [DIR]  Destination directory (defaults to ./_site)
            --safe         Safe mode (defaults to false)
        -p, --plugins PLUGINS_DIR1[,PLUGINS_DIR2[,...]]  Plugins directory (defaults to ./_plugins)
            --layouts DIR  Layouts directory (defaults to ./_layouts)
            --profile      Generate a Liquid rendering profile
        -h, --help         Show this message
        -v, --version      Print the name and version
        -t, --trace        Show the full backtrace when an error occurs

  build, b              Build your site
  clean                 Clean the site (removes site output and metadata file) without building.
  doctor, hyde          Search site and print specific deprecation warnings
  help                  Show the help message, optionally for a given subcommand.
  new                   Creates a new Jekyll site scaffold in PATH
  new-theme             Creates a new Jekyll theme scaffold
  serve, server, s      Serve your site locally

Note that our Ruby version is still unchanged:

ruby --version

This will return:

ruby 2.5.1p57 (2018-03-29 revision 63029) [x86_64-linux-gnu]

Now we can run git clone on a jekyll project we have access to, using the following syntax:

git clone<username>/<repository-name>.git

Once the project’s been cloned, we can cd into it, for example:

cd <repository-name>

Finally, we can run the bundle command (an alias of bundle install).

This will install all the dependencies in our Gemfile. Here’s a sample output:

Fetching gem metadata from
Using concurrent-ruby 1.1.6
Fetching i18n 0.9.5
Installing i18n 0.9.5
Fetching minitest 5.13.0
Installing minitest 5.13.0
Fetching thread_safe 0.3.6
Installing thread_safe 0.3.6
Fetching tzinfo 1.2.7
Installing tzinfo 1.2.7
Fetching zeitwerk 2.3.0
Installing zeitwerk 2.3.0
Fetching activesupport
Installing activesupport
Fetching public_suffix 3.1.1
Installing public_suffix 3.1.1
Using addressable 2.7.0
Using bundler 2.1.4
Fetching coffee-script-source 1.11.1
Installing coffee-script-source 1.11.1
Fetching execjs 2.7.0
Installing execjs 2.7.0
Fetching coffee-script 2.4.1
Installing coffee-script 2.4.1
Using colorator 1.1.0
Fetching ruby-enum 0.8.0
Installing ruby-enum 0.8.0
Fetching commonmarker 0.17.13
Installing commonmarker 0.17.13 with native extensions
Fetching dnsruby 1.61.3
Installing dnsruby 1.61.3
Using eventmachine 1.2.7
Using http_parser.rb 0.6.0
Using em-websocket 0.5.1
Fetching ffi 1.12.2
Installing ffi 1.12.2 with native extensions
Fetching ethon 0.12.0
Installing ethon 0.12.0
Fetching multipart-post 2.1.1
Installing multipart-post 2.1.1
Fetching faraday 1.0.1
Installing faraday 1.0.1
Using forwardable-extended 2.6.0
Fetching gemoji 3.0.1
Installing gemoji 3.0.1
Fetching sawyer 0.8.2
Installing sawyer 0.8.2
Fetching octokit 4.18.0
Installing octokit 4.18.0
Fetching typhoeus 1.4.0
Installing typhoeus 1.4.0
Fetching github-pages-health-check 1.16.1
Installing github-pages-health-check 1.16.1
Using rb-fsevent 0.10.4
Using rb-inotify 0.10.1
Fetching sass-listen 4.0.0
Installing sass-listen 4.0.0
Fetching sass 3.7.4
Installing sass 3.7.4
Fetching jekyll-sass-converter 1.5.2
Installing jekyll-sass-converter 1.5.2
Using listen 3.2.1
Using jekyll-watch 2.2.1
Fetching kramdown 1.17.0
Installing kramdown 1.17.0
Using liquid 4.0.3
Fetching mercenary 0.3.6
Installing mercenary 0.3.6
Using pathutil 0.16.2
Fetching rouge 3.19.0
Installing rouge 3.19.0
Using safe_yaml 1.0.5
Fetching jekyll 3.8.7
Installing jekyll 3.8.7
Fetching jekyll-avatar 0.7.0
Installing jekyll-avatar 0.7.0
Fetching jekyll-coffeescript 1.1.1
Installing jekyll-coffeescript 1.1.1
Fetching jekyll-commonmark 1.3.1
Installing jekyll-commonmark 1.3.1
Fetching jekyll-commonmark-ghpages 0.1.6
Installing jekyll-commonmark-ghpages 0.1.6
Fetching jekyll-default-layout 0.1.4
Installing jekyll-default-layout 0.1.4
Fetching jekyll-feed 0.13.0
Installing jekyll-feed 0.13.0
Fetching jekyll-gist 1.5.0
Installing jekyll-gist 1.5.0
Fetching jekyll-github-metadata 2.13.0
Installing jekyll-github-metadata 2.13.0
Fetching mini_portile2 2.4.0
Installing mini_portile2 2.4.0
Fetching nokogiri 1.10.9
Installing nokogiri 1.10.9 with native extensions
Fetching html-pipeline 2.13.0
Installing html-pipeline 2.13.0
Fetching jekyll-mentions 1.5.1
Installing jekyll-mentions 1.5.1
Fetching jekyll-optional-front-matter 0.3.2
Installing jekyll-optional-front-matter 0.3.2
Fetching jekyll-paginate 1.1.0
Installing jekyll-paginate 1.1.0
Fetching jekyll-readme-index 0.3.0
Installing jekyll-readme-index 0.3.0
Fetching jekyll-redirect-from 0.15.0
Installing jekyll-redirect-from 0.15.0
Fetching jekyll-relative-links 0.6.1
Installing jekyll-relative-links 0.6.1
Fetching rubyzip 2.3.0
Installing rubyzip 2.3.0
Fetching jekyll-remote-theme 0.4.1
Installing jekyll-remote-theme 0.4.1
Fetching jekyll-seo-tag 2.6.1
Installing jekyll-seo-tag 2.6.1
Fetching jekyll-sitemap 1.4.0
Installing jekyll-sitemap 1.4.0
Fetching jekyll-swiss 1.0.0
Installing jekyll-swiss 1.0.0
Fetching jekyll-theme-architect 0.1.1
Installing jekyll-theme-architect 0.1.1
Fetching jekyll-theme-cayman 0.1.1
Installing jekyll-theme-cayman 0.1.1
Fetching jekyll-theme-dinky 0.1.1
Installing jekyll-theme-dinky 0.1.1
Fetching jekyll-theme-hacker 0.1.1
Installing jekyll-theme-hacker 0.1.1
Fetching jekyll-theme-leap-day 0.1.1
Installing jekyll-theme-leap-day 0.1.1
Fetching jekyll-theme-merlot 0.1.1
Installing jekyll-theme-merlot 0.1.1
Fetching jekyll-theme-midnight 0.1.1
Installing jekyll-theme-midnight 0.1.1
Fetching jekyll-theme-minimal 0.1.1
Installing jekyll-theme-minimal 0.1.1
Fetching jekyll-theme-modernist 0.1.1
Installing jekyll-theme-modernist 0.1.1
Fetching jekyll-theme-primer 0.5.4
Installing jekyll-theme-primer 0.5.4
Fetching jekyll-theme-slate 0.1.1
Installing jekyll-theme-slate 0.1.1
Fetching jekyll-theme-tactile 0.1.1
Installing jekyll-theme-tactile 0.1.1
Fetching jekyll-theme-time-machine 0.1.1
Installing jekyll-theme-time-machine 0.1.1
Fetching jekyll-titles-from-headings 0.5.3
Installing jekyll-titles-from-headings 0.5.3
Fetching jemoji 0.11.1
Installing jemoji 0.11.1
Fetching minima 2.5.1
Installing minima 2.5.1
Using unicode-display_width 1.7.0
Using terminal-table 1.8.0
Fetching github-pages 206
Installing github-pages 206
Bundle complete! 1 Gemfile dependency, 85 gems now installed.
Use `bundle info [gemname]` to see where a bundled gem is installed.
Post-install message from dnsruby:
Installing dnsruby...
  For issues and source code:
  For general discussion (please tell us how you use dnsruby):!forum/dnsruby
Post-install message from sass:

Ruby Sass has reached end-of-life and should no longer be used.

* If you use Sass as a command-line tool, we recommend using Dart Sass, the new
  primary implementation:

* If you use Sass as a plug-in for a Ruby web framework, we recommend using the
  sassc gem:

* For more details, please refer to the Sass blog:

Post-install message from html-pipeline:
Thank you for installing html-pipeline!
You must bundle Filter gem dependencies.
See html-pipeline for more details.

Finally, we can try running our local Jekyll project with:

jekyll s

The jekyll s command is an alias for jekyll serve.

After running this command, we might get the following sample error:

	 1: from /home/phpuser/gems/gems/bundler-2.1.4/lib/bundler/runtime.rb:31:in `block in setup'
/home/phpuser/gems/gems/bundler-2.1.4/lib/bundler/runtime.rb:312:in `check_for_activated_spec!': You have already activated i18n 1.8.3, but your Gemfile requires i18n 0.9.5. Prepending `bundle exec` to your command may solve this. (Gem::LoadError)

To fix this issue, we simply run this command:

bundle exec jekyll s

This time, Jekyll will build our site locally:

Incremental build: disabled. Enable with --incremental

Once built, we can view the site at localhost:4000 in our browser of choice.