Subscribe via RSS

Setting up the new home for engineering.relateiq.com

Welcome to the new home for The Engineering Blog! When RelateIQ was younger, we managed a WordPress blog where we could push a lot of cool content. This worked well for us, and it enabled us to write about a bunch of cool things, from clojure and docker to how we launch features and how we turn ideas into reality.

However, as we grew it became clear that the customer-facing blog needed to become a top-level area of our website. After migrating over all of that content, the engineering team was presented with an opportunity to re-imagine the architecture of our engineering-specific content. This is the result of that work.

Overview

Inspired by the ease and simplicity of Github Pages, we migrated this blog to a static site driven by jekyll and octopress. Initially we deployed to github pages, but due to the lack of top-level https support for custom domains we switched to now deploy to S3 with CloudFront providing the necessary https support, using SNI.

We began by migrating all of our old engineering blog posts from WordPress to jekyll using their phenomenally well-documented import tool. After some post-processing and link munging to get old posts rendering using the new style, we had a statically generated site ready for deployment.

Setting it up

We want to deploy to S3, so first we created a public S3 bucket named engineering.relateiq.com, enable versioning and lifecycle management, and assign it a policy like the following:

{
  "Version":"2012-10-17",
  "Statement":[{
    "Sid":"PublicReadGetObject",
    "Effect":"Allow",
    "Principal": "*",
    "Action":["s3:GetObject"],
    "Resource":["arn:aws:s3:::engineering.relateiq.com/*"]
  }]
}

that is, permit everyone to read the files posted to this S3 bucket. We also need to enable static website hosting on this S3 bucket, as redirections to /index.html outside of the root directory do not work. According to their documentation, subdirectory requests do not return the default root object, event if a copy of index.html appears in the directory. Interestingly, this is the only reason to turn on static website hosting.

In order to make these files available to the general public, we then create a CloudFront web distribution with the correct origin domain name (which should point to your S3 bucket) and alternate domain names (in our case, engineering.relateiq.com). In order to support https to your custom domain, you need to modify the path of your certificate to start with cloudfront — to verify, you can use the aws cli tool as follows:

> aws iam get-server-certificate --server-certificate-name engineering.relateiq.com | jq -r .ServerCertificate.ServerCertificateMetadata.Path
/cloudfront/

At this point, we have everything but the actual assets! Make sure that octopress is installed through your Gemfile, and add the following to your _deploy.yml:

method: s3                                # How do you want to deploy? git, rsync or s3.
site_dir: _site                           # Location of your static site files.

bucket_name: YOUR_BUCKET_HERE             # Name of the S3 bucket where these files will be stored.
distribution_id: CLOUDFRONT_DEPLOY_ID     # Get this from your CloudFront page at https://console.aws.amazon.com/cloudfront/
remote_path: /                            # relative path on bucket where files should be copied.
region: us-west-2                         # Region where your bucket is located.
verbose: true                             # Print out all file operations.
incremental: true                         # Only upload new/changed files
delete: true                              # Remove files from destination which do not match source files.

at which point you could deploy using octopress.

bundle exec octopress deploy

Deploying

Being engineers of best practice, our blog is built and deployed without human intervention using our favorite CI solution. The overall work flow is wrapped in a pretty straight-forward Dockerfile:

FROM ruby:2.1

# Required for jekyll
RUN apt-get update && apt-get install -y nodejs

# Cache required gems for the build in an early layer
WORKDIR /tmp
ADD Gemfile /tmp/Gemfile
ADD Gemfile.lock /tmp/Gemfile.lock

RUN bundle install

ADD . /source
WORKDIR /source
RUN jekyll build
CMD octopress deploy

And our automated build process boils down to:

  • docker build --rm -t relateiq/engineering_blog:latest .
  • docker run --rm relateiq/engineering_blog:latest

    Where the second step needs to be executed from a machine (build agent) with permission to deploy to AWS.

Conclusion

Now that we have a good blog setup with continuous integration, deployment, and a sane content delivery mechanism, we can get back to work on products people love.

Don’t forget, we are always hiring!