Jekyll is, no doubt, one of the best blog-aware static site generators available out there. While hosting the Jekyll site on GitHub Pages seems to be a very common practice, there are situations where we need the code source-controlled privately. GitHub charges for private repositories. BitBucket is the next go-to choice.
If the code is stored on BitBucket, GitHub pages may not be a possible hosting option, which brings us to Amazon Web Services. This gist is about having the code on BitBucket, having Wercker build the site and deploy it to AWS S3, and then having CloudFront deliver the site.
Here's a gist of how this is done:
- You add data to the code (basically Markdown files) as posts. These changes are pushed to BitBucket, the source control provider for the site.
- Wercker (a Docker-based continuous delivery platform) is triggered as soon as there's a push; it picks up the code from BitBucket.
- Wercker has two pipelines,
build
anddeploy
, which, of course, builds the site using Jekyll (on a Ruby box), and deploys it to the AWS S3 bucket that hosts the site. - CloudFront is the CDN that delivers the contents of the S3 bucket.
- Amazon's Certificate Manager provides the SSL certificate that encrypts your connection to this site.
Now to the detailed picture (Source: https://resume.ramiyer.me/making.html).
This document has been created for Windows 10 Pro. While building the site locally is not entirely necessary, it helps when you need to build the site locally to test out its working.
Enable the Linux Subsystem on Windows feature, and install the necessary components required to be able to build sites using Jekyll. While there may be seemingly less-complicated ways to set up Jekyll on Windows without WSL, setting it up with WSL is much less hassle. This post by Dave Rupert helps a great deal with it. Also, some of the Nokogiri binaries need to be installed.
There are really many ways to do this, the easiest way being to fork one of the existing templates and going forward by simply customising the content.
I wanted to build an uncomplicated site, so I used the Skeleton boilerplate to build the site. There are two ways to go forward from here:
- Use the
jekyll new
command to get the basic Jekyll site, and then add the Skeleton components. - Use the Skeleton Framework for Jekyll, rebuild
index.html
and move forward.
I chose the latter. Sure, I still had to make a few changes to optimise the site, but hey, what's life without adventures?
Now comes the creation of the Amazon S3 bucket that would host the site contents:
- Go to the S3 Management Console. The prerequisite to this is that you have an AWS account.
- Click on Create bucket.
- Enter the name of the bucket exactly as the URL to host the site; I entered
resume.ramiyer.me
(because I want the site to be live at http://resume.ramiyer.me). I'll refer to this asyour.bucket.name
, going forward. - Select the region and select Next. Any region would do, since we're going to use CloudFront anyway.
- In the screen that appears next, click on Next, unless you want logging or versioning configured.
- In the next screen, under Manage public permissions, select Grant public read access to this bucket and click Next.
- Review the settings and create the bucket.
- Once the bucket is created, open the bucket and go to the Permissions tab. Click on Bucket Policy.
- Enter the following JSON in the editor area:
{ "Version":"2012-10-17", "Statement": [ { "Sid":"PublicReadForGetBucketObjects", "Effect":"Allow", "Principal": "*", "Action": [ "s3:GetObject" ], "Resource": [ "arn:aws:s3:::your.bucket.name", "arn:aws:s3:::your.bucket.name/*" ] } ] }
- Save the configuration.
That completes the bucket setup part.
Wercker needs to authenticate itself to push content to the S3 bucket. We'll set up an IAM user for this.
- Go to the IAM console.
- Go to the Users tab and click Add user.
- Add a User name.
- Select the box against Programmatic access, and proceed to add permissions.
- In the permissions screen, select Add existing policies directly.
- Click Create Policy.
- In the next screen, click on Select against Create Your Own Policy.
- Enter a Policy Name, like,
AmazonS3-JekyllResume-ReadWrite
. Enter a description to help you remember what you created the policy for. - In the Policy Document area, enter:
{ "Version": "2012-10-17", "Statement": [ { "Sid": "ResumeBucketWrite", "Effect": "Allow", "Action": [ "s3:DeleteObject", "s3:GetObject", "s3:PutObject" ], "Resource": [ "arn:aws:s3:::your.bucket.name/*" ] }, { "Sid": "ResumeBucketList", "Effect": "Allow", "Action": [ "s3:ListBucket" ], "Resource": [ "arn:aws:s3:::your.bucket.name" ] } ] }
- Search for AmazonS3-JekyllResume-ReadWrite, select it, and proceed to review.
- Click on Create user.
- In the next screen, you'll get the Access key ID and Secret key. Note these down in a safe place.
This is a little tricky part, since we have outdated documentation surrounding it, on the Internet, for now. New users will have a hard time hunting around to get this information. The reason for this is that Wercker apparently changed the underlying system, by introducing Docker. This has brought in some changes to workflows, which obviously brings in subsequent user-facing changes.
- Go to the Wercker home page.
- Login with BitBucket.
- Create a new application in Wercker by selecting the BitBucket repository where the code is stored.
- At this point, it should ask you to add a
wercker.yml
file; it would give the code. Ignore that for now. - In your code repository on BitBucket, create a new file at the root, called
wercker.yml
. - Add the following code to it (careful with the spaces and indentation; YAML is a little fussy):
box: ruby build: steps: - bundle-install - script: name: generate site code: bundle exec jekyll build --trace deploy: steps: - s3sync: key-id: $AWS_ACCESS_KEY_ID key-secret: $AWS_SECRET_ACCESS_KEY bucket-url: $AWS_BUCKET_URL source-dir: ./_site/ opts: --add-header=Cache-Control:max-age=3600
- Back in the Wercker screen, you should have a link that says, 'I already have a wercker.yml, trigger a build now.' Go ahead and click that to start the pipeline. Ensure the
build
part completes successfully. The code would not be deployed to S3 just yet. - You should see a tab on the screen, called Environment. Click on it.
- Add the Amazon Access key ID, the Secret key, and the bucket name here. Ensure to make both they keys protected. The key names should exactly match the variable names in the
deploy
part ofwercker.yml
(without the leading$
). Also, note thes3://
before the bucket name. That's important, too.AWS_ACCESS_KEY_ID : AKIAJ3R2K6NQLKVKXIJV AWS_SECRET_ACCESS_KEY : MpyMJBqY3Gq+5Jx7xGjZkO8/CqURMUefXDA6o59o AWS_BUCKET_URL: s3://your.bucket.name
- Now, go to the Workflows tab of the Wercker app screen.
- In the Pipelines section, click on Add new pipeline.
- In the Name and YML Pipeline name fields, enter
deploy
. - Click on Create.
- Back in the Workflows screen, click the
+
next tobuild
. - At the Execute pipeline dropdown, select
deploy
, and click Add. - Go ahead and make a push from your local repository after making a small change to the code. Come back to the Runs tab on Wercker, and you should see the build happen, immediately followed by deployment.
- Once the build and deployment complete, refresh the S3 bucket to see the site contents appear!
Your site should be live already, and you can access it using the bucket's endpoint URL. To find that URL, you can open your bucket, go to the Properties tab, click on Static website hosting. The URL mentioned there is the endpoint. However, there are two reasons I chose to go with CloudFront as well.
- CloudFront makes the content delivery fast, throughout the world. Granted, this is not an issue for small static sites, which brings us to the next point.
- You can have an SSL certificate, issued by Amazon for free, tagged to your site to encrypt the connections to the site.
Let's first proceed with getting ourselves an SSL certificate. This is optional. I like to encrypt connections to my sites, so I chose to go with it.
- Open the AWS Certificate Manager console.
- Click on Request a certificate.
- Enter the domain (or subdomain) name, which should be the URL where you want to host the site, as well as the name of the bucket,
your.bucket.name
. The prerequisite here is that you have sufficient authority on your domain, including the ability to receive admin emails. An email would be sent to the admin address of the domain for verification. - Click on Review and request.
- Go to the mailbox configured with the admin address of your domain. You should've received an email to approve the certificate request. Go ahead and approve it after verifying the details.
- Refresh the ACM screen, and you should see the certificate that was just issued.
It's now time to set up the CloudFront distribution.
- Go to the CloudFront console.
- Click on Create distrubution.
- Click on Get started in the Web section.
- Clicking in the Origin Domain Name field should drop down a few values, the S3 bucket you created for the site being one of them. Select it.
- In the Default cache behaviour settings section, select the radio button against Redirect HTTP to HTTPS.
- Scroll down to Distribution settings, and enter the name of your bucket (and the subdomain URL of your site),
your.bucket.name
, in the Alternate domain names field. - Select Custom SSL certificate, and select the certificate you just created, from the dropdown.
- Enter
index.html
in the Default Root Object field. - Go ahead and click on Create Distribution.
- Wait. The process of creating the distribution can take anywhere from ten minutes to a few hours.
- Once the Status says
Deployed
, and State saysEnabled
, the CloudFront distribution should be live. Note down the Domain name value for the distribution; it should be something likeqdw3xburi4bfy.cloudfront.net
.
Your site should now be accessible using the domain name (qdw3xburi4bfy.cloudfront.net
) as well. But we want it to be accessible at your.bucket.name
. This takes some DNS configuration.
- Log into the DNS console of your DNS provider (your domain provider in most cases).
- Create a new CNAME record, with
your.bucket.name
in the Name field, andqdw3xburi4bfy.cloudfront.net
in the Points to field. - Save the zone file.
- Wait. DNS modifications may take between a few seconds and several hours to propagate.
That brings us to the end of the setup. The site should be all set to be accessed using https://your.bucket.name
. The browser should show the secure connection indicator as well, with the certificate showing, Verified by Amazon.
Would love to see a version of this gist without Wercker