Personal website with password protection

After numerous attempts at finding a cheap and easy solution to making a password protected static website, I finally have settled my mind on one! Before going over the solution let me go over the requirements that I had in my mind for the website:

  • Cheap
  • Static and blog-aware
  • Password protection on a part of the website
  • Smooth and easy workflow to move content from private part to public
  • Preferably, an automatic CI/CD

I tried multiple solutions such as setting up Heroku dynos, CloudCanon etc. None of the solutions satisfied all the requirements until I found this option:

GitHub + Jekyll + Makefile + AWS S3 + AWS Lambda

Let me paint a high level picture of how the setup looks like:

Two GitHub Repositories

Website content is split into two parts: public and private repositories. The public repository works like any other static website hosted on GitHub.

It contains all the jekyll build material and public posts. Private repository only contains posts that are private.

Public Repository Hosting

The public repository gets hosted on GitHub pages as any other static website. This takes care of the public part of the website.

Setting up private part is slightly complex but it’s a one-time effort. I’ll try to provide a high-level overview how that works.

Password Protection

The private content is hosted in an AWS S3 bucket which only allows AWS CloudFront to read the contents. I then setup AWS Lambda that runs when a viewer tries to read content via CloudFront distribution. Here’s a step-by-step tutorial on how to set up S3 and CloudFront.

Building Private Website

In order to build the private website, we are going to need both the public and private repositories. After cloning the public repository, we create a directory named <public_repo>/_posts_private and clone the private repository in it. Yeah, we could have used git submodules. But, given that the _posts_private should point to a private repository, if we use submodules, it will break GitHub’s CI/CD for the public website. We don’t want that to break. So, we manually clone the private repository inside _posts_private folder. The magic happens inside the Makefile.

Command Action
make _site_private Build private website
make _site_public Build public website
make serve_private Build and run private website locally
make serve_public Build and run public website locally
make sync Update private repository on S3
make clean Clean directory

After running make sync, we can see that the private part of the website is published to S3/CloudFront. If you try to access it via CloudFront URL, you’ll see that a dialog pops up asking for your username and password.

Tying Private and Public Repositories Together

Ok so we now have public part of the website working on GitHub pages and the private part of the website working on S3/CloudFront. We are now going to tie them together using a custom domain name! Domain names are pretty cheap (10-20$/yr). So, what I did was I bought this domain name and configured the DNS such that harshad.me points to the GitHub URL and personal.harshad.me points to cloudfront URL. Here’s how the DNS entries look:

Name Type Resolves to Comment
harshad.me A 185.199.108.153 GitHub IPs
    185.199.109.153  
    185.199.110.153  
    185.199.111.153  
aws_verifier_key.personal CNAME aws_verifier_val.aws.  
personal CNAME CloudFront URL  

…and there you go! At the end of this, I had my public site live at - http://harshad.me and the private part of the site is live at https://personal.harshad.me!