Evan X. Merz

musician / technologist / human being

How to host a static site on AWS

In this post, I'm going to show you how you can put up a simple html webpage on AWS using resources that are usually free. It's probably the cheapest way to set up a website.

Prerequisites

There are a few things you need to do ahead of time.

  1. Sign up for AWS
  2. Create a webpage

For the first one, head on over to https://aws.amazon.com/console/ and create a new account.

For the second one, you will probably need to learn a little coding to make it happen, but I'll give you something simple to start with.

<!DOCTYPE html>
<html>
  <head>
    <title>My Webpage</title>
  </head>
  <body>
    <main>
      <h1>My Webpage</h1>
      <p>
        This is a simple html webpage hosted on AWS S3 and AWS Cloudfront.
      </p>
      <p>
        This was built based on <a href="https://evanxmerz.com/post/how-to-host-a-static-site-on-aws" target="_blank">a tutorial at evanxmerz.com/post/how-to-host-a-static-site-on-aws</a>.
      </p>
    </main>
  </body>
</html>

There are some optional prerequisites that I'm intentionally omitting here. If you want to host your site on your own domain, then you'll need to purchase that domain from a domain registrar, such as AWS Route 53. Then you would also need to get an SSL certificate from a certificate authority such as AWS Certificate Manager.

Create a public S3 bucket

For your site to exist on the internet, it must be served by a computer connected to the internet. To make this possible, we need to upload your html file to "the cloud" somehow. Don't worry, "the cloud" is simply a marketing term for a web server. In this tutorial, our cloud storage service is AWS S3.

First you need to create a bucket.

  1. Browse to the AWS S3 service
  2. Click "Create Bucket". A bucket is a container for files. You might use a different bucket for each of your websites.
  3. Enter a name for your bucket. I name my static site buckets after the site they represent. So empressblog.org is in a bucket called empressblog-org. I named my bucket for this tutorial "static-site-tutorial-1-evanxmerz-com" because I am going to connect it to static-site-tutrial-1.evanxmerz.com.
  4. Next, select the AWS region for your bucket. The region is not really important, but you must write down what you select, because you will need it later. I selected "us-west-1".
  5. Under "Object Ownership" select "ACLs enabled". This will make it easier for us to make this bucket public.
  6. Under "Block Public Access settings for this bucket", unselect "Block all public access", then click the checkbox to acknowledge that you are making the contents of this bucket public.
  7. Then scroll to the bottom and click "Create Bucket".

Next, you need to allow hosting a public website from your bucket.

  1. Locate your bucket in the bucket list in S3, then click it.
  2. You should now be looking at the details for your bucket. Click the "Properties" tab, then scroll down ti "Block all public access" and click "Edit".
  3. Click "Enable", then under "Index document", enter "index.html". Then click "Save changes".
  4. Click the "Permissions" tab for your bucket. Scroll down to "Access control list (ACL)" and click "Edit". Next to "Everyone (public access)", click the box that says "Read". Then click the box that says "I understand the effects of these changes on my objects and buckets" and click "Save changes".

Create your index page

This step assumes that you have already created an html page that you want to make public. You can also upload other pages, css files, and javascript, using this same procedure.

  1. Find the "Objects" tab for your bucket on S3.
  2. Click "Upload".
  3. Click "Add files".
  4. Browse to your index.html
  5. Scroll down to the "Permissions" accordion and expand it.
  6. Click "Grant public-read access" and the checkbox to say that you understand the risk.
  7. Then click "Upload".

Now your page is on the internet. You can go to the objects tab for your bucket, then click on your file. That should display a link called "Object URL". If you click that link, then you should see your page. My link is https://static-site-tutorial-1-evanxmerz-com.s3.us-west-1.amazonaws.com/index.html.

Why to make a CloudFront distribution

Now you have seen your file on the web. Isn't that enough? Isn't this tutorial over? No. There are several problems with using S3 alone.

  1. Your files will be served from S3, which is not optimized for worldwide distribution. Your files have a home on a server in the region you selected. If that region is in the US, then people in Asia are going to have a much slower download experience.
  2. Your site will not work if there are errors. Your index page works fine, but what happens if you entered an incorrect link, and someone ends up at indec.html? You will get a nasty error message from AWS, rather than being redirected to a page on your site.

The final problem is the URL. This can be solved by setting up a domain in Route 53, but it's much wiser to set up a CloudFront distribution, then connect your domain to that.

Set up a CloudFront distribution

AWS CloudFront is a Ccontent Distribution Network (CDN). A CDN is a network of servers all over the world that are close to where people live. So people in Asia will be served by a copy of your page on a server in Asia.

  1. Find the CloudFront service on AWS.
  2. Click "Create distribution".
  3. In the "Origin domain" field you must enter your S3 bucket's Static Website Hosting Endpoint as the CloudFront origin. You can find this on the "Properties" tab of your S3 bucket. So for me, that was "static-site-tutorial-1-evanxmerz-com.s3-website-us-west-1.amazonaws.com".
  4. Then scroll all the way down to "Alternate domain name (CNAME)". This is where you would enter a custom domain that you purchased from AWS Route 53 or another registrar. For instance, if you want to set up your site on mystore.com, then you would enter "*.mystore.com" and "mystore.com" as custom domains. I entered "static-site-tutorial-1.evanxmerz.com" as my custom domain because that's where I'm putting up this tutorial.
  5. Then go to the "Custom SSL certificate" field. If you do not have your own domain, then you can ignore this. But if you have your own domain, then you will need your own SSL certificate. The SSL certificate is what enables private web browsing using the "https" protocol. Go set up a certificate using AWS Certificate Manager before setting up CloudFront if you want to use a custom domain.
  6. Finally, click "Create distribution"

Then you need to modify the distribution to act more like a normal web server. So we will redirect users to index.html if they request an invalid url.

  1. Find your distribution on CloudFron and click it.
  2. Click the "Error pages" tab.
  3. Click "Create custom error response".
  4. Under "HTTP error code" select "400: Bad Request".
  5. Under "Customize error response" click "Yes".
  6. Under "Response page path" enter "/index.html".
  7. Under "HTTP Response code" select "200: OK".
  8. Click "Create custom error response".
  9. Repeat these steps for 403 and 404 errors.

Then, if you have a custom domain, you need to go to AWS Route 53 and enable it.

  1. Go to Route 53 and select the hosted zone for your domain.
  2. Click "Create record".
  3. Create an A record for your domain or subdomain.
  4. Under "Route traffic to" click "Alias".
  5. Click "Alias to CloudFront distribution" and select your distribution.
  6. Click "Create records".

Now if you visit your custom domain, you should see your page. Here's mine: https://static-site-tutorial-1.evanxmerz.com/

Congratulations!

Congratulations! You've erected your first website using AWS S3 and AWS CLoudFront! Let's review the basic architecture here.

  1. Files are stored in a cloud file system called AWS S3.
  2. Files are served by a Content Distribution Network (CDN) called AWS CloudFront.
  3. Optionally, domains are routed to your CloudFront distribution by AWS Route 53.
  4. Optionally, CloudFront uses an SSL certificate from AWS Certificate Manager.

This is about the simplest and cheapest architecture for hosting a fast static site on the internet.

It's important to note that this is also the simplest way for hosting ANY static site. If you generated a static site using React, Gatsby, or Next, then you could host them in the same way.

IT's also important to note that this architecture fails as soon as you need to make decisions server side. This architecture works fine for websites that are frontend only websites, where you don't interact with private data. Once you need private data storage, an API, or custom logic on a page, then you will need a server in some variety. There are multiple solutions in that case, from the so-called "serverless" AWS Lambda, or the more old-fashioned AWS EC2, which is simply a server farm.

But you are now ready to start exploring those more complex options.