Mock browser with S3 logo

Low-cost Website Hosting with Amazon S3

May 16, 2016

A while ago, I decided to ditch the traditional web hosting services (like HostGator and Bluehost) in favour of Amazon’s Simple Storage System (S3). I was on a quest to find the most inexpensive solution to host my portfolio website. Instead of paying a flat rate of $3-$6 per month, S3 charges by usage and starts at as little as 3 cents per GB per month. The only catch is that it lacks the usual back-end services that are provided with a hosting package, such as WordPress, MySQL database and email accounts. For static websites (purely front-end) like a marketing site or a Jekyll blog, hosting on S3 is cost-effective with excellent up-time and minimal maintenance.

Assuming you’re comfortable with basic web development, this article will show you how to host a static website on Amazon S3 under a custom domain while using s3_website for painless deployment.

Setting up a S3 Bucket

First of all, let’s create an empty S3 bucket to store your website files.

  1. Sign up for an Amazon Web Services account.
  2. Head over to the AWS management console and navigate to S3.
  3. Click Create Bucket and name the bucket the URL of your website (e.g., www.youdomain.com) so you can link it with your domain later.
  4. Under Static Website Hosting section on the right-hand pane, tick Enable website hosting. Also, keep note of the Endpoint URL, to be referenced later.

    S3 bucket policy
    Enabling website hosting for a bucket in the Properties pane.
  5. Under Permissions section, click Add bucket policy. Copy and paste the policy code from below, which allows the public to be able to read the files you’ll put into the bucket. Replace www.yourdomain.com with your bucket name.

    {
    "Version": "2012-10-17",
    "Statement": [
    {
    "Sid": "PublicReadGetObject",
    "Effect": "Allow",
    "Principal": "*",
    "Action": "s3:GetObject",
    "Resource": "arn:aws:s3:::www.yourdomain.com/*"
    }
    ]
    }

Setting up s3_website

With traditional web hosts, you would use the FTP protocol to upload your files. With S3, you’d need to use either their cumbersome web console, REST API, or a third-party tool to manage your files. Fortunately, there is a project called s3_website that can synchronize your website assets to your bucket by simply running a line of code through the terminal. The script requires Ruby and Java installed, so make sure they’re on your computer before going any further.

  1. Open Terminal to your project folder and run: gem install s3_website && s3_website cfg create.
  2. Open s3_website.yml and replace the first three lines with what’s below. Remember to change s3_bucket value to the name of your bucket.

    s3_id: <%= ENV['S3_ID'] %>
    s3_secret: <%= ENV['S3_SECRET'] %>
    s3_bucket: www.yourdomain.com
  3. Run the snippet below while replacing YOUR_S3_ACCESS_ID_HERE andYOUR_S3_SECRET_HERE with your actual ID and secret. This creates a separate configuration file that stores your access information. If you’re using Git, add .env to your .gitignore so it doesn’t get checked in and be hosted elsewhere.

    echo "S3_ID: YOUR_S3_ACCESS_ID_HERE" > .env
    echo "S3_SECRET: YOUR_S3_SECRET_HERE" >> .env
    Project folder structure in Finder
    An example of a project folder structure at this point (dot files are hidden in Finder by default).

That’s all for the bare essential configuration. You can create and store your website files inside a src/ folder (as an example) and run: s3_website push --dry-run --site src/.

The snippet above shows you how the script will modify your S3 bucket. Run the same command without --dry-run to actually commit the changes. This is how you’ll deploy your website without having to fiddle with UIs.

Terminal running deployment script
Running the deployment command using s3_website.

Enabling Cache and Gzip Compression

To save more money on your bucket, you can configure s3_website to add a Cache-control header to your uploaded files. This will ensure that certain files get cached in your visitor’s browsers instead of having them downloaded on every page load (thus, reducing the amount of GET requests). In your s3_website.yml, add the following:

max_age:
"**/*.html": 21600 # 6 hours
"**/*.css": 21600 # 6 hours
"**/*.js": 21600 # 6 hours
"**/*.png": 86400 # 1 day
"**/*.gif": 86400 # 1 day
"**/*.jpg": 86400 # 1 day
"*.ico": 2592000 # 1 month

The key represents the path of files using glob patterns, relative to your src/ folder. The value is the cache duration in seconds. Keep the durations small if you plan to update your content regularly.

Another great feature s3_website has is automated gzipping. It compresses files that can be decoded by the visitor’s browser, thus reducing their storage size and speeding up page load. Enable it in yours3_website.yml by adding the following:

gzip:
- .html
- .css
- .js

Finally, run the push command with --force parameter to update your existing files with the new settings.

Linking to Your Custom Domain

Assuming you want people to visit your domain through the www subdomain, you’ll need to create another bucket in the AWS console with the name yourdomain.com (without the www prefix). Then, under Static Website Hosting, tick Redirect all requests to another name and enter your domain with the www prefix.

Next, you’ll have to go to your domain registrar’s dashboard and add two entries to your domain’s DNS records:

  1. CNAME record with host www and value of your bucket Endpoint URL.
  2. URL Redirect Record with host @ and value of your domain with the www subdomain.

    Namecheap DNS record
    An example of the configuration for a domain that points to a S3 bucket through Namecheap’s dashboard. If you’re using a different registrar, look up their knowledge base on how to access the DNS records.

Save your changes, and it should take a few minutes before the URL endpoints are live. Visit your website URL and make sure both www and non-www version works. If so, then you have successfully linked your S3 bucket to your domain!

Conclusion

And there you go: a highly affordable static website hosted on the reliable servers from Amazon. I’d like to give kudos to the contributors of s3_website, who made S3 a feasible hosting solution without the hassles of server ops.

So, what’s next? There are plenty of static site generators that can help you create and manage complicated websites. Perhaps an old WordPress-powered site of yours could be converted to take advantage of S3, saving you time and cost down the road.

Resources


Charlie is a product designer and developer from Vancouver. He writes about design, development and productivity hacks. If you like what you've read, follow his feed or tweets to stay updated 😎

Portrait of Charlie

Want to talk about this article?

Tweet @charliecm