January 21, 2012
Blogging With Jekyll + S3 + CloudFront
When I decided to power this blog with Jekyll, it took me a while to figure out a good way to host and configure it. I thought explaining my setup might be helpful for others who are getting started with Jekyll.
If you have a blog but haven’t heard of Jekyll, you should check it out. It’s great for anyone who likes writing in the text editor of their choice instead of some web interface, wants to store their work in Dropbox or version control, and is comfortable running a few Terminal commands.
Why S3?
I initially started out hosting my blog on GitHub Pages, which is a free service offered by GitHub for hosting a Jekyll blog stored in Git. The price is certainly right, but there were a couple problems.
First, GitHub Pages experienced some downtime while I was setting up my blog, and I feel strongly about having good blog uptime. Second, if you don’t have a paid GitHub account ($7/month+) the repository containing your blog is accessible to the world, including drafts and unpublished posts.
An alternative is using Amazon S3, Amazon’s cloud file storage service. Amazon lets you host a static website on S3 with your own domain name. You can also easily use Amazon CloudFront with S3. CloudFront is a CDN (content distribution network) that serves your content from a worldwide server network and helps to make your website faster.
Setting up S3 and CloudFront
If you’ve never used Amazon Web Services before, it can be a little confusing to get started. First, you need to sign up for an AWS account. When you have your account, log into the AWS Management Console and head to the S3 tab. Then:
Create a bucket called
www.yourdomain.com
. One minor downside to S3 is you can’t useyourdomain.com
– you have to use some subdomain likewww
orblog
. I’ll talk about this more below.Under the properties for this bucket, you’ll need to go to the Website tab, check the box to enable static web hosting, and set your index and error documents. Your index document should probably be
index.html
. Your error document is another HTML page for file not found (404) errors.Make a note of your endpoint (mine is
http://www.maxmasnick.com.s3-website-us-east-1.amazonaws.com/
). You’ll need it below.On the permissions tab, create a bucket policy. You can copy mine and just change the bucket name.
You can go ahead and enable CloudFront now too. Head over to the CloudFront tab, and create a new Distribution for the S3 bucket you just created. This will mirror your S3 bucket on CloudFront – for example, http://d2lazzs3blj336.cloudfront.net/index.html shows the home page of my website exactly* as it appears on S3.
* CloudFront will cache the contents of your S3 bucket for up to 24 hours. This cache is created from S3 the first time someone hits an asset under your CloudFront URL. This means that CloudFront won’t necessarily reflect changes on S3 immediately. You can manually expire objects in CloudFront, but it’s easier to just not use it for anything that will change frequently.
Setting up your DNS
You’ll need to create some DNS records to use your own domain with S3. The way you do this depends on your DNS provider (I use Zerigo, which is cheap, reliable, and easy to use). At a minimum, you’ll need to follow your DNS provider’s instructions to create a CNAME
pointing www.yourdomain.com
at your S3 endpoint.
Zerigo lets you create a redirect from yourdomain.com
to www.yourdomain.com
– you can’t use a CNAME
on a bare domain. You can set up a redirect with Apache if your DNS provider doesn’t do redirects.
You can also create a CNAME
for your CloudFront endpoint. I use cdn.maxmasnick.com
for this.
Getting your Jekyll site onto S3
There’s a great command line tool called s3cmd
that acts like rsync
for S3. It makes it easy to upload your Jekyll site onto S3, and after your initial upload s3cmd
will only upload file that have changed. If you’re on Mac, you can use Homebrew to install s3cmd
by running brew install s3cmd
.
I created a file called publish.sh
in my Jekyll folder so I can run jekyll && ./publish.sh
to publish to S3. publish.sh
only has one line in it:
s3cmd sync --delete-removed _site/ s3://www.maxmasnick.com/ --verbose
If you haven’t used s3cmd
before, you can set it up with your access keys by running s3cmd --configure
. You can get these access keys off the Security Credentials portion of the AWS website.
Jekyll configuration for CloudFront
To make it easy to serve my assets from CloudFront, I set up a custom Liquid filter:
module Jekyll
module AssetFilter
def cdn(input)
"#{@context.registers[:site].config['cdn']}/#{input}"
end
end
end
Liquid::Template.register_filter(Jekyll::AssetFilter)
Save this in _plugins/cdn.rb
off the root of your Jekyll site’s directory.
Then I added a CDN entry to my _config.yml
file. If I comment this line out, my assets will be served off of S3 (or localhost
if I’m running Jekyll locally).
cdn: http://cdn.maxmasnick.com
Whenever I want an asset to be served by the CDN, I pass it through this Liquid filter. For example, in my layout file I have: {% assign special = ‘{{ “assets/css/frameless.css” | cdn }}’ %}
<link rel="stylesheet" href="{{ special }}" />
Alternatives
I like hosting on S3 because it’s reliable (S3 is “designed to provide 99.999999999% durability and 99.99% availability of objects over a given year”) and cheap (I served more than 20,000 pageviews for less than $1 this January).
However, there are alternatives for hosting static sites. As I mentioned above, GitHub Pages is free and works pretty well. You can also host a static site on Heroku (for example, see this great post on hosting a static blog on Heroku + Google App Engine).
If you’re looking for alternatives to Jekyll, I wrote about the different options.
Comments? Please send me a message.