In this post we’ll create and configure an S3 bucket for hosting a static website.

Before I start, let me say that there are numerous guides for this process online. I have nothing new to add here - this post is intended to reflect my experience as opposed to being a how-to. The AWS documentation is easy to follow and is guaranteed to be up to date, a guarantee that other blogs (including this one) can’t make. So the steps I follow here will almost definitely change as S3 continues to evolve.

With that said, let’s go.

I plan to create two buckets so I can have a Development and Live environment for the site. This will allow me to test potential config or theme changes in real-world conditions, and will also let me try out AWS services that deploy across multiple environments. The names of the buckets must mirror the websites’ domain names, and in this case will be www.amazonwebshark.com and www.amazondevshark.com (this was almost named www.amazonwebsharkdev.com - and perhaps should have been - but I really can’t leave a name like amazondevshark on the table)

First of all, let’s create and name the bucket.


AWSB0006-01_S3BucketName

Why Ireland? Well, it’s cheaper than London, but also seems to get the new AWS services before the rest of the EU regions. (Incidentally, Concurrency Labs have a very extensive blog on the subject that’s worth a read) And while London is technically closer to me, any latency issues could be addressed with CloudFront in the future.

Next is configuration. Unlike the bucket name, these options can be edited at a later time. For now I’m just going to tag both buckets and move on. The Project tag will tell me what the buckets are for, and if I want to drill down further then the Environment tag will let me separate them into Dev and Live

AWSB0006-02_S3BucketTags

Next is setting permissions. Remember when I mentioned S3’s evolutions before? This is one of them. AWS have set all S3 buckets to block public access by default:

AWSB0006-03_S3BlockPublic

This is a relatively recent change and was likely the result of a number of data breaches involving S3 misconfigurations in recent times. Blocking public access is absolutely the right thing to do when storing personal data, but in this case we need the bucket’s contents to be accessible to the wider world, so here the tick in Block All Public Access needs to be removed. Once this is done and the bucket is created the S3 dashboard is displayed again, and there’s a clear difference in the Access column between the buckets I already had and the one I just created:

AWSB0006-04_S3Dashboard

But what do these statements mean? Let’s dig deeper:

AWSB0006-05_S3Access

So that’s not ideal. We could go through each object at a time, granting public access permissions to each one. But there’s a quicker way - updating www.amazondevshark.com ’s bucket policy. For this we need to access the bucket overview, then go to the Permissions tab and click Bucket Policy.


AWSB0006-06_S3BuckPolicy

Bucket policies allow users to manage advanced permissions to the bucket in question using JSON. Handily the AWS documentation includes a bucket policy that achieves most of what we need:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "PublicReadGetObject",
            "Effect": "Allow",
            "Principal": "*",
            "Action": [
                "s3:GetObject"
            ],
            "Resource": [
                "arn:aws:s3:::example-bucket/*"
            ]
        }
    ]
}



But what does all this mean? Well there’s a great page at The AWS Insider that breaks down each line of the above, but for our immediate purposes the policy boils down to:

  • [Allow] [*] [s3:GetObject] [aws:s3:::example-bucket/*]
  • Allow everyone to get objects from the s3 bucket called example-bucket (all objects)

Most of this is fine except the bucket name, so the line arn:aws:s3:::example-bucket/* needs changing to arn:aws:s3:::www.amazondevshark.com/*. Saving this immediately produces some more changes:

AWSB0006-07_S3BuckPublicPolicy

AWS are leaving you in no doubt at this point - everything in that bucket is now accessible to the Internet. There’s nothing in there yet though, but before anything is uploaded there’s still one more step to do. Access the bucket’s properties and select Static Website Hosting.


AWSB0006-08_StaticHost

This screen offers an endpoint hyperlink, but clicking on it at this point produces an error:

1
2
3
4
5
6
404 Not Found
Code: NoSuchWebsiteConfiguration
Message: The specified bucket does not have a website configuration
BucketName: www.amazondevshark.com
RequestId: 59553C8F99BE091B
HostId: PCllvdaWafvPXXEniyOfDWW/BBYyf93BSqt5wNp2/u+lN0dF6YnDTXm7JL8DXfQ4JYFJUi8zhrE=



AWS need to know the names of the index and error documents as part of this process. These are available in the public folder created in the last post, specifically index.html and 404.html. With all this done, visiting the S3 dashboard shows the bucket is now fully public:

AWSB0006-09_S3DashboardPublic

The endpoint is still showing an error, albeit a different one now:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
404 Not Found
Code: NoSuchKey
Message: The specified key does not exist.
Key: index.html
RequestId: 3DD771ABD3D9154E
HostId: xX44SXp9zIHiEDs9tahJR54M3OnvOKrI8o6oCkdu8jl4xAIxGeW17ghEg12vtw9dk+pRN3p+gio=
An Error Occurred While Attempting to Retrieve a Custom Error Document
Code: NoSuchKey
Message: The specified key does not exist.
Key: 404.html



This isn’t surprising - there’s nothing in the bucket for it to display! So let’s fix that by uploading the contents of the Public folder in Hugo’s amazondevshark.com folder to the www.amazondevshark.com S3 bucket. And this time when the endpoint is called:

As a regular site:

AWSB0006-10_ADSMain



In incognito:

AWSB0006-11_ADSIncog



And via mobile:

AWSB0006-12_ADSAndroid

There are still things to fix of course - the blog’s title, tab metadata, header and footer are still set as default for instance, but we have a working site! A site with no server or database dependencies, a site backed up by S3’s eleven nines of durability and high availability and, crucially, a site that will cost a fraction of the price to run when compared to a similar setup using EC2 and RDS.

Thanks for reading ~~^~~