Jekyll is a great tool for building a blog, especially for a developer. It doesn’t come with a deployment solution out of the box. It is suggested that you take the generated _site/ folder contents and copy them to your server.

As a rails developer I already have a server with rails apps on it. This guide is how to deploy jekyll to that environment.

Blog updates will be pushed to the server using capistrano.

The server will use nginx to serve the blog over SSL provided by Let’s Encrypt. In my case the server is a 512MB DigitalOcean droplet (read: virtual server) running Ubuntu 16.04. This guide will assume you are at least using an Ubuntu server.

Before starting, make sure you have configured the domain you want your blog served on to point at your server’s IP address.

Server Setup

Log into your server as root, or obtain a root shell (sudo -i). If you are uncomfortable using root, prepend the following commands with sudo.

If nginx or letsencrypt is not already installed on the server, install it:

apt install nginx letsencrypt

Nginx will now be serving a default page on port 80. However, we need to briefly stop nginx so we can use the letsencrypt cert bot to verify we control the domain we are using.

systemctl stop nginx

Now that nginx is stopped, go through the letsencrypt wizard to get certs for one or more domains. Make note of the location of the full chain cert file. We’ll use it later in our nginx config. Should look like /etc/letsencrypt/live/myblog.com/fullchain.pem.

letsencrypt certonly --standalone -d blog-domain.com

After obtaining the certs you can start nginx again.

systemctl start nginx

We’ll need a user who will deploy the blog. Create one if you don’t already have a deploy user. I suggest leaving most fields blank and using a long random password. After configuring SSH properly you won’t have to ever type the password again.

adduser deploy

Next, we create a folder to serve the blog from and give ownership to the deploy user.

cd /var/www
mkdir -p blog/shared/log
chown -R deploy:deploy blog

Nginx will need to know about our new site, so lets create that config now. Create a file at /etc/nginx/sites-available/blog with the following contents. Make sure you replace the paths with the correct paths for your blog and cert. This particular config will redirect all HTTP requests to identical HTTPS requests, ensuring SSL is used by all your site visitors.

Add a link to your new site config in sites-enabled and restart nginx.

cd /etc/nginx/sites-enabled
ln -s /etc/nginx/sites-available/blog blog
systemctl restart nginx

Complete SSH setup is beyond the scope of this guide, but the next step should be adding your public ssh key you will use when deploying to /home/deploy/.ssh/authorized_keys so you won’t have to enter a password each deploy.

Now, the server config is ready. Time to actually deploy the site content to the server.

Capistrano/Deploy Setup

The rest of this guide will take place on your local machine. Install capistrano by adding some gems to your jekyll blog’s Gemfile:

gem "capistrano"
gem "capistrano-chruby"

Then have bundler install capistrano and have capistrano capify your blog.

bundle install
cap install

This will create several files in your blog’s directory. We will need to modify them. First, let’s start with the Capfile. We only need a few things for our blog, so your Capfile should look something like this:

require "capistrano/setup"
require "capistrano/deploy"

require 'capistrano/chruby'
require 'capistrano/bundler'

The bulk of the capistrano configuration lives in config/deploy.rb. That file should be updated to look like the following file. Update the git URL, application, and deploy location. Also, if you are not using chruby you can remove the chruby lines (and the chruby entries from Gemfile and Capfile).

We are going to deploy the blog to an environment (“stage” in capistrano parlance) called production. The config specific to your production environment lives in config/deploy/production.rb and really just needs to contain the server address. It should look something like this:

server "blog.linkleaf.com", user: "deploy", roles: %w{web}

With all the prior configuration in place you should now be able to deploy your blog using capistrano.

cap production deploy

Hopefully congratulations are now appropriate as you have successfully setup a modern, efficient, SSL encrypted blog with automated deployment through capistrano. Run the above command any time you are ready for your most recent blog posts or changes to be published.

Happy blogging.