We use Jekyll, AWS S3, and CloudFlare to create a personal blog or hobby site.
Prerequisites
Install ruby
, make
, an AWS admin account, a CloudFlare account, AWS CLI, and then configure AWS CLI with your AWS credentials.
Create the default Jekyll website
-
The website I will create is
therailtrailster.com
. Anywhere you see that website, replace it with your own. -
Somewhere in your home directory, create a directory with the name of your website.
cd ~/Dev/my_websites mkdir therailtrailster.com cd therailtrailster.com
-
Create a Jekyll website. I’m using the Jekyll Quickstart here. I like to use Makefiles and command lines wherever I can. Create a
Makefile
with the following commands and then executemake init
. If you prefer, enter the commands directly into your shell terminal window.init : gem install jekyll bundler if ! test -d "jekyll" ; then \ jekyll new jekyll; \ fi ; \ cd jekyll && \ gem install json && \ bundle install
We only create the Jekyll site if it does not already exist. This lets us run
make init
again later if something in ruby or gem gets messed up. -
Start the dev server. Add the following to your
Makefile
and execute the commandmake dev
.dev : cd jekyll && \ bundle exec jekyll serve --livereload
-
Browse to http://localhost:4000/ to view your new website.
AWS S3
We will use AWS S3 to store your webite’s files. It’s super cheap for a small website. For this exercise, we will exclusively use the AWS CLI to create your website.
-
Create an S3 bucket with your website domain as the bucket name. Don’t forget to replace
therailtrailster.com
with your website name. Choose an approprite region for your purposes.WEBSITE_NAME = therailtrailster.com BUCKET_NAME = $(WEBSITE_NAME) AWS_REGION = us-east-1 aws-create-bucket : aws s3api create-bucket --bucket $(BUCKET_NAME) --region $(AWS_REGION)
Run
make aws-create-bucket
. -
Configure the bucket for static website hosting.
aws-configure-static-website : aws s3 website s3://$(BUCKET_NAME)/ \ --index-document index.html \ --error-document 404.html
Run
make aws-configure-static-website
. -
Set the bucket permissions. Create a new json file named
bucket-policy.json
with the following contents, replacingtherailtrailster.com
with your website name:{ "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Principal": "*", "Action": "s3:GetObject", "Resource": "arn:aws:s3:::therailtrailster.com/*" } ] }
-
Add the following target to your Makefile and run
make aws-set-bucket-permissions
. The first command allows all public access and the second shuts down all except read using the policy you created above.aws-set-bucket-permissions : aws s3api put-public-access-block --bucket $(BUCKET_NAME) --region $(AWS_REGION) \ --public-access-block-configuration "BlockPublicAcls=false" aws s3api put-bucket-policy --bucket $(BUCKET_NAME) --region $(AWS_REGION) \ --policy file://bucket-policy.json
-
Set the CORS configuration for your bucket so that it can service cross-origin requests. Create a new json file named
cors.json
with the following contents:{ "CORSRules": [ { "AllowedOrigins": ["*"], "AllowedHeaders": ["Authorization"], "AllowedMethods": ["GET"], "MaxAgeSeconds": 3000 } ] }
-
Add this target to your Makefile and run
make aws-set-cors-configuration
.aws-set-cors-configuration : aws s3api put-bucket-cors --bucket $(BUCKET_NAME) --region $(AWS_REGION) \ --cors-configuration file://cors.json
-
Add a command to generate the production version of your website.
prod : JEKYLL_ENV=production cd jekyll && bundle exec jekyll build
Terminate the dev server and generate the production version with
make prod
. -
Publish the default Jekyll website by uploading the files in
jekyll/_site
to your S3 bucket.publish : aws s3 sync --quiet --delete jekyll/_site s3://$(BUCKET_NAME)
Run
make publish
. -
Test the AWS S3 website you just created. Add the following to your Makefile:
AWS_ENDPOINT = http://$(BUCKET_NAME).s3-website-$(AWS_REGION).amazonaws.com aws-test-endpoint : open $(AWS_ENDPOINT)
Run
make aws-test-endpoint
. You should see exactly what you saw with the dev server at http://localhost:4000/. This is the default Jekyll website before we’ve added our own files.If this didn’t work, check the endpoint by going to your bucket on S3 and selecting the Properties tab. You’ll see the correct endpoint in the section Static website hosting. You can click the link to open your new website.
Make a note of this S3 endpoint (or just leave this page open) because you will need it later.
-
You have now succeeded in creating and publishing a static website. But you can only access it with this clumsy AWS endpoint. We’ll fix that next. One of your choices is AWS Route 53 and CloudFront. Route 53 costs a minimum of $0.50 per month per website. That’s a pretty good deal for a small operation. But we can do even better using Cloudflare.
CloudFlare (your custom domain name, security, and world-wide cache)
With CloudFlare, we will enable your custom domain name, add DNS security, and provide world-wide cachine of your site.
-
Login to your CloudFlare account. Find and click Websites in the side panel. Click the
button. Enter your new domain name and click . -
In Step 1 of 3, scroll down and select the Free option and click
. -
We will shortly add the only DNS record you need for this site. Unless you know you need them, don’t import DNS records from your registrar.
-
Create a domain alias for your S3 endpoint. Click the
button. Select CNAME for the Type. Enter @ into the Name field. Paste your S3 endpoint into the Target field. Assure that Proxy status is checked. -
CloudFlare helpfully tells you that your domain is an alias of the s3 endpoint and has its traffic proxied through Cloudflare.
-
Click the
button and . -
On the next page, Change your nameservers, Cloudflare shows you what your nameservers should be. Replacing a domain’s nameservers is different for each domain registrar, but it’s generally pretty easy to do. Login to your domain registrar and replace the existing nameservers with the nameservers shown on this page. Click
. -
Wait an unkown number of minutes (at least 5, maybe more) for the nameservers and new DNS record to propogate. Then visit your custom domain name in the browser. If you waited long enough and we did everything right above, you should see the default Jekyll site that we built in AWS S3.
If you have a problem, see the Troubleshooting section of Hosting a static website: Amazon S3 + Cloudflare.
-
The next page is oddly called the Quick Start Guide. But we’ve gotten started already. I think they mean it’s the quick start for configuring your domain settings for better security.
You can finish this up on your own. Turn on Automatic HTTPS Rewrites, Always Use HTTPS, and DNSSEC.
Oh happy day! You have a brand new website!
This is the pattern you will now follow:
-
Replace the default Jekyll website with your own content. Choose and apply a Jekyll theme. Install and use plugins.
-
Preview your changes by running the dev server (
make dev
) and browsing to http://localhost:4000/. -
Loop on 1. and 2. until you’re happy with your changes.
-
To publish your changes, terminate the dev server and run
make prod publish
.
Easy!
Credits
Thank you to Lambos Petrou for his post Migrate to AWS - Make a static website using S3, Cloudfront and Route 53. It helped me create a static website with AWS S3.
Thank you to Jaroslav Hranička for Hosting a static website: Amazon S3 + Cloudflare.