Complete Guide to Hosting a Static Website on AWS S3: Step-by-Step Tutorial and Best Practices

Neeraj Bhasin
13 min readJul 7, 2023

--

Introduction:

In this tutorial, you use some of the Amazon Simple Storage Service (Amazon S3) features that you just learned about to create a static website.

Static websites can contain HTML pages, images, style sheets, and all files that are needed to render a website. Static websites do not use server-side scripting or a database. However, they may contain client-side scripts that run in a user’s web browser.

You can host a static website on Amazon S3 by uploading the content and making it readable by users. No servers are needed, and you can use Amazon S3 to store and retrieve any amount of data at any time from anywhere on the web.

Objectives

After completing this lab, you will know how to do the following:

  • Create a bucket in Amazon S3.
  • Configure a bucket to host a static website.
  • Upload content to a bucket.
  • Turned on public access to bucket objects.
  • Securely share a bucket object using a presigned URL.
  • Secure a bucket using a bucket policy.
  • Update the website.
  • View object versions in the Amazon S3 console.

Step 1: Creating a bucket in Amazon S3

  • In the AWS Management Console, on the Services menu, choose S3.
  • Choose Create bucket
  • An S3 bucket name is globally unique, and all AWS accounts share the namespace. After you create a bucket, no other AWS accounts in any AWS Regions can use the name of that bucket unless you delete the bucket.
  • For this lab, you use a bucket name that includes a random number, such as website-123.
  • For Bucket name, enter website-<123> and replace <123> with a random number.
  • Public access to buckets is blocked by default. Because the files in your static website will need to be accessible through the internet, you must permit public access.
  • For Object Ownership, choose ACLs enabled.
  • Choose Bucket owner preferred.
  • For Block Public Access settings for this bucket, clear the check box for Block all public access, and then select the box that states I acknowledge that the current settings might result in this bucket and the objects within becoming public.
  • For Bucket Versioning, choose Enable.
  • Note: Once you turn on (enable) bucket versioning, you can’t turn it off.
  • For Tags, choose Add tag, and enter the following: Key: Department, Value: Marketing. You can use tags to add additional information to a bucket, such as a project code, cost center, or owner.
  • Choose Create bucket
  • In the Buckets section, choose the name of your new bucket.
  • Choose the Properties tab.

Step 2: Configuring a static website on Amazon S3

You will now configure the bucket for static website hosting.

  • Scroll to the Static website hosting panel. Choose Edit Configure the following settings:
  • Static web hosting: Choose Enable.
  • Hosting type: Choose Host a static website.
  • Index document: Enter index.html
  • Error document: Enter error.html

Note: You must enter index.html and error.html even though they are already displayed.

  • Choose Save changes
  • In the Static website hosting panel under Bucket website endpoint, choose the link.
  • You receive a 403 Forbidden message because you have not yet configured the bucket permissions. Keep this tab open in your web browser so that you can return to it later.
  • You have configured your bucket to host a static website.

Step 3: Uploading content to your bucket

In this task, you upload the static files to your bucket.

  1. Choose (right-click) each of the following links, and download the files to your computer:
  2. Ensure that each file keeps the same file name, including the extension. index.html, script.js, style.css

here is code snippets

<!--index.html-->
<!DOCTYPE html>
<!--[if lt IE 7 ]><html class="ie ie6" lang="en"> <![endif]-->
<!--[if IE 7 ]><html class="ie ie7" lang="en"> <![endif]-->
<!--[if IE 8 ]><html class="ie ie8" lang="en"> <![endif]-->
<!--[if (gte IE 9)|!(IE)]><!-->
<html lang="en">
<!--<![endif]-->

<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
<meta name="description" content="">
<meta name="author" content="">
<!--[if IE]>
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<![endif]-->
<title>My Static Website</title>
<!--REQUIRED STYLE SHEETS-->
<!-- BOOTSTRAP CORE STYLE CSS -->
<link href="https://stackpath.bootstrapcdn.com/bootstrap/3.1.1/css/bootstrap.min.css" rel="stylesheet" />
<!-- FONTAWESOME STYLE CSS -->
<link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.5.0/css/all.css" crossorigin="anonymous">
<!-- CUSTOM STYLE CSS -->
<link href="style.css" rel="stylesheet" />
<!-- GOOGLE FONT -->
<link href='http://fonts.googleapis.com/css?family=Open+Sans' rel='stylesheet' type='text/css'>
<!-- HTML5 shim and Respond.js IE8 support of HTML5 elements and media queries -->
<!--[if lt IE 9]>
<script src="https://oss.maxcdn.com/libs/html5shiv/3.7.0/html5shiv.js"></script>
<script src="https://oss.maxcdn.com/libs/respond.js/1.3.0/respond.min.js"></script>
<![endif]-->
</head>

<body>
<!--Header section -->
<div class="container" id="home">
<div class="row text-center">
<div class="col-md-12">
<h1 class="head-main"> <i class="fab fa-aws fa-2x"></i> Static Website</h1>
<h2 class="head-sub-main"> Served from Amazon S3 </h2>
</div>
</div>
</div>
<!--End Header section -->

<!-- Navigation -->
<nav class="navbar-inverse" role="navigation">
<div class="container">
<div class="navbar-header">
<button type="button" class="navbar-toggle" data-toggle="collapse" data-target=".navbar-ex1-collapse">
<span class="sr-only">Toggle navigation</span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
<a class="navbar-brand" href="http://aws.amazon.com/partners/">APN Network </a>
</div>
<!-- Collect the nav links for toggling -->
<div class="collapse navbar-collapse navbar-ex1-collapse">
<ul class="nav navbar-nav">
<li><a href="#home"><i class="fas fa-home"></i></a>
</li>
<li><a href="#about">About</a>
</li>
<li><a href="#work-sec">Transformation</a>
</li>
<li><a href="#contact-sec">Contact</a>
</li>
<li><a href="#map-sec">Location</a>
</li>
</ul>
</div>
<!-- /.navbar-collapse -->
</div>
<!-- /.container -->
</nav>
<!--End Navigation -->

<!--About Section-->
<section class="color-white " id="about">
<div class="container">
<div class="row text-center">
<div class="col-md-8 col-md-offset-2 ">
<h2 style="padding-top:50px;">About Us</h2>
<h4>
<strong>
Lorem ipsum dolor sit amet, consectetur adipiscing elit.
Curabitur nec nisl odio. Mauris vehicula at nunc id posuere.
</strong>
</h4>
</div>
</div>
</div>
</section>

<section class=" color-light">
<div class="container">
<div class="row text-center">
<div class="col-md-12">
<h2> Our exclusive services</h2>
<p>
Lorem ipsum dolor sit amet, consectetur adipiscing elit.
Curabitur nec nisl odio. Mauris vehicula at nunc id posuere.
Lorem ipsum dolor sit amet, consectetur adipiscing elit.
Curabitur nec nisl odio. Mauris vehicula at nunc id posuere.
Lorem ipsum dolor sit amet, consectetur adipiscing elit.
Curabitur nec nisl odio. Mauris vehicula at nunc id posuere.
Lorem ipsum dolor sit amet, consectetur adipiscing elit.
Curabitur nec nisl odio. Mauris vehicula at nunc id posuere.
Lorem ipsum dolor sit amet, consectetur adipiscing elit.
Curabitur nec nisl odio. Mauris vehicula at nunc id posuere.
Lorem ipsum dolor sit amet, consectetur adipiscing elit.
Curabitur nec nisl odio. Mauris vehicula at nunc id posuere.
Lorem ipsum dolor sit amet, consectetur adipiscing elit.
Curabitur nec nisl odio. Mauris vehicula at nunc id posuere.
Lorem ipsum dolor sit amet, consectetur adipiscing elit.
Curabitur nec nisl odio. Mauris vehicula at nunc id posuere.
</p>
</div>
</div>
</div>
</section>
<!--End About Section-->

<!-- Transformation Section -->
<section class="color-white " id="work-sec">
<div class="container">
<div class="row text-center">
<div class="col-md-8 col-md-offset-2 ">
<h2>Transformation</h2>
<h4>
<strong>
Lorem ipsum dolor sit amet, consectetur adipiscing elit.
Curabitur nec nisl odio. Mauris vehicula at nunc id posuere.
</strong>
</h4>
</div>
</div>

<div class="row text-center g-pad-bottom">
<div class="col-md-4">
<div class="work-div">
<i class="fas fa-box-open fa-5x"></i>
<h3>Package </h3>
</div>
</div>

<div class="col-md-4 ">
<div class="work-div">
<i class="fas fa-arrows-alt-h fa-5x"></i>
</div>
</div>

<div class="col-md-4 ">
<div class="work-div">
<i class="fas fa-cloud fa-5x"></i>
<h3>The Cloud</h3>
</div>
</div>

</div>
</div>
</section>
<!--End Transformation Section -->
<!-- Contact Section -->
<section class="color-light " id="contact-sec">
<div class="container">
<div class="row text-center">
<div class="col-md-8 col-md-offset-2 ">
<h2>Locate Us here</h2>
<h4>
<strong>
Lorem ipsum dolor sit amet, consectetur adipiscing elit.
Curabitur nec nisl odio. Mauris vehicula at nunc id posuere.
</strong>
</h4>
</div>
</div>

<div class="row">
<div class="col-md-5 contact-cls">
<h3>Our Address</h3>
<div>
<span><i class="fa fa-home"> </i> Address: 123/56, Your City, USA </span>
<br />
<span><i class="fa fa-phone"> </i> Phone: 82-230-555-8899</span>
</div>

</div>
<div class="col-md-7">
<br />
<div id="social-icon">
<a href="#"><i class="fab fa-facebook fa-2x"></i></a>
<a href="#"><i class="fab fa-twitter fa-2x"></i></a>
<a href="#"><i class="fab fa-linkedin fa-2x"></i></a>
<a href="#"><i class="fab fa-google-plus fa-2x"></i></a>
<a href="#"><i class="fab fa-pinterest fa-2x"></i></a>
</div>
</div>
</div>
</div>
</section>
<!--End Contact Section -->

<!--Map Section -->
<section class="color-light " id="map-sec">
<iframe class="cnt" src="https://www.google.com/maps/embed?pb=!1m18!1m12!1m3!1d2999841.293321206!2d-75.80920404999999!3d42.75594204999997!2m3!1f0!2f0!3f0!3m2!1i1024!2i768!4f13.1!3m3!1m2!1s0x4ccc4bf0f123a5a9%3A0xddcfc6c1de189567!2sNew+York!5e0!3m2!1sen!2s!4v1395313088825"></iframe>
</section>
<!--End Map Section -->
<!--footer Section -->
<div class="for-full-back " id="footer">
CSS Template from <a href="https://www.free-css.com/free-css-templates/page203/image-less">Free CSS</a>
</div>
<!--End footer Section -->
<!-- JAVASCRIPT FILES PLACED AT THE BOTTOM TO REDUCE THE LOADING TIME -->
<!-- CORE JQUERY -->
<script src="https://code.jquery.com/jquery-1.10.2.min.js"></script>
<!-- BOOTSTRAP CORE SCRIPT -->
<script src="https://stackpath.bootstrapcdn.com/bootstrap/3.1.1/js/bootstrap.min.js"></script>
<!-- CUSTOM SCRIPTS -->
<script src="script.js"></script>

</body>

</html>
//script.js
/*=============================================================
Authour URI: www.binarytheme.com
License: Commons Attribution 3.0

http://creativecommons.org/licenses/by/3.0/

100% To use For Personal And Commercial Use.
IN EXCHANGE JUST GIVE US CREDITS AND TELL YOUR FRIENDS ABOUT US

======================================================== */


(function ($) {
"use strict";
var mainApp = {

main_fun: function () {
/*====================================
CUSTOM LINKS SCROLLING FUNCTION
======================================*/

$('nav a[href*=#]').click(function () {
if (location.pathname.replace(/^\//, '') == this.pathname.replace(/^\//, '')
&& location.hostname == this.hostname) {
var $target = $(this.hash);
$target = $target.length && $target
|| $('[name=' + this.hash.slice(1) + ']');
if ($target.length) {
var targetOffset = $target.offset().top;
$('html,body')
.animate({ scrollTop: targetOffset }, 800); //set scroll speed here
return false;
}
}
});


/*====================================
NAV SCRIPTS
======================================*/
$(window).bind('scroll', function () {
var navHeight = $(window).height() -50;
if ($(window).scrollTop() > navHeight) {
$('nav').addClass('fixed');
}
else {
$('nav').removeClass('fixed');
}
});

},

initialization: function () {
mainApp.main_fun();

}

}
// Initializing ///

$(document).ready(function () {
mainApp.main_fun();
});

}(jQuery));
/*style.css*/
/*=============================================================
Authour URI: www.binarytheme.com
License: Commons Attribution 3.0

http://creativecommons.org/licenses/by/3.0/

100% To use For Personal And Commercial Use.
IN EXCHANGE JUST GIVE US CREDITS AND TELL YOUR FRIENDS ABOUT US

======================================================== */



/*=======================================
GENERAL STYLES
==================================================*/
body {
font-family:'Open Sans', sans-serif;
font-size:14px;
background-color:#9B60DB;
}

.nav a {
color:#ffffff !important;
}
.navbar-header a {
color:#ffffff !important;
padding-right:100px;
}

.text-center {
text-align:center;
}

h1, h2, h3, h4, h5, h6 {
font-family:'Open Sans', sans-serif;
}

h1 {
line-height:80px;
font-weight:900;
font-size:60px;
padding:30px 20px 10px 20px;
}
h2 {
line-height:40px;
font-weight:900;
font-size:30px;
padding:20px 20px 10px 20px;
text-transform:uppercase;
}
h3 {
line-height:30px;
padding-bottom:20px;
}
h4 {
line-height:40px;
padding-bottom:15px;
}

p {
font-weight:300;
line-height:30px;
padding-bottom:20px;
}

.space-free {
height:100px;
}


section {
padding-top:50px;
padding-bottom:30px;
}

/*=======================================
COLOR CODES
==================================================*/
.color-white {
background-color:#fff!important;
}
.color-dark {
background-color:#696969!important;
}

.color-light {
background-color:#E9E9E9!important;
}

/*=======================================
HEADER STYLES
==================================================*/
.head-main {
font-size:80px !important;
font-weight:900!important;
color:#fff!important;
padding:150px 20px 10px 20px;
}
.head-sub-main {
font-size:40px !important;
font-weight:600!important;
color:#fff!important;
padding:5px 20px 150px 20px;
}


/*=======================================
NAVIGATION STYLES
==================================================*/


nav {
position: absolute;
width: 100%;
background: #fff;
z-index:99;
}
.fixed {
position: fixed;
top: 0;
min-height: 50px;
z-index: 99;
}

.navbar-inverse {
background-color: #000000;
border-color: #000000;
min-height: 80px;
padding-top: 10px;
font-size: 18px;
}
.navbar-brand {

font-size: 30px;
}

/*=======================================
WORK FLOW STYLES
==================================================*/


.work-div {
width: 100%;
border: 0;
padding:20px;
margin-bottom:30px;
}
/*=======================================
CONTACT STYLES
==================================================*/

#social-icon a {
color:#616161!important;
margin-right:10px;
}
.contact-cls {
font-size:20px;
line-height:40px;
}
.cnt {
width: 100%;
min-height: 350px;
border: 1px solid #e1e1e1;
}
/*=======================================
FOOTER STYLES
==================================================*/


#footer {
background-color:#000;
color:#fff;
padding:20px 50px 20px 50px;
text-align:right;
}
  • Return to the Amazon S3 console, and choose the Objects tab.
  • Choose Upload
  • Choose Add files
  • Choose the three files that you downloaded.
  • Choose Upload. Your files are uploaded to the bucket.
  • Choose Close

Step 4: Turning on public access to the objects

Objects that are stored in Amazon S3 are private by default. This setting helps keep your organization’s data secure.

In this step, you make the uploaded objects publicly accessible so users can view your website.

First, confirm that the objects are currently private.

  • Return to the browser tab that showed the 403 Forbidden message.
  • Refresh the webpage.

go to the Properties tab, and in the Static website hosting panel, choose the Bucket website endpoint link again.

You should still see a 403 Forbidden message. This response is expected! This message indicates that your static website is being hosted by Amazon S3 but that the content is private.

You can make Amazon S3 objects public through two different ways:

  • To make either a whole bucket public or a specific directory in a bucket public, use a bucket policy.
  • To make individual objects in a bucket public, use an access control list (ACL). It is normally safer to make individual objects public because doing so avoids accidentally making other objects public. However, if you know that the entire bucket contains no sensitive information, you can use a bucket policy.
  • You now configure the individual objects to be publicly accessible.
  • Keep the website tab open, and return to the web browser tab with the Amazon S3 console.
  • Choose all three objects.
  • In the Actions menu, choose Make public using ACL.

A list of the three objects is displayed.

  • Choose Make public

Your static website is now publicly accessible.

  • Choose Close
  • Return to the web browser tab that has the 403 Forbidden message.
  • Refresh the webpage.

You should now see the static website that is being hosted by Amazon S3.

Now you know how to share objects with everyone by making them public. However, there may be times when you need to share an individual object for a limited amount of time. In the next task, you learn how to temporarily share an object.

Task 5: Securely sharing an object using a presigned URL

When you need to temporarily and securely share an object with a person or group of people, you can create a presigned URL. When you create the URL, you must configure how long the URL will be valid. Then, you can share this URL with the users who should have access to the object.

As long as the presigned URL is valid, anyone who has it can get to the object. Avoid keeping the URL active longer than necessary, and only share the URL with people you trust.

  • Choose (right-click) the following link, and download the file to your computer: Ensure that the file keeps the same file name, including the extension.
  • new-report.png
  • Return to the Amazon S3 console, and choose the Objects tab.
  • Choose Upload
  • Choose Add files
  • Choose the file that you downloaded.
  • Choose Upload

You have uploaded your file to the bucket.

  • Choose Close

Like when you first uploaded the website files, the new-report.png file is private by default. This time, instead of making the object public, you create a presigned URL to access the file.

  • In the Objects tab, choose new-report.png.
  • From the Actions menu, select Share with a presigned URL
  • In the pop-up window, configure the Time interval until the presigned URL expires: Choose Minutes
  • Choose Create presigned URL
  • From the banner at the top of the page, choose Copy presigned URL.
  • Open a new browser tab, and paste the URL you copied into the address bar. A report is displayed in the web browser. If you wait 5 minutes and use the link again, you will find that the URL has expired and no longer works.

Task 6: Using a bucket policy to secure your bucket

You want to protect your website files and make sure that no one can delete them. To do this, you apply a bucket policy that denies delete privileges on your website files.

  • Return to the Amazon S3 console, and choose the Permissions tab.
  • Under Bucket policy, choose Edit
  • Copy the following policy text. In the Policy text editor, replace the existing policy text with this text:
  • This policy prevents everyone from deleting the three files that make your website work.

Next, you update the text in the policy editor. In the following lines of code in the policy editor, replace the <bucket-name> placeholders with the name of your bucket.

{
"Version": "2012-10-17",
"Id": "MyBucketPolicy",
"Statement": [
{
"Sid": "BucketPutDelete",
"Effect": "Deny",
"Principal": "*",
"Action": "s3:DeleteObject",
"Resource": [
"arn:aws:s3:::<bucket-name>/index.html",
"arn:aws:s3:::<bucket-name>/script.js",
"arn:aws:s3:::<bucket-name>/style.css"
]
}
]
}

Note: Your bucket name will be different. Be sure to use the name of the bucket that you created.

  • Choose Save changes
  • Return to the the Object tab
  • Select index.html.
  • Choose Delete.
  • In the Delete objects panel, enter delete to confirm that you want to remove this file.
  • Choose Delete objects
  • Notice that the index.html file is listed in the Failed to delete pane.
  • This confirms that your policy is working and preventing the website’s files from being deleted.
  • Choose Close to return to the Objects tab.

Task 7: Updating the website

Although you have configured a policy to prevent deletion of website files, you can still update the website by editing the HTML file and uploading it to the S3 bucket again.

Amazon S3 is an object storage service, so you must upload the whole file. This action replaces the existing object in your bucket. You cannot edit the contents of an object; instead, you must replace the whole object.

  • On your computer, load the index.html file into a text editor (for example, Notepad or TextEdit).
  • Find the text Served from Amazon S3, and replace it with Created by <YOUR-NAME> and substitute your name for <YOUR-NAME> (for example, Created by Jane).
  • Save the file.
  • Return to the Amazon S3 console, and upload the index.html file that you just edited.
  • Choose index.html, and in the Actions menu, choose the Make public using ACL option again.
  • Choose Make public.
  • Return to the web browser tab with the static website, and refresh the page.

Your name should now be on the page.

Your static website is now accessible on the internet. Because it is hosted on Amazon S3, the website has high availability and can serve high volumes of traffic without using any servers.

Task 8: Exploring file versions

Bucket versioning is turned off by default. When versioning is turned off, changes to objects can’t be undone. For example, if you upload a new version of a file, the old file is replaced with the new one. The original file is lost. If you delete a file, it is permanently deleted, and you can’t get it back.

However, when versioning is turned on, changed and deleted versions of files are saved. Previous versions of objects are not presented by default, but you can access them using the console or programmatically. Because you are keeping earlier versions of objects, you can recover them if you need to.

It is important to remember that once you turn on version, you cannot turn it off. However, you can suspend versioning. For more information on bucket versioning, see the Amazon Simple Storage Service Users Guide.

Recall that when you created your bucket, you turned on versioning. In this task, you view the object versions available in your bucket.

  • Return to the Amazon S3 console, and choose the Objects tab.
  • Choose Show versions to turn on bucket versioning.
  • Review the list of objects in the bucket.

Summary

In this tutorial, you created a personalized, publicly accessible static website. You learned how to use a presigned URL to temporarily share objects in your bucket. You also protected your work with a bucket policy that prevents file deletion and turned on bucket versioning in case you need to recover previous versions of files. Excellent work!

--

--

Neeraj Bhasin
Neeraj Bhasin

No responses yet