S3 Version without SSL Certificate #
This tutorial is just a quick solution for testing purposes. It deploys a static websites consisting of html, css and js files. It provides no SSL/TSL encryption and the content of the S3 Bucket is public.

Disable and acknowledge the “Block all public access” option:

Go to the permissions section of your S3 Bucket and past the following configuration,
replace s3.jklug.work
with the name of your Bucket:
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "PublicReadGetObject",
"Effect": "Allow",
"Principal": "*",
"Action": [
"s3:GetObject"
],
"Resource": [
"arn:aws:s3:::s3.jklug.work/*"
]
}
]
}

Go to Objects Section of your S3 Bucket and upload an index.html file like this one:
<!DOCTYPE html>
<html>
<head>
<title>jklug.work</title>
</head>
<body>
<h1>S3 Static Website</h1>
</body>
</html>
Open the permissions section of your S3 Bucket, enable static website hosting and define an index document, in the example it’s “index.html”:



Save the changes, copy the bucket website endpoint and open it in a browser. Note that the website is not encrypted:


Cloudfront Version with SSL/TSL Certificate #
This tutorial uses a S3 Bucket to host a static website but it’s content is only accessable through a Cloudfront Distribution. The Cloudfront Distribution also provides the necessary encryption the provide secure data transfair.
Create S3 Bucket #
Create a new S3 Bucket with standard settings. The “Block all public access” option should be enabled by default:

Go to Objects Section of your S3 Bucket and upload an index.html file like this one:
<!DOCTYPE html>
<html>
<head>
<title>jklug.work</title>
</head>
<body>
<h1>S3 Cloudfront</h1>
</body>
</html>
Create Cloudfront Distribution #
Select your S3 Bucket, enable the “Origin access control settings” and click the “Create control setting” buttion:

Create a control setting and make sure it’s selected in the main view:


Enable the “Redirect HTTP to HTTPS” option:

Select a price class / region, select your SSL certificate - note: for CloudFront the SSL Certificate must be in the us-east-1 region - and define a default root object, in the example the root object is “index.html”:

Create the CloudFront Distribution, open the objects section of your distribution, select the origin name and click “edit”:

Copy the origin access control bucket policy - it should look like in the example below - and past it as permission to your bucket policy:

{
"Version": "2008-10-17",
"Id": "PolicyForCloudFrontPrivateContent",
"Statement": [
{
"Sid": "AllowCloudFrontServicePrincipal",
"Effect": "Allow",
"Principal": {
"Service": "cloudfront.amazonaws.com"
},
"Action": "s3:GetObject",
"Resource": "arn:aws:s3:::s3-cloudfront.jklug.work/*",
"Condition": {
"StringEquals": {
"AWS:SourceArn": "arn:aws:cloudfront::073526172187:distribution/E26589F32XA4RO"
}
}
}
]
}
Add Access Policy to S3 Bucket #
Open the permissions section of your S3 Bucket and paste the policy:

Route 53 DNS entry #
Open Route 53 and create an DNS entry to routes the traffic to your CloudFront Distribution:




Open your URL in a Browser, note that it’s secure now:
Cloudfront: Geographic Restrictions #
Option it can be useful to allow traffic to your website only from specified countries. Open the Geographic Restrictions Panel of your CloudFront Distribution:

Choose allow list and select the desired countries:

Test the Whitelist Settings with Geo Browse:
https://geotargetly.com/geo-brow


Cloudfront Function: Redirect to index.html #
For some web applications it’s necessary to create a function that adds index.html to the end of every URL. This is common with static site generators. Open the CloudFront / Function Panel and create a new function:

Copy and paste the following function and save the changes:
function handler(event) {
var request = event.request;
var uri = request.uri;
// Check whether the URI is missing a file name.
if (uri.endsWith('/')) {
request.uri += 'index.html';
}
// Check whether the URI is missing a file extension.
else if (!uri.includes('.')) {
request.uri += '/index.html';
}
return request;
}

Go to the Publish section of your functiona and publish it:

After the function is published add an association / your CloudFront Distribution:


CloudFront Cache Invalidation #
The remove all files from the cache, for example after the websites was updated, proceed as follows:
- Select the Distribution
- Open the “Invalidations” Tab
- Click “Create invalidation”
- Add object paths:
/*
This invalidates all files in the distribution.