I've been a blogger since 2002 and over the years there have been a lot of different blogging tools: Radio, WordPress, Serendipity, Movable Type, TypePad, b2, etc. After a long, on and off hiatus, I made the decision in 2016 to get serious about blogging again and at that point I committed to Jekyll. The reason was really the simplicity of:

  • Having all my blog posts in a filesystem, not a database, was a transformative and wonderful experience
  • Being able to use my coding editor to jot down a simple blog post was a big, big deal
  • Having all my blog posts run thru github, a tool I use not just daily but generally hourly
  • The ease of use of Github Pages which magically hosts a blog for you

And, for the past almost 2 years, this has been a great decision. My blog, FuzzyBlog, has been an essential tool for writing and just personal documentation. Basically whenever I have to learn something, I try and write it down and that's a model which works great for me.

I recently needed, however, to make a product specific blog, blog.gamenanny.io, for my new Game Nanny product and I discovered that I just couldn't use Github Pages for this at all. Github Pages creates a single blog tied to your github username and, well, I only have one github username. This meant that I had to get into self hosting my Jekyll blog or changing from Jekyll to something else. I chose the self hosting route and there in lies a how to tale.

Note: Like most things on the Internet, there must be a way around this limitation but I haven't found it yet.

Update: My friend Steve Grossi told me that you can get around this apparent Github limitation. I'm not entirely certain that I understand it but I'm glad to have it as an option. Thx Steve!

Understanding Jekyll's Output

The key thing to understand about Jekyll is that, at its heart, it is a static site generator. What this means is that when you type:

jekyll serve


jekyll build

it creates a set of static files that represent your site based on the markdown documents in _posts and your _config.yml configuration file. Self hosting a Jekyll site basically amounts to:

  1. Creating a jekyll site.
  2. Creating content in that Jekyll site.
  3. Running jekyll build or jekyll serve to create the static site files.
  4. Getting the files in _site to a public server (rsync).
  5. Having a web server on a public box that can serve the files generated by Jekyll.

The rest of this blog post walks you through all these steps. I'm a big, big believer in AWS so that's what I used but any public web host will work.

Creating a Jekyll Site

This can be done with:

jekyll new site_name

I used:

jekyll new game_nanny_blog

I'm not going to cover Jekyll details like theme configuration much although I have a set of references at the end. Jekyll theme configuration is to me, well, a black art that best resembles a pagan ritual (do it at in the dark of night, naked, chanting and so on). I just use the default minima theme and generally hope I can get away with it.

Basic configuration can be done by modifying _config.yml in your Jekyll root directory. Advanced configuration, well, it can be tedious.

Configuring Your Server

All you need to self host a jekyll blog is a dead simple web server like Nginx. Although I've mostly been doing Docker for executable software for sometime now, it just felt simpler to go old school on this.

Install nginx with:

sudo apt-get install nginx

You may need to edit the main configuration file with:

sudo vi /etc/nginx/nginx.conf

I found the defaults are pretty basic but your details may vary. And you'd also need to create a config file specifically for your main blog with:

sudo vi /etc/nginx/conf.d/blog.conf

Here's what I have in my blog.conf file:

server {
  listen 3301;
  server_name blog.gamenanny.io;
  root /home/ubuntu/gamenannyblog/_site;

  expires 30s;
  add_header Cache-Control public;
  add_header ETag "";

  error_page 404 /404.html;
  error_page 500 /500.html;

  location  ~ ^/assets/ {
    expires max;

  location ~ /\. {
    return 404;
    access_log off;
    log_not_found off;

  location = /favicon.ico {
    try_files /favicon.ico =204;
    access_log off;
    log_not_found off;

  location / {
    try_files $uri $uri.html $uri/ =404;

The main changes that I made in blog.conf are these:

listen 3301;
server_name blog.gamenanny.io;
root /home/ubuntu/gamenannyblog/_site;

Each of these is explained as follows:

  • listen 3301; The reason for that is that I have multiple sites on this one AWS instance and my AWS Elastic Load Balancer will be responsible for translation data on port 3301 to an port 80 request on blog.gamenanny.io. I use a standard set of port mappings on everything I build (*00 is always the main site, *01 is always the blog, *05 is always the ecommerce)
  • server_name server_name blog.gamenanny.io; This configures the site's domain name.
  • root /home/ubuntu/gamenannyblog/_site; This sets the root directory to serve the site's data from.

AWS Specifics

I'm deploying to a basic AWS EC2 instance and here is a quick overview of what I needed to do. Please note that these are the very broad strokes as I was quite rushed when I did it:

  1. Add blog.gamenanny.io to my Route 53 domain settings.
  2. Add a target group to the ELB for the blog.
  3. Add a listener rule to the ELB for the blog.
  4. Connect the listener rule to the target group. Until you do this there will be a 503 error and that's what always reminds me to couple the two.
  5. Create a directory on your file system where the content can reside. I did this with:

mkdir /home/ubuntu/gamenannyblog/_site

The _site corresponds to Jekyll's _site directory where it generates all data.


In order to handle deployment, I wrote a small shell script. deploy3.sh, which invokes jekyll build and then rsync's the content to the server. I've now spent almost two years using Jekyll with Github pages and my one comment about the git push to get my content live is that it is slow. I was absolutely shocked just how fast invoking jekyll build and then rsync was. Here's my deploy3.sh script:


JEKYLL_ENV=production bundle exec jekyll build
rsync -avr --rsh='ssh' --delete-after --delete-excluded _site/ ubuntu@

This level of speed is just plain awesome.

Thank You

This is actually the first time I've ever successfully used Nginx; previously I was a straight up, old school Apache guy. My buddy Nick did my Nginx configuration in about 2 shakes of time (read that as "really, really, really quick"). Thanks Nick!

See Also