AWS S3 hosted blog using Jekyll and Ansible
I have been running a Gradle & Groovy related blog for an about a year using Wordpress. Wordpress is a great platform, but comes with its own risks and drawbacks:
- More maintenance (needs a server to run)
- Prone to hacking
- Slower than static blog
- Higher operational costs
I’ve decided to host a simple, static blog using S3 static site feature. I’ve also have chosen to use Jekyll as an engine to help me keep my static website maintainable.
Installing Jekyll on macOS
gem install jekyll bundler
cd ~/blog/deploy.live
jekyll new deploy.live
cd deploy.live
jekyll serve
You can now view your blog engine running by accessing http://localhost:4000.
Next:
- Personalise
_config.yml
for your own blog. - Append
_config.yml
withdestination: _deploy
- Add a new blog post by creating a file in the
_posts
directory that follows the conventionYYYY-MM-DD-name-of-post.ext
.
Configure AWS S3
Configure S3 Bucket
- Log-in to your AWS account and open S3.
- Click Create bucket
- Provide DNS compatible bucket name, so for me it was deploy.live
- Select the region you are expecting the most traffic in
- Click Next
- I will add tags for this bucket to be able to track my S3 cost for this website
- Click Next
- Grant Global Read permissions on the bucket. Manage public permissions > Everyone > Objects > Read
- Click Next and Create a Bucket.
Apply S3 Bucket policy
- Generate Bucket policy using this URL http://awspolicygen.s3.amazonaws.com/policygen.html
- Select S3 Bucket Policy
- Select Effect Allow
- Select Pricinpal *
- Select AWS Service Amason S3
- Select Actions GetObject
- Specify ARN as per Amazon S3 > Bucket Name > Permissions > Bucket Policy. e.g. arn:aws:s3:::deploy.live, append it with /* e.g. arn:aws:s3:::deploy.live/*
- Generate Policy
- Apply Policy to Bucket Policy
{ "Version": "2012-10-17", "Id": "Policy1490566913841", "Statement": [ { "Sid": "Stmt1490566176363", "Effect": "Allow", "Principal": "*", "Action": "s3:GetObject", "Resource": "arn:aws:s3:::deploy.live/*" } ] }
Configure IAM for Ansible API access
- Open IAM
- Open Users tab
- Click Add User
- Specify user name e.g. ansible_s3
- Select Access Type as Programatic access
- Click Permissions
- Select Attach existing policies directly
- Select AmazonS3FullAccess
- Click Review
- Click Create user
- Download credentials as .csv
Configure AWS CLI
pip install --upgrade --user awscli
aws configure
AWS Access Key ID [None]: <Enter Access Key ID here>
AWS Secret Access Key [None]: <Enter Secret Access Key here>
Default region name [ec-west-2]: eu-west-2 (I am hosting in London S3 Region)
Default output format [None]: text
Write Ansible deploy script
Prerequisite: installed ansible
I am strong believer in ansible roles, therefore even for the most simpliest playbooks, I will be creating a distinct roles. For this very project I will have the following structure:
- roles
- deploy-jekyll-s3
- defaults
- main.yml (variables specific to your bucket and jekyll directory)
- tasks
- main.yml (generic build and deploy script)
- defaults
- deploy-jekyll-s3
- main.yml
where roles/deploy-jekyll-s3/defaults/main.yml is as follows:
jekyll_blog_root_dir: /Users/dmitrilerko/blog/deploy.live/deploy.live
bucket_name: deploy.live
and roles/deploy-jekyll-s3/tasks/main.yml builds and deploys S3 using AWS CLI:
---
- name: build jekyll
command: jekyll build
args:
chdir: "{{ jekyll_blog_root_dir }}"
- name: upload blog to S3
command: "aws s3 cp {{ jekyll_blog_root_dir }}/_deploy/ s3://{{ bucket_name }}/ --recursive"
Full ansible script can be found here: https://github.com/dmitri-lerko/ansible-jekyll.
Now lets run ansible playbook.
ansible-playbook main.yml
PLAY [upload deploy.live to S3] ************************************************
TASK [setup] *******************************************************************
ok: [localhost]
TASK [deploy-live-s3 : build jekyll] *******************************************
changed: [localhost]
TASK [deploy-live-s3 : upload blog to S3] **************************************
changed: [localhost]
PLAY RECAP *********************************************************************
localhost : ok=3 changed=2 unreachable=0 failed=0
Test your brand new static website http://deploy.live.s3-website.eu-west-2.amazonaws.com/