Deploy a Static Website with Terraform
Use Terraform to provision an S3 bucket and deploy a live static website on AWS.
Introduction
30 Second Summary
Every time you visit a website, a server somewhere is hosting those files and delivering them to your browser. Cloud engineers set up that hosting infrastructure, and the best ones do it using code instead of clicking through dashboards.
In this project, you will deploy a personal profile page to AWS S3 using Terraform. You will write code that defines your cloud infrastructure, then run a single command to bring it to life.
What You'll Build
A static website hosted on AWS S3, provisioned and deployed entirely through Terraform configuration files.
By the end of this project, you'll have:
- A Terraform configuration file that provisions an S3 bucket for static website hosting.
- A live website URL anyone on the internet can visit.
- Hands-on experience with the core Terraform workflow (init, plan, apply, destroy).
- Secret Mission: Add a custom 404 error page and configure your bucket to handle missing pages gracefully.
Are there any prerequisites?
You need an AWS account (free tier is fine) and VS Code installed on your machine. No prior experience with Terraform or Infrastructure as Code is required.
Before We Start
Before you can deploy infrastructure to AWS with code, you need two command-line tools installed on your machine.
The AWS CLI lets you talk to AWS from your terminal. Terraform lets you define cloud resources as code and deploy them in one command.
In this step, get ready to:
- Install the AWS CLI.
- Install Terraform.
- Configure your AWS credentials so both tools can access your account.
Install the AWS CLI
The AWS CLI is a tool that lets you run AWS commands directly from your terminal instead of clicking through the console.
- Press Cmd+Space (macOS) or the Windows key (Windows) to open your search bar.
- Type VS Code and press Enter to open it.
Now download and install the AWS CLI for your operating system.
macOS
- In your browser, download the macOS installer from:
https://awscli.amazonaws.com/AWSCLIV2.pkg
- Open the downloaded AWSCLIV2.pkg file and follow the on-screen prompts to install.
- Click Continue through each screen, then click Install.
- You may need to enter your Mac password to authorize the install.
Windows
- In your browser, download the Windows MSI installer from:
https://awscli.amazonaws.com/AWSCLIV2.msi
- Open the downloaded AWSCLIV2.msi file and follow the on-screen prompts to install.
- Click Next through each screen, then click Install.
- Once the install completes, open a new terminal in VS Code by pressing Ctrl+` (backtick key, below Escape).
- Verify your installation by running this command:
aws --version
Check what you see in the terminal output:
✔️ I see aws-cli/2.x.x
The AWS CLI is installed and ready to go.
ⓧ I see aws-cli/1.x.x
You have an older version of the AWS CLI installed. Version 1 is deprecated and missing features this project needs.
- Uninstall the old version using your original install method (pip uninstall awscli or your package manager).
- Follow the install steps above to download and install version 2.
- Open a new terminal and run aws --version again to confirm you see aws-cli/2.x.x.
ⓧ Command not found
The terminal cannot find the aws command. This usually means the installer did not add it to your PATH.
- Close the terminal and open a brand new one (the PATH updates only apply to new terminals).
- If it still does not work, restart VS Code entirely and try again.
- On macOS, the installer creates a symlink at /usr/local/bin/aws. Confirm this file exists.
- On Windows, re-run the MSI installer and ensure you complete all prompts.
Install Terraform
Terraform is the Infrastructure as Code tool you will use to define and deploy your AWS resources. The install method depends on your operating system.
macOS
On macOS, the easiest way to install Terraform is through Homebrew.
- Install Terraform by running these two commands in your VS Code terminal:
brew tap hashicorp/tap
brew install hashicorp/tap/terraform
What do these commands do?
The first command adds HashiCorp's official package repository (called a "tap") to Homebrew. The second command installs Terraform from that repository.
Seeing 'brew: command not found'?
You need to install Homebrew first. Visit https://brew.sh and follow the one-line install command, then try the Terraform commands again.
How do I install Homebrew on macOS?
Windows
On Windows, you will download Terraform as a standalone binary and add it to your PATH.
- Go to https://developer.hashicorp.com/terraform/install in your browser.
- Under Windows, click the AMD64 binary download link.
- Extract the downloaded zip file. Inside you will find a single file called terraform.exe.
- Move terraform.exe to a permanent folder, for example C:\terraform.
- Open the Windows Start menu and search for Environment Variables.
- Click Edit the system environment variables.
- Click Environment Variables at the bottom of the dialog.
- Under System variables, find and select Path, then click Edit.
- Click New and add C:\terraform.
- Click OK on all dialogs to save.
Why add Terraform to PATH?
Adding a folder to your system PATH tells Windows where to find the terraform command. Without this, your terminal would not recognize the command.
- Open a new terminal in VS Code (close any existing terminals first so the PATH updates take effect).
- Verify your installation by running this command:
terraform -version
Check what you see in the terminal output:
✔️ I see Terraform v1.15.x
Terraform is installed and ready. You should see Terraform v1.15.7 or a similar recent version number.
ⓧ I see an older version
You have an older version of Terraform installed from a previous project. This project works best with version 1.15.x.
- On macOS, upgrade by running:
brew update
brew upgrade hashicorp/tap/terraform
- On Windows, download the latest binary from https://developer.hashicorp.com/terraform/install and replace the old terraform.exe in your C:\terraform folder.
- Open a new terminal and run terraform -version again.
ⓧ Command not found
The terminal cannot find terraform. This usually means it is not on your PATH.
- Close and reopen your terminal (PATH changes only apply to new terminal sessions).
- On Windows, double-check that C:\terraform appears in your system PATH and that terraform.exe exists inside that folder.
- On macOS, re-run brew install hashicorp/tap/terraform and check for errors.
- If you still have trouble, restart VS Code entirely and try again.
Still stuck?
Help me troubleshoot why terraform -version is not working.
Configure AWS CLI credentials
For Terraform to create resources in your AWS account, it needs credentials. You will create an access key in the AWS console and feed it to the AWS CLI.
- Open your browser and sign in to the AWS Console at https://console.aws.amazon.com.
- In the top search bar, type IAM and select IAM from the results.
- In the left sidebar, click Users.
- Click on your username.
- Click 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, then click Next.
- Click Create access key.
- Click Download .csv file to save your credentials. Keep this file safe and do not share it.
What is an access key?
An IAM access key is a pair of values: an Access Key ID and a Secret Access Key. Together, they prove your identity to AWS when you run commands from the terminal instead of the web console.
- Switch back to your VS Code terminal.
- Configure the AWS CLI with your new credentials by running:
aws configure
What will this command ask me?
The aws configure command prompts you for four values, one at a time. Enter each value and press Enter:
- 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 .csv file.
- Default region name - type us-east-1.
- Default output format - type json.
- Enter each value when prompted, using the values from your .csv file for the first two and us-east-1 and json for the last two.
- Verify that your credentials work by running:
aws sts get-caller-identity
You should see a JSON response showing your Account ID, UserId, and ARN. This confirms the AWS CLI can successfully authenticate with your account.
Seeing 'Unable to locate credentials'?
This means aws configure did not save your credentials correctly. Run aws configure again and make sure you paste the values without any extra spaces or line breaks.
Double-check that you copied both the Access Key ID and Secret Access Key from the .csv file. They are two separate values.
Help me fix my AWS CLI credential configuration.
Your development environment is locked and loaded. Next up, you will write Terraform code that tells AWS exactly what infrastructure to create.
Install Your Tools
To deploy infrastructure on AWS using code, you need two command-line tools installed on your machine.
The AWS CLI lets you talk to AWS from your terminal. Terraform reads your configuration files and turns them into real cloud resources.
In this step, get ready to:
- Install and verify the AWS CLI.
- Install and verify Terraform.
- Configure AWS CLI credentials so Terraform can authenticate with your AWS account.
Install the AWS CLI
The AWS CLI is a tool that lets you run AWS commands directly from your terminal instead of clicking through the AWS Console.
- Open a terminal in VS Code by pressing Ctrl+` (macOS and Windows).
- Check if the AWS CLI is already installed by running this command:
aws --version
✔️ I see a version number
You should see output starting with aws-cli/2.x.x. The AWS CLI is ready to go.
ⓧ Command not found
The AWS CLI is not installed yet. Follow the instructions for your operating system below.
macOS
- Download the macOS installer by visiting this URL in your browser:
- https://awscli.amazonaws.com/AWSCLIV2.pkg
- Run the downloaded AWSCLIV2.pkg file and follow the on-screen prompts.
- When prompted, install for all users (this requires your system password).
- Once the installer finishes, close and reopen your VS Code terminal.
- Verify the installation by running:
aws --version
You should see output starting with aws-cli/2.x.x.
Windows
- Download the Windows MSI installer from this URL:
- https://awscli.amazonaws.com/AWSCLIV2.msi
- Run the downloaded AWSCLIV2.msi file and follow the prompts to complete the installation.
- Once the installer finishes, close and reopen your VS Code terminal.
- Verify the installation by running:
aws --version
You should see output like aws-cli/2.x.x Python/3.x.x Windows/10 exe/AMD64.
Still seeing command not found?
Make sure you opened a new terminal after installing. The old terminal session does not know about newly installed programs.
On Windows, try closing VS Code entirely and reopening it.
help me troubleshoot why aws --version is not working after installing the AWS CLI
Install Terraform
Terraform is the tool that reads your infrastructure code and creates the matching resources on AWS.
- Check if Terraform is already installed by running this command:
terraform -version
✔️ I see a version number
You should see output starting with Terraform v1.15 or similar. Terraform is ready to go.
ⓧ Command not found
Terraform is not installed yet. Follow the instructions for your operating system below.
macOS
On macOS, the official install method uses Homebrew.
- Add the HashiCorp tap by running:
brew tap hashicorp/tap
- Install Terraform from the tap by running:
brew install hashicorp/tap/terraform
- Verify the installation by running:
terraform -version
You should see Terraform v1.15.7 or a similar version number.
What if I don't have Homebrew?
Homebrew is a package manager for macOS. If you don't have it, visit https://brew.sh and follow the one-line install command on the homepage.
Windows
On Windows, you can install Terraform using Chocolatey or by downloading the binary directly.
Option A: Chocolatey (recommended if you have it)
- Run this command in an elevated terminal:
choco install terraform
Chocolatey handles the download and PATH configuration for you.
Option B: Manual binary download
- Go to https://developer.hashicorp.com/terraform/install.
- Under Windows, download the AMD64 zip file.
- Extract the terraform.exe file to a folder, for example C:\terraform.
- Add that folder to your system PATH by opening System settings.
- Click Environment Variables.
- Select Path in the list, then click New.
- Type C:\terraform and click OK.
- Close and reopen your VS Code terminal, then verify by running:
terraform -version
You should see Terraform v1.15.7.
Terraform command still not found?
On Windows, make sure you added the correct folder to your PATH and opened a new terminal. The PATH change only applies to new terminal sessions.
On macOS, make sure the brew tap command finished without errors before running brew install.
help me troubleshoot why terraform -version is not working
Configure AWS CLI credentials
Terraform uses the AWS CLI's credentials to authenticate with your AWS account. You need to create an access key in the AWS Console and then store it locally using aws configure.
- Log in to the AWS Console in your browser.
- Search for IAM in the top search bar and open the IAM service.
- In the left sidebar, click Users.
- Click on your username.
- Click 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 and click Next.
- Click Create access key.
- Download the .csv file with your Access Key ID and Secret Access Key. Keep this file safe.
Why download the CSV?
AWS only shows your Secret Access Key once. After you close this page, you cannot retrieve it again. Downloading the CSV ensures you have a backup.
- Back in your VS Code terminal, configure the AWS CLI by running:
aws configure
What does aws configure ask for?
The command prompts you for four values:
- AWS Access Key ID: paste the Access Key ID from your downloaded CSV.
- AWS Secret Access Key: paste the Secret Access Key from your CSV.
- Default region name: type us-east-1.
- Default output format: type json.
- Enter each value when prompted, pressing Enter after each one.
- Verify your credentials are working by running:
aws sts get-caller-identity
You should see a JSON response with your Account ID, user ARN, and user ID. This confirms Terraform will be able to authenticate with AWS.
Seeing an access denied or invalid credentials error?
Double-check that you pasted the correct Access Key ID and Secret Access Key. They are case-sensitive and must not include extra spaces.
If your access key was created for a different region or has restricted permissions, the call may fail. Make sure your IAM user has sufficient permissions.
help me fix aws sts get-caller-identity returning an error
Your tools are installed and authenticated. Next up, you will write your first Terraform configuration file that tells AWS exactly what infrastructure to create.
Write Your Terraform Configuration
In the last step, you installed your tools and connected to AWS. Now it's time to write the code that tells AWS exactly what infrastructure to create.
Instead of clicking through the AWS console, you will define your resources in a .tf file. Terraform reads this file and handles the provisioning for you.
In this step, get ready to:
- Create your Terraform configuration file.
- Define the AWS provider and S3 bucket resources.
- Add an output to display your website URL.
Create your Terraform configuration file
Every Terraform project needs at least one .tf file. This is where you describe the infrastructure you want to exist.
- In VS Code, press Cmd+N (macOS) or Ctrl+N (Windows) to create a new file.
- Save it immediately with Cmd+S (macOS) or Ctrl+S (Windows).
- Name the file main.tf and save it inside your my-first-terraform folder.
- Confirm main.tf appears in the Explorer sidebar on the left side of VS Code.
Don't see the Explorer sidebar?
Press Cmd+Shift+E (macOS) or Ctrl+Shift+E (Windows) to toggle it open.
Help me find the Explorer sidebar in VS Code.
Define the AWS provider and S3 bucket
Terraform needs to know which cloud provider you are using and what resources to create. You will define both in main.tf.
- Add the provider configuration to main.tf by pasting the following code:
# Tell Terraform which provider plugin to download
terraform {
required_providers {
aws = {
source = "hashicorp/aws"
version = "~> 5.0"
}
}
}
# Configure the AWS provider with your region
provider "aws" {
region = "us-east-1"
}
What does this code do?
- The terraform block tells Terraform to download the hashicorp/aws provider plugin. The ~> 5.0 version constraint means any version in the 5.x range is acceptable.
- The provider "aws" block configures that plugin to create resources in the us-east-1 region. This matches the region you set during aws configure in Step 1.
- You won't see any output yet. The next step (terraform init) will verify Terraform can connect to AWS using this configuration.
- Now add the S3 bucket and supporting resources below your provider block in main.tf:
# Create an S3 bucket with a unique name
resource "aws_s3_bucket" "website" {
bucket = "my-terraform-website-${random_string.suffix.result}"
}
# Generate a random 8-character suffix for the bucket name
resource "random_string" "suffix" {
length = 8
special = false
upper = false
}
# Set bucket ownership controls for ACL support
resource "aws_s3_bucket_ownership_controls" "website" {
bucket = aws_s3_bucket.website.id
rule {
object_ownership = "BucketOwnerPreferred"
}
}
# Allow public access to the bucket (required for website hosting)
resource "aws_s3_bucket_public_access_block" "website" {
bucket = aws_s3_bucket.website.id
block_public_acls = false
block_public_policy = false
ignore_public_acls = false
restrict_public_buckets = false
}
# Enable static website hosting on the bucket
resource "aws_s3_bucket_website_configuration" "website" {
bucket = aws_s3_bucket.website.id
index_document {
suffix = "index.html"
}
}
What do these resources do?
- aws_s3_bucket creates the bucket itself. The name includes a random suffix because S3 bucket names must be globally unique across all of AWS.
- random_string generates an 8-character random string (lowercase letters and numbers only) to append to your bucket name.
- aws_s3_bucket_ownership_controls sets the bucket to BucketOwnerPreferred, which enables ACL-based permissions on objects.
- aws_s3_bucket_public_access_block disables all four public access restrictions. This is required for a public website.
- aws_s3_bucket_website_configuration enables static website hosting and tells S3 to serve index.html as the home page.
- Save main.tf with Cmd+S (macOS) or Ctrl+S (Windows).
- You won't see output yet. In the next step, terraform plan will show you exactly what these resources create.
Seeing red squiggly lines in main.tf?
VS Code may not recognize .tf files by default. This is cosmetic and does not affect Terraform. The syntax highlighting improves if you install the HashiCorp Terraform extension from the VS Code marketplace, but it is not required for this project.
Help me fix syntax highlighting for Terraform files in VS Code.
Add an output to display your website URL
Once Terraform creates your website, you need to know its URL. An output block prints important values to your terminal after Terraform finishes.
- Add this output block at the bottom of main.tf, below the website configuration resource:
# Print the website URL after deployment
output "website_url" {
value = aws_s3_bucket_website_configuration.website.website_endpoint
}
What does this output do?
The website_endpoint attribute is the public URL that S3 assigns to your hosted website. After you run terraform apply in the next step, Terraform prints this URL so you can visit your live site immediately.
- Save main.tf.
✔️ Awesome, I've got everything!
Great. Double check you have saved main.tf and that it contains the provider block, all five resources, and the output block.
ⓧ I'd like to double check the full code
Here is the complete main.tf file. Make sure your code matches this exactly:
terraform {
required_providers {
aws = {
source = "hashicorp/aws"
version = "~> 5.0"
}
}
}
provider "aws" {
region = "us-east-1"
}
resource "aws_s3_bucket" "website" {
bucket = "my-terraform-website-${random_string.suffix.result}"
}
resource "random_string" "suffix" {
length = 8
special = false
upper = false
}
resource "aws_s3_bucket_ownership_controls" "website" {
bucket = aws_s3_bucket.website.id
rule {
object_ownership = "BucketOwnerPreferred"
}
}
resource "aws_s3_bucket_public_access_block" "website" {
bucket = aws_s3_bucket.website.id
block_public_acls = false
block_public_policy = false
ignore_public_acls = false
restrict_public_buckets = false
}
resource "aws_s3_bucket_website_configuration" "website" {
bucket = aws_s3_bucket.website.id
index_document {
suffix = "index.html"
}
}
output "website_url" {
value = aws_s3_bucket_website_configuration.website.website_endpoint
}
Why Infrastructure as Code instead of the AWS console?
Clicking through the AWS console works once, but it is impossible to reproduce reliably. If you need to rebuild your infrastructure or share it with a teammate, you would have to remember every setting you clicked.
With Infrastructure as Code, your entire setup lives in a file you can version control, review, and run again in seconds. This is why IaC is the number one skill hiring managers look for in junior cloud engineers.
Your Terraform configuration is complete. Next up, you will create the HTML page that Terraform uploads to your S3 bucket.
Create Your Website Content
Your Terraform configuration knows how to create an S3 bucket and configure it for web hosting. But a website needs actual content to display.
In this step, you will create an HTML profile page and tell Terraform to upload it to your bucket. This is where Infrastructure as Code gets powerful. Instead of manually uploading files through the AWS console, Terraform handles the deployment for you.
In this step, get ready to:
- Create an HTML profile page for your website.
- Add a Terraform resource that uploads the page to your S3 bucket.
Create your HTML profile page
Every website needs an index.html file. This is the page visitors see when they open your website URL.
- In the VS Code Explorer sidebar, right-click inside the my-first-terraform folder.
- Select New File.
- Name it index.html and press Enter.
- Paste the following HTML into the file:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>My Cloud Portfolio</title>
<style>
body {
font-family: system-ui, -apple-system, sans-serif;
max-width: 600px;
margin: 80px auto;
padding: 20px;
background-color: #f8f9fa;
color: #333;
}
h1 {
color: #232f3e;
}
.badge {
display: inline-block;
background-color: #232f3e;
color: #ff9900;
padding: 4px 12px;
border-radius: 4px;
font-size: 0.85rem;
margin-top: 20px;
}
</style>
</head>
<body>
<h1>Hello, I'm [Your Name]</h1>
<p>I'm learning cloud engineering and this is my first project deployed with Infrastructure as Code.</p>
<p>This website is hosted on AWS S3 and was deployed entirely using Terraform.</p>
<span class="badge">Deployed with Terraform</span>
</body>
</html>
What does this page do?
This is a simple profile page with inline CSS styling. It includes a heading with your name, two paragraphs about your cloud journey, and an orange badge that says "Deployed with Terraform".
The styling uses AWS's brand colors (#232f3e dark blue and #ff9900 orange) to give it a professional cloud engineering look.
- Replace [Your Name] in the <h1> tag with your actual name.
- Save index.html by pressing Cmd+S (macOS) or Ctrl+S (Windows).
- Confirm the file exists by running:
ls
You should see both index.html and main.tf listed in the output.
Only see main.tf?
Make sure you created the file inside the my-first-terraform folder, not in a subfolder or parent directory. Check the VS Code Explorer sidebar to confirm index.html appears at the same level as main.tf.
help me find where my index.html file was created
Upload the file using Terraform
Your HTML file exists on your computer, but it needs to live in your S3 bucket for visitors to see it. Terraform can handle this upload for you using an aws_s3_object resource.
- Switch back to main.tf in VS Code.
- Find the output "website_url" block at the bottom of the file.
- Add the following resource above the output block:
resource "aws_s3_object" "index" {
# Upload index.html to the S3 bucket
bucket = aws_s3_bucket.website.id
key = "index.html"
source = "index.html"
content_type = "text/html"
acl = "public-read"
# Wait until public access is enabled before setting ACL
depends_on = [aws_s3_bucket_public_access_block.website]
}
What does this resource do?
- bucket tells Terraform which S3 bucket to upload the file to.
- key is the name the file will have inside the bucket.
- source points to the local file on your machine.
- content_type ensures browsers render it as a webpage rather than downloading it as a file.
- acl set to public-read allows anyone on the internet to view the file.
- depends_on makes Terraform wait until the public access block is configured before uploading. Without this, the upload could fail because the bucket might not yet allow public ACLs.
- Save main.tf.
Seeing red squiggly lines in VS Code?
If VS Code shows syntax warnings, make sure your new resource block is placed between the closing } of the aws_s3_bucket_website_configuration resource and the output block. Check that every opening { has a matching closing }.
help me fix my main.tf syntax
✔️ Awesome, I've got everything!
Great. Double check you've saved both files before moving on.
ⓧ I'd like to double check the full code
Here is the complete main.tf file as it should look now:
terraform {
required_providers {
aws = {
source = "hashicorp/aws"
version = "~> 5.0"
}
}
}
provider "aws" {
region = "us-east-1"
}
resource "aws_s3_bucket" "website" {
bucket = "my-terraform-website-${random_string.suffix.result}"
}
resource "random_string" "suffix" {
length = 8
special = false
upper = false
}
resource "aws_s3_bucket_ownership_controls" "website" {
bucket = aws_s3_bucket.website.id
rule {
object_ownership = "BucketOwnerPreferred"
}
}
resource "aws_s3_bucket_public_access_block" "website" {
bucket = aws_s3_bucket.website.id
block_public_acls = false
block_public_policy = false
ignore_public_acls = false
restrict_public_buckets = false
}
resource "aws_s3_bucket_website_configuration" "website" {
bucket = aws_s3_bucket.website.id
index_document {
suffix = "index.html"
}
}
resource "aws_s3_object" "index" {
bucket = aws_s3_bucket.website.id
key = "index.html"
source = "index.html"
content_type = "text/html"
acl = "public-read"
depends_on = [aws_s3_bucket_public_access_block.website]
}
output "website_url" {
value = aws_s3_bucket_website_configuration.website.website_endpoint
}
And here is the complete index.html file:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>My Cloud Portfolio</title>
<style>
body {
font-family: system-ui, -apple-system, sans-serif;
max-width: 600px;
margin: 80px auto;
padding: 20px;
background-color: #f8f9fa;
color: #333;
}
h1 {
color: #232f3e;
}
.badge {
display: inline-block;
background-color: #232f3e;
color: #ff9900;
padding: 4px 12px;
border-radius: 4px;
font-size: 0.85rem;
margin-top: 20px;
}
</style>
</head>
<body>
<h1>Hello, I'm [Your Name]</h1>
<p>I'm learning cloud engineering and this is my first project deployed with Infrastructure as Code.</p>
<p>This website is hosted on AWS S3 and was deployed entirely using Terraform.</p>
<span class="badge">Deployed with Terraform</span>
</body>
</html>
Your website content is ready and Terraform knows how to upload it. Next up, you will run Terraform to actually create all of these resources in AWS and get your website live on the internet.
Deploy Your Infrastructure
Your Terraform configuration is complete and your website file is ready to go. Now it's time to bring your infrastructure to life on AWS.
Terraform uses a three-command workflow to deploy infrastructure: initialize, plan, then apply. This gives you a chance to preview exactly what will be created before anything changes in your AWS account.
In this step, get ready to:
- Initialize Terraform and download the AWS provider plugin.
- Preview the infrastructure Terraform will create.
- Deploy your website live to the internet.
Initialize Terraform
Before Terraform can create any resources, it needs to download the provider plugins specified in your configuration. The terraform init command sets up your working directory and fetches the AWS provider.
- Initialize your Terraform project by running this command in your VS Code terminal:
terraform init
You should see output ending with the message Terraform has been successfully initialized!
What does this command do?
This command downloads the AWS provider plugin into a hidden .terraform directory in your project folder. It also creates a .terraform.lock.hcl file that locks the exact provider version used.
You only need to run terraform init once per project, or again if you change providers or modules.
Seeing an error about providers?
Make sure your terminal is open inside the my-first-terraform folder where your main.tf file lives. Terraform looks for configuration files in the current directory.
If you see a network error, check your internet connection. Terraform needs to download the provider plugin from the HashiCorp registry.
help me fix a terraform init error
Preview your changes
Now that Terraform is initialized, you can preview what it will create in your AWS account without actually making any changes. This is the safety check that makes Infrastructure as Code so powerful.
- Preview your infrastructure plan by running:
terraform plan
You should see a summary line at the bottom that says Plan: 6 to add, 0 to change, 0 to destroy.
What does the plan show?
The plan lists every resource Terraform will create, marked with a + symbol. Your 6 resources are the S3 bucket, the random string suffix, ownership controls, the public access block, the website configuration, and the uploaded index.html object.
Values shown as (known after apply) mean Terraform can't determine them until the resources actually exist. Your bucket name falls into this category because it depends on the random string.
Seeing credential errors?
If the plan fails with an authentication error, your AWS CLI credentials may not be configured correctly. Run aws sts get-caller-identity to check that your credentials are working.
help me fix terraform plan credential errors
Apply your configuration
The plan looks good. Now it's time to make it real. The terraform apply command will create all 6 resources in your AWS account and give you a live website URL.
- Deploy your infrastructure by running:
terraform apply
What happens when you run this?
Terraform will show you the plan one more time and ask for confirmation. It displays the prompt: Do you want to perform these actions? followed by Enter a value:
Only typing yes (the full word) will proceed. This safety prompt prevents accidental infrastructure changes.
- Type yes when Terraform asks for confirmation, then press Enter.
Terraform will create each resource and display progress updates. Once complete, you should see Apply complete! Resources: 6 added, 0 changed, 0 destroyed. followed by your website_url output.
- Copy the website_url value from the terminal output.
- Paste it into your browser's address bar and press Enter.
You should see your profile page live on the internet. The page displays your name, bio, and the "Deployed with Terraform" badge.
Page not loading?
Make sure you're using http:// (not https://) when pasting the URL. S3 website endpoints use HTTP by default.
If you see an access denied error, the public access block or ACL may not have applied correctly. Run terraform apply again to retry.
help me fix my S3 website not loading
Secret mission
Add a Custom Error Page
Your website works great when visitors land on the right page. But what happens when they visit a URL that doesn't exist? Right now, they get an ugly default XML error from AWS. Let's fix that with a custom 404 page.
Clean Up Your Resources
Clean Up Your Resources
Decide whether to keep your resources running or delete them entirely. This project stays well within AWS Free Tier limits (5 GB storage, 20,000 GET requests, 2,000 PUT requests per month for 12 months).
Cost warning
Your S3 bucket is covered by the AWS Free Tier for the first 12 months of your AWS account. After that period, you will be charged for storage and requests. If your free tier has expired, run the delete steps below to avoid charges.
Resources you used:
- S3 bucket (my-terraform-website-<suffix>) with static website hosting, including index.html and error.html objects.
- Local project folder my-first-terraform on your Desktop.
Keep everything running
No action needed. Choose this if you plan to keep building on this project or want your website to stay live.
- Your site remains accessible at its S3 website URL at no cost within free tier limits.
- Your local my-first-terraform folder stays on your Desktop with all Terraform state intact.
Pause - I'll come back to this later
There is no "pause" option for S3 static websites. Your bucket either exists (and serves traffic) or it doesn't.
- If you want to keep the infrastructure definition but remove the live resources, run the delete steps below. Your local main.tf and HTML files will remain on your machine, so you can re-deploy later with terraform apply.
- If you're comfortable with the minimal free tier cost, choose "Keep everything running" instead.
Delete - I don't want to use this again
Remove all AWS resources Terraform created and delete your local project files.
- In VS Code, open the terminal in your my-first-terraform folder.
- Run the following command to destroy all AWS resources:
terraform destroy
- Type yes when prompted to confirm.
- Wait for Terraform to finish. You should see "Destroy complete" with the number of resources destroyed.
- Delete your local project folder. On macOS/Linux, run:
cd ~/Desktop
rm -rf my-first-terraform
- On Windows, run:
cd ~\Desktop
rmdir /s /q my-first-terraform
- Your S3 bucket and all its contents are now removed from AWS. Your local files are deleted.
That's a Wrap!
That's a Wrap!
Nice work! You just deployed a live website to AWS S3, and you did it entirely through code.
You've learned how to:
- Write a Terraform configuration that provisions an S3 bucket for static website hosting.
- Deploy a live website to AWS using only code instead of clicking through the console.
- Use the core Terraform workflow: init, plan, apply, and destroy.
- Secret Mission: Added a custom 404 error page and configured your bucket to handle missing pages gracefully.
Ready to quiz yourself?