After a lot of frustration at my inability to hack apart, destroy, and rebuild my personal website at my every passing whim, I switched from WordPress to Jekyll. Partially for the benefits that come with serving a static site, but mostly for the learning experience.

However, it has been a learning curve. Getting used to blogging like a hacker is no joke.

I quickly grew tired of using FTP to clumsily update my site. I struggled to find something simple enough to push changes to my live server without overly complex solutions like Capistrano, but powerful enough to:

  1. only push files that had actually been updated,
  2. remove files I’d deleted from the project entirely,
  3. without losing non-Jekyll folders powering subdomains on my target server, living in the same synced folder.

Was it too tall of an order? Thankfully, no.

Note: Update everything on your server before doing ANYTHING. The following tutorial will permanently delete files on your server if you configure it wrong or forget to list something on the first try.

The Magic Elixir: Rsync to Taste

Rsync is one of the recommended deployment methods for Jekyll, and essentially uses SSH to push files to your server. It’s simple, and just customizable enough to serve your purposes.

However, I wasn’t able to use the provided rsync methods right out of the box. It needed a bit of tweaking to fit my above requirements, so here’s how I got it working for my particular setup.

You’ll need rsync on your local server (it’s likely already installed), and SSH access to your remote server.

Step 1: List All Your Server Side Non-Jekyll Files

Since I publish right to public html, there were already a handful of subdomain folders and Google verification files that I don’t want deleted when pushing changes from my Jekyll site.

Create a .txt file in your Jekyll root folder. I called mine “non-jekyll.txt”… but feel free to get creative.

The contents will list one file or folder per line, like this:

cgi-bin/
existing-folder/
google-verification-file.html
another-file.html

List everything that you love that isn’t part of your Jekyll site, but lives on the server in the folder where you are syncing your Jekyll site! Please, for the love of all that is holy, make a backup of everything before actually syncing your site.

Step 2: Build Your Rsync Command

There’s a few flags we need for this to run how we expect.

The basic rsync command:

$ rsync _site/ user@server:/path/to/site

The important, special flags we’ll be adding are:

As Jekyll regenerates files on every build, we can’t check the date of the file to know whether it’s been updated. So, we use checksum.

Delete ensures Jekyll files removed from the project are also removed from the server.

If you’re like me and deploying to a folder where other important files live, you can imagine that the delete flag would also remove those files… which is no good. So, we can use the exclude-from to make sure that those files and folders remain untouched and safe on the server.

This is the importance of the file created in Step 1. It is your only guardian against unintended consequences while using rsync to efficiently manage the deletion of old project files.

Here’s the updated rsync command:

$ rsync -v -rz --exclude-from 'not-jekyll.txt' --checksum --delete _site/ user@server:/path/to/site

You’ll run this from your Jekyll project root. But, how will you remember all these flags? What if you mistype something?

That’s where the alias comes in.

Step 3: Add a Bash Alias for Simplicity

Open up ~/.bash_profile. We’re going to harness the power of alias to make it super simple to run our rsync command.

Somewhere towards the bottom, create your custom alias with a line like so:

alias deploy-mysite="rsync -v -rz --exclude-from 'not-jekyll.txt' --checksum --delete _site/ user@server:/path/to/site"

You can use any name that isn’t already a registered Bash command, but in this example, you would navigate to your Jekyll project folder and run deploy-mysite from the command line.

You’ll then be prompted for your server’s SSH password.

Once you enter the password, your Jekyll site will push any changes to the server. (Be sure to run Jekyll build with all your production values in _config.xml first! Otherwise, what are you doing?)

How do You Sync Your Jekyll Site?

I know this is not the only way to run a Jekyll deployment, but it fit my situation perfectly.

For more complex projects I may eventually switch to a Git triggered deployment, but that is simply not necessary for a project this small when I’m not already equipped to configure that.

Does this work for you? What do you prefer for syncing your Jekyll projects? Let me know in the comments, I’m eager to learn.