Host a Website on Amazon S3

Deploy a static website to AWS S3 using only the AWS CLI.

Introduction

30 Second Summary

Every website you visit lives on a server somewhere. Cloud engineers put them there using command-line tools instead of clicking through web interfaces.

In this project, you will deploy a personal landing page to Amazon S3 using the AWS CLI. You'll provision cloud infrastructure, configure permissions, and make your site accessible to anyone on the internet.

What You'll Build

A static HTML/CSS landing page hosted on an S3 bucket, deployed entirely from your terminal using AWS CLI commands.

By the end of this project, you'll have:

  • A personal landing page built with HTML and CSS.
  • An S3 bucket configured for static website hosting using the AWS CLI.
  • A bucket policy granting public read access so anyone can view your site.
  • Secret Mission: Add a custom-styled 404 error page that displays when visitors hit a broken link.

Are there any prerequisites?

None. This guide includes full setup instructions for every tool you need, including your AWS account and the AWS CLI.

Set Up Your AWS Account and CLI

To deploy a website on AWS, you need a way to talk to AWS from your terminal. The AWS CLI (Command Line Interface) lets you create and manage cloud resources without ever clicking through a web console.

In this step, you will create an AWS account, set up a user with programmatic access, and install the AWS CLI so your terminal can authenticate with AWS.

In this step, get ready to:
  • Create an AWS account and IAM user with programmatic access.
  • Install the AWS CLI v2 on your machine.
  • Configure the CLI with your credentials and verify it works.
Create an AWS account and IAM user

AWS requires an account before you can use any of its services. You also need an IAM user with programmatic access so your CLI can authenticate securely.

  • Go to https://aws.amazon.com and click Create an AWS Account.
  • Follow the sign-up steps including email verification, payment method, and support plan selection.
  • If you already have an account, sign in to the AWS Management Console.

What is IAM?

IAM (Identity and Access Management) controls who can access your AWS resources. Instead of using your root account for everything, you create an IAM user with only the permissions it needs.

For this project, you will create an IAM user with programmatic access. This generates an Access Key ID and Secret Access Key that let the CLI authenticate on your behalf.

  • In the AWS Console, search for IAM in the top search bar and open the IAM service.
  • Click Users in the left sidebar.
  • Click Create user.
  • Enter a username (e.g. cli-user) and click Next.
  • Select Attach policies directly and search for AmazonS3FullAccess.
  • Check the box next to AmazonS3FullAccess and click Next.
  • Review your choices and click Create user.

Now create an access key for this user.

  • Click on the username you just created to open the user details.
  • Select the Security credentials tab.
  • Scroll down to Access keys and click Create access key.
  • Select Command Line Interface (CLI) as the use case.
  • Check the confirmation box at the bottom and click Next.
  • Click Create access key.
  • Click Download .csv file to save your Access Key ID and Secret Access Key. Store this file in a safe location.

Keep your credentials safe

The Secret Access Key is shown only once at creation time. If you lose it, you must delete the key and create a new one. Never share your credentials or commit them to version control.

Install the AWS CLI v2

The AWS CLI is the tool that lets you run commands against AWS services from your terminal. You need version 2 installed.

  • Open your terminal by pressing Cmd+Space (macOS) or the Windows key (Windows), typing Terminal (macOS) or cmd (Windows), and pressing Enter.
  • Check if the AWS CLI is already installed by running:
aws --version

✔️ I see aws-cli/2.x.x

The AWS CLI v2 is already installed. You are ready to configure it in the next substep.

ⓧ I see an older version (1.x)

You have AWS CLI version 1 installed. You need to upgrade to version 2.

Follow the instructions in the "Command not found" tab below to install v2. The v2 installer will replace your v1 installation.

ⓧ Command not found

The AWS CLI is not installed yet. Install it using the instructions for your operating system below.

macOS

  • Download and install the AWS CLI by running these commands:
curl "https://awscli.amazonaws.com/AWSCLIV2.pkg" -o "AWSCLIV2.pkg"
sudo installer -pkg AWSCLIV2.pkg -target /
What does this command do?

The first line downloads the official AWS CLI v2 installer package from AWS. The second line runs the macOS installer, which places the aws command in /usr/local/bin/.

  • Your terminal will prompt you for your macOS password because of the sudo command. Type it and press Enter.
  • Verify the installation succeeded by running:
aws --version

You should see output starting with aws-cli/2. followed by a version number.

Windows

  • Download the AWS CLI MSI installer from this URL: https://awscli.amazonaws.com/AWSCLIV2.msi
  • Run the downloaded AWSCLIV2.msi file and follow the on-screen installer prompts.
  • Close and reopen your command prompt so it picks up the new PATH entry.
  • Verify the installation succeeded by running:
aws --version

You should see output starting with aws-cli/2. followed by a version number.

Still seeing command not found?

Close your terminal and open a new one. The PATH update only takes effect in new terminal sessions.

On macOS, if it still fails, check that /usr/local/bin is in your PATH by running echo $PATH.

help me fix the AWS CLI not being found after installation

Configure the AWS CLI with your credentials

The CLI needs to know your Access Key ID, Secret Access Key, and default region so it can authenticate with AWS on every command.

  • Configure the CLI by running:
aws configure

What does aws configure do?

This command prompts you for four values and stores them locally on your machine. These credentials are used to sign every request the CLI sends to AWS.

  • When prompted, enter the following values one at a time, pressing Enter after each:
  • AWS Access Key ID: paste the Access Key ID from your downloaded CSV file.
  • AWS Secret Access Key: paste the Secret Access Key from your downloaded CSV file.
  • Default region name: type us-east-1.
  • Default output format: type json.

Why us-east-1?

This region simplifies S3 bucket creation because it does not require an extra location constraint parameter. Other regions need additional configuration that adds complexity for a first project.

  • Verify everything is working by running:
aws --version

You should see a version string like aws-cli/2.x.x Python/3.x.x followed by your operating system details.

Seeing an authentication error?

Double-check that you pasted the Access Key ID and Secret Access Key correctly from the CSV file. Run aws configure again to re-enter them.

Make sure you are using the credentials for the IAM user you created, not the root account.

help me troubleshoot my AWS CLI configuration

Your terminal is now connected to AWS. Next up, you will use it to create an S3 bucket from the command line.

Create an S3 Bucket

Your AWS CLI is configured and talking to AWS. Now it's time to create your first piece of cloud infrastructure.

An S3 bucket is a container that stores files in the cloud. You'll create one with a single terminal command, then confirm it exists.

In this step, get ready to:
  • Create an S3 bucket from the command line.
  • Verify the bucket exists using the AWS CLI.
Create your S3 bucket

Every S3 bucket name must be globally unique across all of AWS. Choose a name using lowercase letters, numbers, and hyphens, like my-site-yourname-2026.

  • Create your S3 bucket by running this command:
aws s3api create-bucket --bucket [[BUCKET_NAME="my-site-yourname-2026"]] --region us-east-1

What does this command do?

This command has two parts that work together.

  • aws s3api create-bucket tells the AWS CLI to use the S3 API and create a new bucket.
  • --bucket sets the name of your bucket. This name becomes part of your website's URL later.
  • --region us-east-1 places the bucket in AWS's Virginia data center. This region does not require extra configuration flags, making it the simplest choice for beginners.

Why us-east-1?

Most other AWS regions require an additional --create-bucket-configuration flag. The us-east-1 region skips this requirement entirely, which removes one potential error point from your first deployment.

  • Verify your bucket was created by running this command:
aws s3 ls

You should see your bucket name in the output list, along with the date it was created.

Don't see your bucket?

  • If you see a BucketAlreadyExists error, someone else on AWS already owns that name. Try a more unique name by adding extra numbers or your initials.
  • If you see an InvalidBucketName error, check that your name only uses lowercase letters, numbers, and hyphens. No uppercase letters, spaces, or underscores.
  • If you see Access Denied, your IAM user may not have S3 permissions. Go back to Step 1 and confirm your IAM user has the correct policy attached.

Help me troubleshoot my S3 bucket creation error

Your bucket is live on AWS. Next up, you'll build the website files that will live inside it.

Build Your Website Files

Your S3 bucket is created and waiting for content. Now you need something to put in it.

In this step, you will build a simple landing page with HTML and CSS. This is the website that will go live on AWS once you deploy it to your bucket.

In this step, get ready to:
  • Create a project folder and write an HTML landing page.
  • Add a CSS stylesheet with custom colors, fonts, and layout.
  • Preview your site locally in the browser before deploying.
Create your project folder and HTML page

Every website starts with a folder to hold its files. You will create a dedicated folder on your Desktop, then open it in VS Code to start writing your HTML.

  • Move to your Desktop by running this command:
cd ~/Desktop
  • Create your project folder and move into it by running these commands:
mkdir my-s3-website
cd my-s3-website
  • Confirm the folder exists by running:
ls ~/Desktop

You should see my-s3-website in the output.

  • Press Cmd+Space (macOS) or the Windows key (Windows) to open your search bar.
  • Type Visual Studio Code and press Enter to open it.
  • Click File in the top menu bar.
  • Click Open Folder.
  • Select the my-s3-website folder on your Desktop, then click Open.

Why VS Code?

You can use any text editor you like for this project. VS Code is popular because it shows your file structure in a sidebar and highlights HTML/CSS syntax with colors, making typos easier to spot.

  • In the VS Code Explorer sidebar on the left, click the New File icon (a document with a plus sign).
  • Name the file index.html and press Enter.
  • Paste the following HTML into index.html:
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>My Cloud-Hosted Site</title>
    <!-- Link to our stylesheet -->
    <link rel="stylesheet" href="style.css">
</head>
<body>
    <!-- Page header with title and tagline -->
    <header>
        <h1>Hello from AWS S3!</h1>
        <p>This site is hosted entirely on cloud infrastructure.</p>
    </header>
    <main>
        <!-- Section describing what you built -->
        <section>
            <h2>What I Built</h2>
            <p>I deployed this static website to Amazon S3 using the AWS CLI. No servers to manage, no console clicking. Just infrastructure as code.</p>
        </section>
        <!-- Section listing the tools used -->
        <section>
            <h2>Technologies Used</h2>
            <ul>
                <li>Amazon S3 (storage and hosting)</li>
                <li>AWS CLI v2 (infrastructure management)</li>
                <li>HTML and CSS (content)</li>
            </ul>
        </section>
        <!-- Section with ideas for future improvements -->
        <section>
            <h2>Next Steps</h2>
            <p>From here I can add a custom domain with Route 53, enable HTTPS with CloudFront, or automate deployments with a CI/CD pipeline.</p>
        </section>
    </main>
    <!-- Footer with deployment note -->
    <footer>
        <p>Deployed with the AWS CLI</p>
    </footer>
</body>
</html>

What does this HTML do?

This file defines the structure of your landing page. The <head> section sets the page title and links to your CSS file for styling.

The <body> contains a header with a welcome message, three content sections (What I Built, Technologies Used, Next Steps), and a footer. Each <section> is a self-contained content block that will get styled as a card later.

  • Save index.html by pressing Cmd+S (macOS) or Ctrl+S (Windows).
  • You should see index.html listed in the Explorer sidebar on the left.

Don't see index.html in the sidebar?

Make sure you opened the my-s3-website folder itself, not your entire Desktop. If the sidebar shows all your Desktop files, go to File > Open Folder and select just the my-s3-website folder.

help me find my index.html file in VS Code

✔️ Awesome, I've got everything!

Great. Double check you have saved your file before moving on.

ⓧ I'd like to double check the full code

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>My Cloud-Hosted Site</title>
    <link rel="stylesheet" href="style.css">
</head>
<body>
    <header>
        <h1>Hello from AWS S3!</h1>
        <p>This site is hosted entirely on cloud infrastructure.</p>
    </header>
    <main>
        <section>
            <h2>What I Built</h2>
            <p>I deployed this static website to Amazon S3 using the AWS CLI. No servers to manage, no console clicking. Just infrastructure as code.</p>
        </section>
        <section>
            <h2>Technologies Used</h2>
            <ul>
                <li>Amazon S3 (storage and hosting)</li>
                <li>AWS CLI v2 (infrastructure management)</li>
                <li>HTML and CSS (content)</li>
            </ul>
        </section>
        <section>
            <h2>Next Steps</h2>
            <p>From here I can add a custom domain with Route 53, enable HTTPS with CloudFront, or automate deployments with a CI/CD pipeline.</p>
        </section>
    </main>
    <footer>
        <p>Deployed with the AWS CLI</p>
    </footer>
</body>
</html>
Add styling with CSS

Without CSS, your HTML page will look like plain text with default browser styling. A stylesheet transforms it into a polished, readable landing page.

  • In the VS Code Explorer sidebar, click the New File icon again.
  • Name the file style.css and press Enter.
  • Paste the following foundation styles into style.css:
/* Reset default browser margins and padding */
* {
    margin: 0;
    padding: 0;
    box-sizing: border-box;
}

/* Base page layout and typography */
body {
    font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
    line-height: 1.6;
    color: #333;
    max-width: 800px;
    margin: 0 auto;
    padding: 2rem;
    background-color: #f8f9fa;
}

/* Center-aligned header area */
header {
    text-align: center;
    padding: 3rem 0;
    border-bottom: 2px solid #e9ecef;
    margin-bottom: 2rem;
}

/* Main heading style */
header h1 {
    font-size: 2.5rem;
    color: #1a73e8;
    margin-bottom: 0.5rem;
}

/* Header subtitle */
header p {
    font-size: 1.2rem;
    color: #666;
}

What do these styles do?

The * selector resets all default margins and padding so every browser starts from the same baseline.

The body rule centers your content at a max width of 800px with comfortable padding. The header styles make your title large and blue, centered above a subtle border line.

  • Save style.css.

You will not see a visual change yet because you have not opened the page in a browser. The next chunk adds styling for the content sections.

Seeing a red underline or error highlight?

Check for missing semicolons at the end of property lines. Every CSS property line must end with a semicolon (;). Also make sure each opening curly brace { has a matching closing brace }.

help me fix a CSS syntax error in my style.css

  • Still in style.css, add the following styles below the header styles you just wrote:
/* Content card styling */
section {
    margin-bottom: 2rem;
    padding: 1.5rem;
    background: white;
    border-radius: 8px;
    box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);
}

/* Section heading color */
section h2 {
    color: #1a73e8;
    margin-bottom: 0.75rem;
}

/* Clean list without bullet points */
ul {
    list-style: none;
    padding: 0;
}

/* List items with subtle separators */
ul li {
    padding: 0.5rem 0;
    border-bottom: 1px solid #f0f0f0;
}

/* Remove border from last list item */
ul li:last-child {
    border-bottom: none;
}

/* Centered footer text */
footer {
    text-align: center;
    padding: 2rem 0;
    color: #999;
    font-size: 0.9rem;
}

What do these styles do?

Each section becomes a white card with rounded corners and a soft shadow, making your content blocks stand out against the gray background.

The list items get clean separators instead of bullet points. The footer sits at the bottom in small, muted text.

  • Save style.css.
  • You should see both index.html and style.css listed in the Explorer sidebar.

Only see one file in the sidebar?

Make sure you created style.css inside the same my-s3-website folder, not in a subfolder or a different location. Both files should be at the top level of the folder.

help me find where my style.css file was saved

✔️ Awesome, I've got everything!

Great. Double check you have saved style.css before moving on.

ⓧ I'd like to double check the full code

* {
    margin: 0;
    padding: 0;
    box-sizing: border-box;
}

body {
    font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
    line-height: 1.6;
    color: #333;
    max-width: 800px;
    margin: 0 auto;
    padding: 2rem;
    background-color: #f8f9fa;
}

header {
    text-align: center;
    padding: 3rem 0;
    border-bottom: 2px solid #e9ecef;
    margin-bottom: 2rem;
}

header h1 {
    font-size: 2.5rem;
    color: #1a73e8;
    margin-bottom: 0.5rem;
}

header p {
    font-size: 1.2rem;
    color: #666;
}

section {
    margin-bottom: 2rem;
    padding: 1.5rem;
    background: white;
    border-radius: 8px;
    box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);
}

section h2 {
    color: #1a73e8;
    margin-bottom: 0.75rem;
}

ul {
    list-style: none;
    padding: 0;
}

ul li {
    padding: 0.5rem 0;
    border-bottom: 1px solid #f0f0f0;
}

ul li:last-child {
    border-bottom: none;
}

footer {
    text-align: center;
    padding: 2rem 0;
    color: #999;
    font-size: 0.9rem;
}
Preview your site in the browser

Before deploying to AWS, you should confirm your site looks right locally. Opening the HTML file directly in your browser is the fastest way to check.

  • Open your file manager: Finder (macOS) or File Explorer (Windows).
  • Navigate to Desktop > my-s3-website.
  • Double-click index.html to open it in your default web browser.

You should see a page with a blue "Hello from AWS S3!" heading at the top, followed by three white card sections (What I Built, Technologies Used, Next Steps) on a light gray background.

Page looks like plain unstyled text?

This means your browser cannot find style.css. Check that style.css is in the same folder as index.html (both at the top level of my-s3-website).

Also confirm the filename in your HTML link tag is exactly style.css (lowercase, no spaces). The <link> tag in your <head> should read href="style.css".

help me figure out why my CSS is not loading

Your website is built and looks good locally. Next up, you will configure your S3 bucket to serve it to the world.

Configure Static Hosting and Permissions

Your bucket exists, but right now it is just an empty container with all public access locked down. S3 buckets are private by default, which means no one on the internet can see what is inside.

To turn your bucket into a live website, you need to do three things: tell S3 to serve your files as web pages, remove the built-in public access blocks, and attach a policy that explicitly allows visitors to read your files.

In this step, get ready to:
  • Enable static website hosting on your bucket.
  • Remove Block Public Access settings.
  • Create and apply a bucket policy granting public read access.
Enable static website hosting

S3 can serve files directly to browsers, but you have to opt in. Enabling static website hosting tells S3 which file to serve when someone visits the root URL and which file to show for errors.

  • Enable website hosting on your bucket by running this command:
aws s3 website s3://[[BUCKET_NAME="your-unique-bucket-name"]]/ --index-document index.html --error-document error.html

What does this command do?

The aws s3 website command configures your bucket as a static website host.

  • --index-document index.html tells S3 to serve index.html when someone visits the root URL.
  • --error-document error.html tells S3 which page to show when a visitor requests a path that does not exist.
  • If the command succeeds, you will see no output. That is normal for AWS CLI commands. No output means success.

Seeing an error?

  • Check that your bucket name matches exactly what you created in Step 2. Bucket names are case-sensitive.
  • Make sure the trailing slash after the bucket name is present in the s3:// URI.
  • Confirm your CLI is still configured by running aws --version. If that fails, re-run aws configure.

Help me troubleshoot my aws s3 website command

Remove Block Public Access

AWS applies a safety layer called Block Public Access to every new bucket. This prevents any public policy from taking effect until you explicitly remove the blocks.

  • Remove the Block Public Access settings from your bucket by running this command:
aws s3api delete-public-access-block --bucket [[BUCKET_NAME="your-unique-bucket-name"]]

Why do I need to remove Block Public Access?

Block Public Access is a four-part safety net that AWS enables by default on every S3 bucket. It overrides any bucket policy you apply, so even if you attach a public read policy, visitors still cannot access your files while these blocks are in place.

Removing the blocks does not make your bucket public on its own. It simply allows your bucket policy (which you will create next) to take effect.

  • If the command succeeds, you will see no output. No output means success.

Getting an access denied error?

  • Your IAM user may not have the s3:PutBucketPublicAccessBlock permission. Check that your IAM user has the AmazonS3FullAccess policy attached.
  • Double-check the bucket name matches exactly what you used in Step 2.

Help me fix my delete-public-access-block error

Create and apply the bucket policy

A bucket policy is a JSON document that tells AWS exactly who can do what with your bucket's contents. You will create a policy that grants everyone on the internet permission to read your files.

  • In your project folder, create a new file called policy.json and paste in the following content:
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "PublicReadGetObject",
            "Effect": "Allow",
            "Principal": "*",
            "Action": [
                "s3:GetObject"
            ],
            "Resource": [
                "arn:aws:s3:::[[BUCKET_NAME="your-unique-bucket-name"]]/*"
            ]
        }
    ]
}

What does this policy do?

  • Version is the policy language version. 2012-10-17 is the current and only version you should use.
  • Principal: "*" means anyone on the internet.
  • Action: "s3:GetObject" allows reading (downloading) objects from your bucket.
  • Resource targets every object inside your bucket using the /* wildcard at the end of the ARN.
  • Save policy.json.
  • Confirm the file exists by running:
ls
  • You should see policy.json alongside index.html and style.css in the output.

Don't see policy.json?

  • Make sure you saved the file in the same project folder where index.html lives.
  • Check that your terminal is in the correct directory. Run pwd to see your current location.

Help me find my policy.json file

  • Apply the bucket policy to your S3 bucket by running this command:
aws s3api put-bucket-policy --bucket [[BUCKET_NAME="your-unique-bucket-name"]] --policy file://policy.json

What does this command do?

The aws s3api put-bucket-policy command uploads your JSON policy and attaches it to the bucket. The file:// prefix tells the CLI to read the policy from a local file instead of expecting it inline.

  • If the command succeeds, you will see no output. Your bucket is now publicly readable.

Seeing 'MalformedPolicy' or access denied?

  • If you see a MalformedPolicy error, open policy.json and check that the bucket name in the Resource field matches your actual bucket name exactly.
  • Make sure you removed Block Public Access in the previous substep. The policy cannot be applied while those blocks are active.
  • Confirm there are no extra commas or missing brackets in your JSON. JSON is strict about syntax.

Help me fix my bucket policy error

✔️ Awesome, I've got everything!

Great. Double check you have saved policy.json in your project folder.

ⓧ I'd like to double check the full code

Here is the complete policy.json file for comparison:

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "PublicReadGetObject",
            "Effect": "Allow",
            "Principal": "*",
            "Action": [
                "s3:GetObject"
            ],
            "Resource": [
                "arn:aws:s3:::[[BUCKET_NAME="your-unique-bucket-name"]]/*"
            ]
        }
    ]
}

Your bucket is now a fully configured web host with public read access. Next up, you will upload your website files and see your site live on the internet.

Upload and Go Live

Your S3 bucket is fully configured with static hosting, public access, and a bucket policy. The only thing left is to get your files up there.

In this step, you'll upload your website to S3 with a single command and visit your live URL to confirm the deployment worked.

In this step, get ready to:
  • Upload your website files to S3.
  • Visit your live website URL.
  • Test the default error page behavior.
Upload your website files to S3

The aws s3 sync command compares your local folder with your S3 bucket and uploads any new or changed files. This means you can run it repeatedly and it will only transfer what's different.

  • Make sure your terminal is in your project folder (the one containing index.html and style.css).
  • Upload all your files to S3 by running this command:
aws s3 sync . s3://[[BUCKET_NAME="your-unique-bucket-name"]]

What does this command do?

The . refers to your current directory. The command uploads every file in this folder to your S3 bucket.

Because sync is smart about detecting changes, you can re-run it after editing files and only the modified ones will be re-uploaded.

  • You should see output lines like upload: ./index.html to s3://your-bucket-name/index.html for each file transferred.

Not seeing any upload output?

Make sure you are in the correct folder. Run ls (macOS/Linux) or dir (Windows) and confirm you see index.html and style.css listed.

If you see an "Access Denied" error, double-check that your aws configure credentials match the IAM user you created in Step 1.

Help me troubleshoot my aws s3 sync command

Visit your live website

Your files are now in S3. Because you already enabled static website hosting in the previous step, AWS is serving those files as a website at a public URL.

  • Open your browser and paste your website URL. The format is:
http://[[BUCKET_NAME="your-unique-bucket-name"]].s3-website-us-east-1.amazonaws.com

How is this URL constructed?

AWS generates this URL automatically when you enable static website hosting. It combines your bucket name with the region and the s3-website prefix.

This endpoint uses HTTP, not HTTPS. Adding HTTPS would require CloudFront, which is outside the scope of this project.

  • Confirm your styled landing page loads in the browser. You should see a blue heading that says "Hello from AWS S3!" with white card sections below it.
  • Now test the error behavior by adding a path that does not exist to the end of your URL, like /nonexistent.
  • You should see a basic XML error response from S3. This is the default behavior because you have not created an error.html file yet.

Seeing a 403 Forbidden error?

This usually means the bucket policy was not applied correctly in the previous step. Run aws s3api get-bucket-policy --bucket your-bucket-name to verify the policy is in place.

Also confirm that Block Public Access was removed. If any of the four block settings are still active, the policy cannot grant public access.

Help me fix my 403 Forbidden error on S3 static hosting

Your site is live on the internet. In the Secret Mission, you'll replace that ugly default error response with a polished custom 404 page.

Secret mission

Add a Custom 404 Error Page

Your website already handles missing pages with a default error. But what if you could show visitors a friendly, on-brand page instead? In this secret mission, you'll design and deploy a custom 404 error page that matches your site's styling.

Clean Up Your Resources

Clean Up Your Resources

Decide whether to keep your resources running, pause them to come back later, or delete them entirely. This project uses S3 storage that falls within the AWS Free Tier for 12 months. After that, a few HTML and CSS files cost fractions of a cent per month.

Cost warning

Your S3 bucket has a public bucket policy, meaning anyone on the internet can read its contents. While storage costs are negligible, keep this in mind if you later add files you do not want to be publicly accessible.

Resources you used:

  • 1 S3 bucket with static website hosting enabled, a public bucket policy, and uploaded website files.
  • Local project folder containing index.html, style.css, and policy.json.

Keep everything running

No action needed. Choose this if you are still actively building or want your site to remain live.

  • Your website stays accessible at its S3 endpoint URL.
  • Storage costs remain within Free Tier for 12 months. After that, a handful of files costs less than $0.01 per month.
  • The AWS CLI remains installed on your machine for future projects.

Pause - I'll come back to this later

Remove public access so your site is no longer live, but keep all files in the bucket for when you want to come back.

  • Remove the public bucket policy by running:
  • This makes your bucket private again. Your files stay in the bucket, but nobody can access them from the internet.
aws s3api delete-bucket-policy --bucket [[BUCKET_NAME="your-unique-bucket-name"]]

When you are ready to go live again, re-apply your bucket policy using the same aws s3api put-bucket-policy command from Step 4.

Delete - I don't want to use this again

Remove all project resources and start fresh. This deletes your S3 bucket and all its contents permanently.

  • Delete all objects from your bucket by running:
aws s3 rm s3://[[BUCKET_NAME="your-unique-bucket-name"]] --recursive
  • Delete the empty bucket by running:
aws s3api delete-bucket --bucket [[BUCKET_NAME="your-unique-bucket-name"]]
  • Verify the bucket is gone by running:
aws s3 ls

Your bucket should no longer appear in the list.

  • Delete your local project folder. On macOS or Linux, run:
rm -rf ~/Desktop/my-s3-website
  • On Windows, run:
rmdir /s /q %USERPROFILE%\Desktop\my-s3-website

That's a Wrap!

That's a Wrap!

You just deployed a website to the cloud using nothing but your terminal. Welcome to cloud engineering.

Here's what you learned:

  • Created an S3 bucket from the command line and configured it for static website hosting with index and error documents.
  • Wrote and applied a bucket policy granting public read access by removing Block Public Access settings.
  • Uploaded files using aws s3 sync and verified your live site at a public S3 endpoint URL.
  • Secret Mission: Added a custom-styled 404 error page for broken links.

Ready to quiz yourself?