Skip to content

Instantly share code, notes, and snippets.

@rs77
Created December 9, 2022 21:34
Show Gist options
  • Save rs77/26eef4e43d414346e4d8c3ec145eaef7 to your computer and use it in GitHub Desktop.
Save rs77/26eef4e43d414346e4d8c3ec145eaef7 to your computer and use it in GitHub Desktop.
How to create a secure S3 website using AWS Cloudfront

If you have made the migration to host your website using Amazon's S3 service and encounter issues with serving your content through a secure certificate or even trying to get Cloudflare to connect then this article will hopefully help set your connection right.

To help illustrate the concepts behind the connection, I'll use a site I once owned to show the entire process freeworksheetsmath.com.

Step 0 - Log in AWS & Cloudflare Accounts

This is perhaps the easiest out of all the steps, although the rest aren't too bad, but to get started you will need to log in to your AWS and your Cloudflare accounts.

Our first X steps will be in the AWS area, then towards the end we finish up with Cloudflare.

So, starting in your AWS account let's get the following configurations set up.

Step A - Create an S3 Bucket (or two)

If you haven't done so already you will need to create an S3 bucket to be able to host your static files.

Click on the orange Create bucket button and enter the web address of your website. For example, if your web address is www.some-site.com then you would enter this into the Bucket Name field. If you want to host your website from a specific region then select this region in the next field. Lastly, as our static site is to be viewable by the public we need to untick the Block all public access checkbox and confirm this selection by acknowledging the warning that pops up underneath.

For my old website this creation of the S3 bucket stage would look something like this:

![Create s3 static website](https://media.scripteverything.com/wp-content/uploads/2021/02/create-s3-static-website-731x1024.png) Create bucket for static hosting in Amazon S3

You'll know everything has worked when you see a green confirmation pane, and a listing of all your S3 buckets.

Configure Your S3 Bucket for Static Hosting

There are a couple of further configurations still needed on our bucket to enable it for static site hosting. Therefore, click on your S3 bucket in the table before you and from this new page click on the Properties tab.

On the properties screen we have a couple of options to further enable static site hosting, the most obvious being the tile labelled Static website hosting - click anywhere on the white space in this tile (i.e. everything but the Learn More link):

![S3 Website Hosting](https://media.scripteverything.com/wp-content/uploads/2021/02/set-static-website-hosting-properties.png) Set static website hosting details for S3 bucket

The available options on this tile should be fairly obvious, we want to select the option to Use this bucket to host a website and upon selecting this option we need to set what the index document is when people enter our web address in their web browser, and what the error document is when people type an incorrect web page for our website.

As I use Hugo to generate my static sites, it automatically creates a 404.html page as the error page, therefore my settings for my S3 bucket would be as follows:

![S3 Static Options](https://media.scripteverything.com/wp-content/uploads/2021/02/set-s3-static.png) Set S3 static website index & error pages

Before we leave this window you'll need to grab the URL. The URL generated by AWS for my S3 bucket is http://freeworksheetsmath.com.s3-website-ap-southeast-2.amazonaws.com. Keep a copy of this URL as it will be needed later.

When you've copied the URL click the Save button.

Create Bucket Policy

Once you've set the properties of the bucket, you need to set the Bucket's policies.

Click on the Permissions tab, then click on the Bucket Policy button.

Below the main text box is a link labelled Policy Generator, click this, and you will be navigated to a visual editor where you can set your permissions.

On this screen set the following values:

  • Step 1: Select Policy Type = S3 Bucket Policy
  • Step 2: Effect = Allow
  • Step 2: Principal = *****
  • Step 2: AWS Service = Scroll down and tick GetObject
  • Step 2: Amazon Resource Name = Type in your bucket according to the format arn:aws:s3:::/ (mine would be arn:aws:s3:::freeworksheetsmath.com/*)
  • Step 2: Add any conditions if needed (I didn't set any).

Here's how my options appeared:

![s3 Bucket Statement](https://media.scripteverything.com/wp-content/uploads/2021/02/add-s3-bucket-statement-1024x576.png) Add S3 bucket statement to bucket policy

Click the Add Statement button, and your settings would be added to the policy:

![S3 Statement Policy](https://media.scripteverything.com/wp-content/uploads/2021/02/s3-statement-added-to-policy-1024x349.png) S3 statement added to bucket policy

To generate the JSON code to use in our Bucket Policy you need to click the Generate Policy button found in Step 3.

Doing so pops up a modal window where you need to copy the contents of that window and then paste it over to the text box area above the Policy Generator link.

The code generated for my S3 bucket was as follows:

{
  "Id": "Policy1590953744901",
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "Stmt1590953064638",
      "Action": [
        "s3:GetObject"
      ],
      "Effect": "Allow",
      "Resource": "arn:aws:s3:::freeworksheetsmath.com/*",
      "Principal": "*"
    }
  ]
}

When I copied this back into the bucket's Bucket Policy text area and then clicked Save you should see confirmation of the nature of your bucket's policy being public.

![S3 Bucket Policy](https://media.scripteverything.com/wp-content/uploads/2021/02/set-s3-bucket-policy-json-1024x732.png) Set S3 bucket policy JSON

Your bucket has now been set up to correctly display web pages. You can upload a file to your bucket and test this works by navigating to the URL you copied earlier.

Test S3 Bucket

To test your S3 bucket will correctly display web pages, create a simple index.html (or whatever identifier you used when setting the website's index page in the Properties window).

I created a simple web page as follows:

<!DOCTYPE html>
<html><body><p>Hello world!</p></body></html>

Then upon clicking on the Overview tab in the bucket, click on the Upload button.

  1. Add your files from your computer. Click Next.
  2. Set permissions (I left everything as is). Click Next.
  3. Set the properties of the file (I left it set to Standard). Click Next.
  4. On the Review screen click Upload.

To test your page works go to the URL you copied in your web browser.

![Test S3 Bucket](https://media.scripteverything.com/wp-content/uploads/2021/02/test-s3-bucket-works-1024x177.png) Test S3 bucket works by navigating to your bucket's URL

If you can see the text of the HTML document you uploaded into your bucket then well done! If not, click on the Properties tab in your bucket, then click on the Static Website Hosting tile and click on the link to your bucket.

If you still cannot see anything check the settings on this tile for the Index document, and the name of the file you uploaded - they need to be exactly the same.

Create Another Second S3 Bucket

If you'd like to create another S3 bucket which automatically routes traffic through to your previous S3 bucket you've just created then do so now.

Go back through the previous steps, except this time name the bucket differently according to the web address you wish to redirect.

For example, I didn't use the www sub-domain for my website address, but I wanted to redirect users who type the popular sub-domain in their address bar so that it redirects them correctly to freeworksheetsmath.com. Therefore, I created a new bucket labelled www.freeworkeetsmath.com.

The only difference with this set up is we only need to set the Properties on this bucket.

Therefore, once the bucket has been created, click on the Properties tab, then click on the Static website hosting tile again.

You'll need to set the properties here a little different from your main bucket. Click the Redirect radio button and enter the name of your main bucket and whether to redirect traffic to a secure website or standard.

Here's how the properties of my redirected bucket looked:

![Redirect S3 Bucket](https://media.scripteverything.com/wp-content/uploads/2021/02/redirect-s3-bucket.png) Set S3 bucket redirect properties

Click Save, and your redirected website is good to go!

Step B - Create SSL Certificate

If you want your bucket to be served through a secure connection (highly recommended) then you'll need to use another service in AWS called AWS Certificate Manager.

By clicking on the Services link in the upper-left, type Certificate Manager and select the option that appears.

To start this process click the Get Started button to Provision certificates.

IMPORTANT!
I found I had to set the zone for my certificates to N. Virginia to get them to work properly with Cloudflare. If you experience any problems with connecting your certificates to Cloudflare you might want to do the same.

To continue through you will want to select Request a public certificate, upon clicking the Request a certificate button you will be presented with a list of steps, let's go through these one by one.

Step 1 - Add domain names

Add the domain names you want this certificate to cover.

I wanted to be specific, so in this area I entered each of the following domains:

freeworksheetsmath.com
www.freeworksheetsmath.com
![Cloudfront Add Domains](https://media.scripteverything.com/wp-content/uploads/2021/02/add-domain-names-1024x513.png) Add your domain names one at a time

Click Next.

Step 2 - Select a validation method

With this step you need to prove you own the domain by performing one of two tasks: modifying your DNS records, or through email verification.

If you're comfortable and have access to your domain's DNS records then select the DNS Validation option.

Step 3 - Add Tags

If you'd like to manage your certificates by applying tags you can do so here, otherwise, click th_e Review_ button.

Step 4 - Review

The final step is to review everything you've done. If you're happy with everything then click the Confirm and request button.

Step 5 - Validation

In this final step, if you've previously selected DNS validation you will be required to create a unique CNAME record for your domain.

![AWS Certificate Manager](https://media.scripteverything.com/wp-content/uploads/2021/02/dns-validation-aws-certificate-manager-1024x889.png) Validate by DNS in AWS Certificate Manager

Here I need to set the CNAME record to verify both the root domain and the www sub-domain.

Once you've set these properties in your DNS provider you need to wait for AWS to validate and confirm your domain.

![AWS Validated Certificate](https://media.scripteverything.com/wp-content/uploads/2021/02/aws-validated-certificate-1024x235.png) AWS Validated Certificate for your domains

Step C - Create Cloudfront Distribution

Our final step is connecting both the S3 bucket with the secure certificates generated.

Click on the Services link again in the top-left hand corner and enter Cloudfront.

Click on the Create Distribution button to get started.

Step 1 - Select Delivery Method

Click on the Get Started button for Web.

Step 2 - Create distribution

On this screen you need to set a few properties, as follows:

  • Origin Domain Name = Paste the URL of your bucket's website address without the leading http value. For example, the URL of my S3 bucket is http://freeworksheetsmath.com.s3-website-ap-southeast-amazonaws.com but I just pasted freeworksheetsmath.com.s3-website-ap-southeast-amazonaws.com into this input field.

  • Viewer Protocol Policy = Set to Redirect HTTP to HTTPS

  • Compress Objects Automatically = Yes

  • Alternate Domain Names (CNAMEs) = I entered per line each of the domains I had registered with the Certificate Manager, namely:

    freeworksheetsmath.com www.freeworksheetsmath.com

  • SSL Certificate = Set Custom SSL Certificate (example.com) and then select the domain of the Certificate you created previously.

  • Default Root Object = Set index.html or whatever you set in your websites properties when setting the Static website Hosting.

Additionally, change any of the other settings as needed. Once you are done, click on the Create Distribution button.

You'll need to wait a few minutes while the distribution creates the necessary configurations, and you'll know everything is ready when you see the state of the distribution as Enabled

![Cloudfront Distribution](https://media.scripteverything.com/wp-content/uploads/2021/02/cloudfront-distribution-enabled-1024x197.png) Cloudfront distribution has been enabled

Step D - Set Domain CNAME Record

Finally, to finish this whole process off all you need do is set the unique Cloudfront URL to the value of your domains in your DNS provider.

My Cloudfront URL is d2i7zzjw0icbrm.cloudfront.net, therefore, the property value for the CNAME records of my root domain and www sub-domain would be this Cloudfront URL.

To check everything has connected properly, and the domains have propagated through you can test this by running a dig command in your terminal:

$ dig freeworksheetmath.com

When you see some A records with IP address numbers then you've likely got things connected.

The ultimate test is to type your domain web address into your web browser and see the page you uploaded to your S3 bucket back in Step A.

Conclusion

In this article, we have learned how to create a secure website using Amazon S3, AWS Certificate Manager and Cloudfront.

You should be able to click on the lock icon in your web browser to inspect the secure certificate served.

Here was the final result of my website:

![Secure Connection](https://media.scripteverything.com/wp-content/uploads/2021/02/website-secure-connection.png) Testing your connection is secure, click on the lock icon in your web browser ![Certificate Valid](https://media.scripteverything.com/wp-content/uploads/2021/02/check-certificate-validity.png) Checking the certificate's validity
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment