by Nicholas Vincent-Hill
How to build and deploy a beautiful personal static site with AWS S3, Route53, and CloudFront 🔥
This is a step-by-step guide to creating a responsive static billboard/portfolio site, deploying it to the web with AWS, and serving it securely with HTTPS.
This guide is designed for beginner and intermediate-level software engineers and web developers looking for an easy way to create a personal site for cheaper than paid-services like SquareSpace or other site-builders. Basic technical requirements include a knowledge of HTML/CSS/JS, npm, and Git (the advanced site creation process uses Gatsby.js which requires knowledge of React.js and GraphQL).
The only economic requirements are AWS Route53 hosted zone fees ($0.50/month) and the cost of acquiring a domain (I rented nickvh.tech for $25 for five years from get.tech). Netlify is a free option as well. The estimated time commitment is four to five hours depending on individual skill and experience.
This guide will enable you, the developer, to control all aspects of the design, development, and deployment of your site.
Step 1 — Create your personal site (the easy way or the hard way)
Here’s the easy way: go here and pick out a fully responsive, super customizable, and 100% free (under the Creative Commons) HTML/CSS/JS template. Download it and customize/build on it until you love it!
package.json by calling
npm init in the root directory of your chosen project. Make sure to
git init, add all non-public information to
.gitignore, and write great commit messages.
Here’s the hard way: use Gatsby.js to build a blazing fast static site and PWA from scratch. This isn’t a Gatsby.js tutorial (plenty of great tutorials can be found here) and requires React.js and GraphQL knowledge. A number of starter templates can be found here (I used the “strata” HTML5UP template as a jumping off point for nickvh.tech).
Test and develop your website until you are happy with it and want to share it with the world. We will be building a continuous development pipeline with either Grunt or the
gatsby-plugin-s3 plugin later so future revisions/deployment will be quick and easy.
Step 2 — Get a domain
Sites like https://get.tech or https://www.namecheap.com offer very compelling prices for domains. I waited for a promotion and got https://nickvh.tech for $25 for five years. Alternatively buy a .dev domain from Google.
Step 3 — Create an AWS account
Create an AWS account. This step is fairly straightforward. New accounts get free services for a year — outlined here. This requires you to have an active credit card on file with AWS. Be aware of the security implications and do not accidentally push your AWS credentials to the public web.
Step 4 — Configure AWS S3 buckets
Amazon Simple Storage Service (Amazon S3) is an object storage service that offers industry-leading scalability, data availability, security, and performance. This means customers can use it to store and protect any amount of data for a range of use cases, such as websites, mobile applications, backup and restore, archive, enterprise applications, IoT devices, and big data analytics.
AWS S3 is where your static site will live; there are a few things to do in order to configure this correctly.
First create a bucket; AWS S3 and Route53 only work correctly if your bucket name and domain name match precisely — name your bucket mysite.domain (i.e. nickvh.tech). Make sure to set permissions correctly; the public should be able to read from the bucket but not write to it.
Next navigate to “Properties” and configure AWS S3 to statically serve
index.html (see below).
Create a bucket (also public read access enabled) named www.mysite.domain (www.nickvh.tech in my case) and redirect to the main bucket address (see below).
aws-keys.json in the root directory of your project:
Here’s a guide to finding your AWS access key ID and Secret key.
Remember to add
aws-keys.json to your
.gitignore! One of my students accidentally pushed their AWS credentials to Github, was programmatically attacked, and incurred ~$1.3k in charges in a few hours.
Step 5— Upload your site to AWS S3 with Grunt or
If you choose the easy way to create your site, you can use Grunt to upload your completed site files to your AWS S3 bucket.
npm install grunt grunt-aws-s3 --save-dev
Add this to the scripts object of your
"deploy": "grunt deploy"
Now whenever you want to deploy a new production version of your site just execute
npm run deploy. This will only POST/PUT files to AWS S3 that have changed — reducing the number of requests you need to pay for (new AWS accounts get 2,000 free PUT requests/month for the first year).
Alternatively — if you built your site with Gatsby.js, forget Grunt and just use
gatsby-plugin-s3 for static site deployment. I wrote a npm script
npm run ship which builds the production bundle and uploads it to AWS S3 -
gatsby build && gatsby-plugin-s3 deploy. The code for my Gatsby site can be found here.
Step 6— Create a distribution with AWS CloudFront
Amazon CloudFront is a fast content delivery network (CDN) service that securely delivers data, videos, applications, and APIs to customers globally with low latency, high transfer speeds, all within a developer-friendly environment.
Create a new CloudFront distribution (loosely following these AWS docs). Make sure to specify Alternate Domain Names (CNAMEs) correctly and request a custom SSL certificate to enable HTTPS.
Also specify the Default Root Object as
Click Create Origin to link your S3 bucket to your CloudFront Distribution. Specify Origin Domain Name as
YOUR_S3_BUCKET_NAME.s3.amazonaws.com. Do not restrict bucket access.
Create a new behavior and set Viewer Protocol Policy to “Redirect HTTP to HTTPS.”
You can also customize error responses — I redirect 404 errors to a custom 404.html page.
Step 7— Redirect traffic to your new CDN with AWS Route53
Amazon Route 53 is a highly available and scalable cloud Domain Name System (DNS) web service. It is designed to give developers and businesses an extremely reliable and cost effective way to route end users to Internet applications by translating names like www.example.com into the numeric IP addresses like 192.0.2.1 that computers use to connect to each other.
Now we need to connect your domain name (mysite.domain) to your CloudFront distribution so that when a user makes a request to your domain they receive your
index.html and the rest of your static site (by hitting your newly created CDN).
Open the AWS Route53 console and create a new Hosted Zone. Here’s some helpful AWS docs to get you started.
Make sure to update the name servers for the domain you bought. Use the method provided by the registrar for the domain you purchased to change the name servers for the domain (use the four Route53 name servers found in the NS — Name server record set).
Create a new record set and set the alias target to your AWS CloudFront distribution (see below). Make sure to name it yoursite.domain.
Changes to domain name servers take time to propagate so make sure to wait a few minutes before attempting to access your site via your new domain.
Step 8— Bask in the glory of your newly deployed site! (or troubleshoot problems)
You did it! Enjoy your beautiful new portfolio site deployed to the world wide web. Check out my site I built and deployed using this tech stack; I wired up the contact form with AWS Lambda using this guide.