Deploy Your First Web Server on EC2

Launch a live Nginx web server on AWS EC2 with IAM, VPC, and security groups.

Introduction

30 Second Summary

Every website you visit runs on a server somewhere in the world. What if you could set up your own server in the cloud and make it accessible to anyone on the internet?

In this project, you will deploy a web server on Amazon EC2. You'll configure the networking and security from scratch, connect to your server remotely, and serve a custom web page to the internet.

What You'll Build

A live web server running Nginx on an Amazon Linux EC2 instance, fully configured with IAM access, security groups, and SSH connectivity from your Windows machine.

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

  • A configured AWS CLI on your local machine with IAM credentials for programmatic access.
  • A running EC2 instance with a security group that controls exactly what traffic gets in and out.
  • A live Nginx web server serving your custom HTML page to the public internet.
  • Secret Mission: Build a custom VPC from scratch with public and private subnets, an internet gateway, and route tables.

Are there any prerequisites?

You'll need an AWS account (free tier eligible) and a Windows device. No prior AWS experience is required.

Install and Configure the AWS CLI

To manage AWS resources from your local machine, you need the AWS CLI (Command Line Interface). It lets you create, configure, and inspect cloud resources directly from your terminal instead of clicking through the console every time.

In this step, you will install the AWS CLI on Windows, create an IAM user with the right permissions, and connect your CLI to your AWS account. By the end, your local machine can talk to AWS.

In this step, get ready to:
  • Install AWS CLI v2 on your Windows machine.
  • Create an IAM user with EC2 permissions and generate access keys.
  • Configure the CLI to authenticate with your AWS account.
Download and install AWS CLI v2

The AWS CLI is a tool you install on your computer that lets you run commands like aws ec2 describe-instances to interact with AWS services. You will install it using the official MSI installer for Windows.

  • Download the AWS CLI v2 installer by clicking this link: AWS CLI v2 MSI Installer.
  • Once the download completes, double-click the AWSCLIV2.msi file to launch the installer.
  • Follow the installer prompts, accepting the default options on each screen.
  • Click Install and wait for the installation to complete, then click Finish.

Now you need to open PowerShell to verify the installation worked.

  • Press the Windows key to open your search bar.
  • Type PowerShell and press Enter to open it.
  • Verify the AWS CLI is installed by running this command:
aws --version

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

The output shows something like aws-cli/2.x.x Python/3.x.x Windows/10. 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. The v2 installer runs alongside v1 but your PATH may be pointing to the old version.

  • Close PowerShell completely and reopen it.
  • Run aws --version again.
  • If it still shows v1, uninstall AWS CLI v1 from Settings > Apps > Apps & features, then reopen PowerShell and try again.

ⓧ Command not found

PowerShell does not recognise the aws command yet. This usually means you need to restart PowerShell so it picks up the new PATH entry.

  • Close PowerShell completely and reopen it.
  • Run aws --version again.
  • If it still fails, re-run the MSI installer from the link above and make sure the installation completes without errors.
Create an IAM user in the AWS Console

The AWS CLI needs credentials to prove who you are. You will create a dedicated IAM user with permission to manage EC2 resources, then generate an access key for that user.

  • Open your web browser and sign in to the AWS Management Console at https://console.aws.amazon.com.
  • In the search bar at the top of the console, type IAM and select IAM from the results.
  • In the left navigation pane, click Users.
  • Click Create user.
  • For User name, type cli-user.
  • Click Next.

Now you will attach a permissions policy that gives this user full access to EC2.

  • On the Set permissions page, select Attach policies directly.
  • In the search box under Permissions policies, type AmazonEC2FullAccess.
  • Select the checkbox next to AmazonEC2FullAccess.
  • Click Next.
  • Review the details, then click Create user.

What is IAM?

IAM (Identity and Access Management) controls who can access your AWS account and what they can do. Instead of using your root account for everything, you create individual IAM users with only the permissions they need.

The AmazonEC2FullAccess policy is a pre-built set of permissions that allows the user to create, manage, and terminate EC2 instances.

Next, you will generate an access key so the CLI can authenticate as this user.

  • Click the user name cli-user to open the user details page.
  • Select the Security credentials tab.
  • Scroll down to the Access keys section and click Create access key.
  • For the use case, select Command Line Interface (CLI).
  • Check the confirmation checkbox at the bottom, then click Next.
  • Click Create access key.

Save your credentials now

You will see your Access Key ID and Secret Access Key on this page. This is the only time you can view the Secret Access Key.

Click Download .csv file to save them securely. You will need both values in the next substep. Do not share these credentials with anyone.

  • Click Done.

Why not use the root account?

AWS recommends creating separate IAM users instead of using your root account credentials. Root credentials have unlimited access to everything in your account. An IAM user with limited permissions reduces the damage if credentials are ever compromised.

Configure the CLI with your credentials

Now that you have an IAM user with access keys, you can tell the AWS CLI who you are. The aws configure command stores your credentials locally so every future CLI command is authenticated automatically.

  • Switch back to your PowerShell window.
  • Run the configuration wizard by entering this command:
aws configure

What will aws configure ask?

The command prompts you for four values, one at a time. Enter the following:

  • AWS Access Key ID: paste the Access Key ID from your downloaded .csv file.
  • AWS Secret Access Key: paste the Secret Access Key from the same file.
  • Default region name: type us-east-1.
  • Default output format: type json.

Now verify that the CLI can authenticate with AWS by running this command:

  • Confirm the CLI is connected to your account by running:
aws sts get-caller-identity

You should see a JSON response containing your account ID, user ID, and ARN that looks similar to this:

{
    "UserId": "AIDAEXAMPLEID",
    "Account": "123456789012",
    "Arn": "arn:aws:iam::123456789012:user/cli-user"
}

What does this output mean?

The aws sts get-caller-identity command asks AWS to confirm who is making the request. If you see your account number and the cli-user ARN, your credentials are working correctly.

Seeing an error about invalid credentials?

Double-check that you pasted the Access Key ID and Secret Access Key correctly with no extra spaces. You can re-run aws configure to enter the values again.

If you closed the access key page without saving, you will need to go back to IAM, delete the old access key, and create a new one.

Help me fix my AWS CLI credentials error.

Your AWS CLI is now installed, configured, and authenticated. Next up, you will create the security resources that protect your future EC2 instance.

Create a Key Pair and Security Group

Your AWS CLI is configured and ready to talk to your account. Now you need two things before you can launch a server: a way to log in to it securely, and a set of rules that control what network traffic can reach it.

In this step, you will create an SSH key pair (your secure login credential) and a security group (your firewall rules). Together, these two resources protect your instance while still letting you connect and serve web traffic.

In this step, get ready to:
  • Create an SSH key pair for secure remote access.
  • Create a security group to control inbound and outbound network traffic.
  • Verify both resources from the CLI.
Create an SSH key pair

An SSH key pair is like a lock-and-key system for your server. AWS keeps the public key (the lock) on the instance, and you keep the private key (the key) on your computer.

  • In the AWS Management Console, make sure you are in the EC2 service. If you are not already there, type EC2 in the search bar at the top and select EC2.
  • In the left navigation pane, expand Network & Security.
  • Click Key Pairs.
  • Click Create key pair in the top right corner.
  • Enter my-ec2-keypair in the Name field.
  • Under Key pair type, select RSA.
  • Under Private key file format, select .pem.
  • Click Create key pair.

Your browser automatically downloads a file called my-ec2-keypair.pem. This is your private key. You need to store it in a safe location and restrict its file permissions.

What is a .pem file?

A .pem file contains your private key in a text-based format. SSH uses this file to prove your identity when you connect to the instance. If anyone else gets this file, they can log in as you.

  • Return to your PowerShell window.
  • Create a .ssh folder in your user directory by running this command:
New-Item -ItemType Directory -Force -Path "$env:USERPROFILE\.ssh"

What does this command do?

`New-Item` creates a new file or folder. The -Force flag means it won't error if the folder already exists. $env:USERPROFILE automatically resolves to your Windows user folder (e.g. C:\Users\YourName).

  • Move the downloaded .pem file from your Downloads folder into the new .ssh folder by running:
Move-Item -Path "$env:USERPROFILE\Downloads\my-ec2-keypair.pem" -Destination "$env:USERPROFILE\.ssh\my-ec2-keypair.pem"
  • Confirm the file is in place by running:
ls "$env:USERPROFILE\.ssh"

You should see my-ec2-keypair.pem listed in the output.

File not found in Downloads?

Your browser may have saved the file to a different folder. Check your browser's download settings or use File Explorer to search for my-ec2-keypair.pem, then update the Move-Item path to match.

Help me find where my .pem file downloaded to

Now you need to restrict the file permissions so only your Windows user can read it. SSH will refuse to use the key if the permissions are too open.

  • Open File Explorer and navigate to C:\Users\YourName\.ssh (replace YourName with your actual Windows username).
  • Right-click my-ec2-keypair.pem and select Properties.
  • Click the Security tab.
  • Click Advanced.
  • Click Disable inheritance.
  • Select Remove all inherited permissions from this object.
  • Click Add, then click Select a principal.
  • Type your Windows username, click Check Names, then click OK.
  • Check Full control, then click OK on each open dialog until they are all closed.

Why restrict file permissions?

SSH clients check that only you can read the private key file. If other users on your machine have access, SSH treats the key as compromised and refuses to use it. Removing inherited permissions ensures only your account can read the file.

Create a security group

A security group acts as a virtual firewall for your instance. You define rules that say which traffic is allowed in (inbound) and which traffic can go out (outbound).

  • In the EC2 console's left navigation pane, click Security Groups (under Network & Security).
  • Click Create security group.
  • Enter web-server-sg in the Security group name field.
  • Enter Allow SSH and HTTP traffic in the Description field.
  • Leave the VPC set to the default VPC.

Now add two inbound rules. These tell AWS which incoming connections to allow.

  • Under Inbound rules, click Add rule.
  • Set Type to SSH. This automatically fills in port 22.
  • Set Source to My IP. The console detects your current IP address and fills it in automatically.
  • Click Add rule again to add a second rule.
  • Set Type to HTTP. This automatically fills in port 80.
  • Set Source to Anywhere-IPv4 (0.0.0.0/0). This allows anyone on the internet to view your web page.
  • Leave the Outbound rules as the default (all traffic allowed).
  • Click Create security group.

Why two different Source settings?

SSH gives full command-line access to your server, so you restrict it to your own IP address. HTTP is your public web page, so you open it to everyone. This is the principle of least privilege: only allow what is necessary.

Security groups are also stateful. This means that if you allow an inbound request, the response is automatically allowed out without needing a separate outbound rule.

Behind a VPN or corporate network?

The "My IP" auto-detection might pick up your VPN's IP address instead of your home IP. If you have trouble connecting via SSH later, return to this security group and update the SSH rule's source to your actual IP (search "what is my IP" in a browser).

Verify both resources from the CLI

Let's confirm that AWS created both resources successfully using the CLI.

  • Return to your PowerShell window and verify your key pair exists by running:
aws ec2 describe-key-pairs --key-names my-ec2-keypair

You should see a JSON response containing your key pair name, fingerprint, and key type.

  • Verify your security group exists by running:
aws ec2 describe-security-groups --group-names web-server-sg

You should see a JSON response showing the group name, description, and your two inbound rules (SSH on port 22 and HTTP on port 80).

Seeing an error about the resource not found?

Double-check that you are in the us-east-1 region. The CLI looks in whatever region you set during aws configure. If you created the resources in a different region in the console, either switch your console region to us-east-1 and recreate them, or update your CLI default region with aws configure.

Also confirm the names match exactly: my-ec2-keypair and web-server-sg (names are case-sensitive).

Help me troubleshoot why my AWS CLI can't find my key pair or security group

Your key pair and security group are ready. Next up, you will use them to launch a live EC2 instance.

Launch an EC2 Instance

You have a key pair for secure access and a security group defining which traffic can reach your server.

Now it is time to launch the actual virtual machine. In this step, you will create an EC2 instance running Amazon Linux, attach your key pair and security group, and confirm it passes its health checks.

In this step, get ready to:
  • Launch an EC2 instance named my-web-server using a free-tier eligible AMI.
  • Attach your key pair and security group to the instance.
  • Confirm the instance is running and note its public IP address.
Configure the instance name, AMI, and type

An AMI (Amazon Machine Image) is a template that contains the operating system and software for your instance. You will use Amazon Linux, which is optimized for EC2 and included in the free tier.

  • In the AWS Console, type EC2 in the top search bar and select EC2 from the results.
  • In the EC2 dashboard, click Launch instance.
  • Under Name and tags, enter my-web-server in the Name field.
  • Under Application and OS Images (Amazon Machine Image), click Quick Start.
  • Select Amazon Linux as the operating system.
  • From Amazon Machine Image (AMI), select an AMI marked Free Tier eligible.
  • Under Instance type, select t3.micro (free tier eligible).

What is an AMI?

An AMI is a pre-built template containing an operating system and software. Think of it as a snapshot that EC2 uses to create your virtual machine.

Amazon Linux is AWS's own Linux distribution, optimized for performance on EC2. The t3.micro instance type gives you 2 vCPUs and 1 GB of memory, which is plenty for a web server.

Why t3.micro?

The t3.micro instance type is free tier eligible whether your account was created before or after July 15, 2025. It provides enough resources for a lightweight web server at no cost during the free tier period.

Attach your key pair and security group

Your key pair enables SSH access, and your security group controls which network traffic can reach the instance. You will connect them both here.

  • Under Key pair (login), select my-ec2-keypair from the Key pair name dropdown.
  • Under Network settings, click the Edit button.
  • Keep the default VPC and default subnet selected.
  • Confirm that Auto-assign public IP is set to Enable. This gives your instance a public address so you can reach it from the internet.
  • Under Firewall (security groups), select Select existing security group.
  • From the dropdown, choose web-server-sg.

Why use the default VPC?

Every AWS account comes with a default VPC in each Region. It is pre-configured with an internet gateway and public subnets, so instances launched inside it can reach the internet immediately.

Using the default VPC keeps things simple for your first deployment. In the Secret Mission, you will build a custom VPC from scratch to see how production networks are configured.

Launch the instance and confirm it is running
  • Review your settings in the Summary panel on the right side of the page.
  • Click Launch instance.
  • On the success notification, click the instance ID link to open the Instances page.

Your instance will take a minute or two to start up. The initial state is Pending.

  • Wait for the Instance state column to change to Running.
  • Click the refresh icon if the state has not updated after 30 seconds.
  • Check the Status check column. Wait until it shows 2/2 checks passed. This can take 2-3 minutes.
  • Select your instance by clicking its checkbox.
  • In the details panel at the bottom, find the Public IPv4 address field.
  • Copy this IP address and save it somewhere accessible. You will use it to connect via SSH in the next step.

What does 2/2 checks passed mean?

EC2 runs two automated health checks on every instance. The system status check verifies the underlying AWS hardware. The instance status check verifies the software and network connectivity of your instance itself.

When both pass, your instance is healthy and ready to accept connections.

Status checks stuck on Initializing?

Status checks can take up to 5 minutes after launch. Click the refresh icon periodically. If they stay on initializing for more than 5 minutes, check that your security group web-server-sg exists in the same VPC as your instance.

Help me troubleshoot my EC2 instance status checks

Your EC2 instance is live and healthy. Next up, you will connect to it over SSH and install a web server that serves your custom page to the internet.

Connect via SSH and Install Nginx

Your EC2 instance is up and running in the cloud with a public IP address. Now it's time to connect to it remotely and turn it into a functioning web server.

SSH (Secure Shell) lets you control your remote instance directly from your local command line. You'll use it to connect from PowerShell, install Nginx (a fast, modern web server), and deploy a custom HTML page that the world can see.

In this step, get ready to:
  • Connect to your EC2 instance via SSH from PowerShell.
  • Install and configure Nginx as a web server.
  • Deploy a custom HTML page to your instance.
Connect to your instance via SSH

Your EC2 instance is a remote Linux machine. To run commands on it, you need to open a secure connection from your Windows machine using the SSH key pair you created earlier.

  • Connect to your EC2 instance by running this command in PowerShell:
ssh -i [[PEMPATH="C:\Users\YourName\.ssh\my-ec2-keypair.pem"]] ec2-user@[[EC2_PUBLIC_IP="your EC2 public IPv4 address"]]

What does this command do?

  • ssh starts a Secure Shell connection to a remote machine.
  • -i specifies the private key file that proves your identity to the instance.
  • ec2-user is the default username on Amazon Linux instances.
  • The public IP address tells SSH which machine to connect to.
  • When prompted with a message about the authenticity of the host, type yes and press Enter.

What is the fingerprint prompt?

The first time you connect to any new server, SSH asks you to verify its fingerprint. This is a security measure to confirm you're connecting to the right machine. Typing yes adds the server to your known hosts list so you won't be asked again.

You should see your terminal prompt change to something like [ec2-user@ip-172-31-xx-xx ~]$. This means you're now controlling your remote EC2 instance.

Connection refused or timed out?

  • Double-check that you're using the correct Public IPv4 address from the EC2 instance details page.
  • Make sure the security group web-server-sg has an inbound rule allowing SSH (port 22) from your current IP. If you're on a VPN, your IP may differ from what the console detected.
  • Verify your .pem file permissions are restricted to only your user account. SSH rejects keys that are accessible by others.

Help me troubleshoot my SSH connection to EC2

Update the system and install Nginx

Before installing any software, it's good practice to update the existing packages on your instance. Then you'll install Nginx, a lightweight web server commonly used in modern cloud architectures.

  • Update all system packages by running this command on your EC2 instance:
sudo dnf update -y
  • Wait for the update to finish. You'll see a list of packages being updated, followed by a Complete! message.
  • Install Nginx by running:
sudo dnf install nginx -y

What do these commands do?

  • sudo runs the command with administrator (root) privileges.
  • dnf is Amazon Linux's package manager. It downloads and installs software from official repositories.
  • -y automatically says "yes" to all prompts, so the install runs without interruption.
  • Start Nginx immediately by running:
sudo systemctl start nginx
  • Enable Nginx to start automatically whenever the instance reboots by running:
sudo systemctl enable nginx
  • Verify Nginx is running by running:
sudo systemctl status nginx

You should see active (running) in green text. This confirms Nginx is up and serving web traffic on port 80.

Nginx not showing as active?

  • Make sure you ran sudo systemctl start nginx before checking the status.
  • If you see a permission error, make sure you included sudo at the start of each command.

Help me get Nginx running on my Amazon Linux EC2 instance

Create a custom HTML page

Nginx is now serving a default welcome page. You'll replace it with your own custom HTML page that announces your first AWS deployment to the world.

  • Open the default Nginx HTML file in the nano text editor by running:
sudo nano /usr/share/nginx/html/index.html
  • Delete all existing content in the file. Press Alt+\ to jump to the top of the file, then press Alt+T to cut everything from the cursor to the end of the file.
  • Copy the HTML below from this page. Then paste it into nano by right-clicking inside your PowerShell window (or pressing Ctrl+V).
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>My First AWS Deployment</title>
    <style>
        body {
            font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
            display: flex;
            justify-content: center;
            align-items: center;
            min-height: 100vh;
            margin: 0;
            background: linear-gradient(135deg, #232f3e 0%, #ff9900 100%);
            color: white;
        }
        .container {
            text-align: center;
            padding: 2rem;
            background: rgba(0, 0, 0, 0.3);
            border-radius: 12px;
            backdrop-filter: blur(10px);
        }
        h1 {
            font-size: 2.5rem;
            margin-bottom: 0.5rem;
        }
        p {
            font-size: 1.2rem;
            opacity: 0.9;
        }
        .services {
            margin-top: 1.5rem;
            display: flex;
            gap: 1rem;
            justify-content: center;
            flex-wrap: wrap;
        }
        .badge {
            background: rgba(255, 153, 0, 0.8);
            padding: 0.5rem 1rem;
            border-radius: 20px;
            font-size: 0.9rem;
            font-weight: bold;
        }
    </style>
</head>
<body>
    <div class="container">
        <h1>Hello from AWS EC2!</h1>
        <p>This page is served by Nginx on an Amazon Linux instance.</p>
        <p>I built this infrastructure myself.</p>
        <div class="services">
            <span class="badge">IAM</span>
            <span class="badge">VPC</span>
            <span class="badge">EC2</span>
            <span class="badge">Security Groups</span>
        </div>
    </div>
</body>
</html>
  • Save the file by pressing Ctrl+O, then press Enter to confirm the filename.
  • Exit nano by pressing Ctrl+X.

What does this HTML page do?

This page creates a styled announcement card with a gradient background matching AWS brand colours. It displays a heading, two paragraphs describing what you built, and badge labels for each AWS service you used (IAM, VPC, EC2, Security Groups).

The CSS uses flexbox to center the card vertically and horizontally. The backdrop filter adds a frosted-glass effect to the container.

  • Verify your custom page is being served by Nginx by running:
curl localhost

You should see your HTML code printed in the terminal output. This confirms Nginx is now serving your custom page instead of the default welcome page.

Seeing the default Nginx page instead?

  • Make sure you saved the file in nano with Ctrl+O before exiting. If you only pressed Ctrl+X, nano may have discarded your changes.
  • Confirm the file path is exactly /usr/share/nginx/html/index.html. A typo in the path creates a new file that Nginx doesn't know about.
  • Run sudo nano /usr/share/nginx/html/index.html again to check the file contents. You should see your custom HTML.

Help me troubleshoot why Nginx is showing the wrong page

✔️ Awesome, I've got everything!

Great. Make sure you're still connected to your EC2 instance via SSH for the next step.

ⓧ I'd like to double check the full code

Here is the complete index.html file that should be at /usr/share/nginx/html/index.html on your EC2 instance:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>My First AWS Deployment</title>
    <style>
        body {
            font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
            display: flex;
            justify-content: center;
            align-items: center;
            min-height: 100vh;
            margin: 0;
            background: linear-gradient(135deg, #232f3e 0%, #ff9900 100%);
            color: white;
        }
        .container {
            text-align: center;
            padding: 2rem;
            background: rgba(0, 0, 0, 0.3);
            border-radius: 12px;
            backdrop-filter: blur(10px);
        }
        h1 {
            font-size: 2.5rem;
            margin-bottom: 0.5rem;
        }
        p {
            font-size: 1.2rem;
            opacity: 0.9;
        }
        .services {
            margin-top: 1.5rem;
            display: flex;
            gap: 1rem;
            justify-content: center;
            flex-wrap: wrap;
        }
        .badge {
            background: rgba(255, 153, 0, 0.8);
            padding: 0.5rem 1rem;
            border-radius: 20px;
            font-size: 0.9rem;
            font-weight: bold;
        }
    </style>
</head>
<body>
    <div class="container">
        <h1>Hello from AWS EC2!</h1>
        <p>This page is served by Nginx on an Amazon Linux instance.</p>
        <p>I built this infrastructure myself.</p>
        <div class="services">
            <span class="badge">IAM</span>
            <span class="badge">VPC</span>
            <span class="badge">EC2</span>
            <span class="badge">Security Groups</span>
        </div>
    </div>
</body>
</html>

Your web server is installed, running, and serving a custom page. Next up, you'll open a browser on your local machine and see your page live on the internet.

Verify Your Live Website

In the last step, you connected to your EC2 instance via SSH and installed Nginx with a custom HTML page.

Now it's time for the payoff. You'll open a browser, visit your instance's public IP, and see your page live on the internet. Then you'll confirm everything from the CLI and trace exactly how traffic flows from a browser to your web server.

In this step, get ready to:
  • Visit your live website in a browser.
  • Verify your running instance from the CLI.
  • Understand the full traffic flow from browser to web server.
Visit your live website in a browser

Your Nginx web server is running and serving your custom HTML page. Anyone on the internet can reach it through your instance's public IP address.

  • Open any web browser on your Windows machine (Chrome, Edge, Firefox).
  • In the address bar, enter your instance's public IP with http:// in front of it:
http://[[EC2_PUBLIC_IP="your EC2 instance public IPv4 address"]]

Why http:// and not https://?

Your security group only allows traffic on port 80, which is HTTP. HTTPS requires port 443 and an SSL certificate, which is beyond the scope of this project.

  • Press Enter. You should see your custom page with a gradient background, the heading "Hello from AWS EC2!", and four orange badges listing the services you used.

Page not loading?

  • Double-check you're using http:// (not https://). HTTPS will not work without an SSL certificate.
  • Confirm you copied the correct Public IPv4 address from the EC2 console (not the private IP).
  • Verify your security group web-server-sg has an inbound rule allowing HTTP (port 80) from 0.0.0.0/0.

If you're still stuck, help me troubleshoot why my EC2 web server page isn't loading in the browser.

Confirm your instance from the CLI

Seeing the page in a browser is proof it works. Now let's verify the instance status from your local machine using the AWS CLI.

  • If you're still connected to your EC2 instance via SSH, type exit and press Enter to return to your local PowerShell prompt.
  • Confirm your running instance and its public IP by running this command:
aws ec2 describe-instances --filters "Name=instance-state-name,Values=running" --query "Reservations[*].Instances[*].[InstanceId,PublicIpAddress,State.Name]" --output table

What does this command do?

  • --filters "Name=instance-state-name,Values=running" narrows the results to only instances that are currently running.
  • --query selects specific fields: the instance ID, public IP, and state name.
  • --output table formats the result as a readable table instead of raw JSON.
  • You should see a table with your instance ID, the same public IP you visited in your browser, and the state running.

Command returning empty results?

  • Make sure you exited the SSH session. The aws command must run on your local machine, not inside the EC2 instance.
  • Verify you're using the same region. Run aws configure and confirm the default region is us-east-1.

If it still doesn't work, help me troubleshoot why my AWS CLI describe-instances command returns no results.

Understand the full traffic flow

You've confirmed your website works from two different angles: the browser and the CLI. Let's trace the path a request takes to understand why it all works.

How does traffic reach your web server?

When you typed your public IP into the browser, here's what happened behind the scenes:

  • Your browser sent an HTTP request to the public IP address on port 80.
  • The internet gateway in the default VPC received the request and routed it to your EC2 instance.
  • The Security Group (web-server-sg) checked its inbound rules. Port 80 from 0.0.0.0/0 is allowed, so the traffic passed through.
  • Nginx received the request and served your index.html file back to the browser.

If any link in this chain were missing (no internet gateway, no port 80 rule, Nginx not running), your page would not load. Each piece you configured in previous steps serves a specific purpose.

Why is the security group so important?

Without the HTTP rule on port 80, the traffic would be silently dropped. Security groups act as a virtual firewall that blocks everything by default. You explicitly chose what to allow in.

This is why you added two separate rules: SSH on port 22 so you could connect and set up the server, and HTTP on port 80 so the public can view your website.

Secret mission

Build a Custom VPC from Scratch

In production, no one uses the default VPC. Cloud engineers design their own network architecture with public subnets, private subnets, internet gateways, and route tables. Can you build one yourself and migrate your web server into it?

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. Your EC2 instance is free tier eligible, but charges apply if you exceed your free tier hours or your free tier period has expired.

Cost warning

A running t3.micro instance outside the free tier costs approximately $0.01/hour. If your 12-month free tier window has passed (or you have used all your free tier hours for the month), you will be charged for every hour the instance stays running.

If you are not planning to use this instance again, choose Stop or Delete below to avoid unexpected charges.

Resources you used:

  • EC2 instance (t3.micro) running in your custom VPC.
  • Custom VPC with public and private subnets, internet gateway, and route table.
  • Security group in the custom VPC (SSH and HTTP rules).
  • Security group in the default VPC (web-server-sg).
  • Key pair (my-ec2-keypair) and local .pem file.
  • IAM user with access key and AmazonEC2FullAccess policy.
  • AWS CLI v2 installation and .aws configuration folder.

Keep everything running

No action needed. Choose this if you are still actively building or experimenting with your instance.

  • Your EC2 instance stays running and your web page remains accessible.
  • Monitor your free tier usage in the AWS Billing console under Free Tier to avoid surprise charges.
  • The AWS CLI remains installed on your machine for future projects.

Pause - I'll come back to this later

Stop your EC2 instance to avoid compute charges while keeping all your resources intact. A small EBS storage charge may still apply.

  • In the EC2 console, select your running instance in the custom VPC.
  • Click Instance state, then click Stop instance.
  • Confirm by clicking Stop.
  • Your instance will show a "Stopped" state. You can restart it later by selecting Instance state then Start instance.
  • Note that your public IP address will change when you restart. You will need to use the new IP to reconnect via SSH.

Delete - I don't want to use this again

Remove all project resources and start fresh. Follow these steps in order.

Terminate the EC2 instance
  • In the EC2 console, select your running instance in the custom VPC.
  • Click Instance state, then click Terminate instance.
  • Confirm by clicking Terminate.
  • Wait for the instance state to show "Terminated" before continuing.
Delete the custom VPC resources

Delete these in the following order. Each resource depends on the one before it being removed first.

  • Navigate to VPC in the AWS Console, then select Route tables.
  • Select your custom route table. Click Subnet associations, then click Edit subnet associations. Deselect the public subnet and click Save associations.
  • With the route table still selected, click Actions, then click Delete route table. Confirm the deletion.
  • Navigate to Internet gateways. Select your internet gateway.
  • Click Actions, then click Detach from VPC. Confirm the detachment.
  • With the internet gateway still selected, click Actions, then click Delete internet gateway. Confirm the deletion.
  • Navigate to Subnets. Select your public subnet (10.0.1.0/24). Click Actions, then click Delete subnet. Confirm.
  • Repeat for your private subnet (10.0.2.0/24).
  • Navigate to Your VPCs. Select your custom VPC (10.0.0.0/16). Click Actions, then click Delete VPC. Confirm the deletion.
Delete the security groups
  • Navigate to EC2 then Security Groups.
  • Select web-server-sg (the one in the default VPC). Click Actions, then click Delete security groups. Confirm.

What about the custom VPC security group?

The security group you created in the custom VPC was automatically deleted when you deleted the VPC. You only need to manually delete web-server-sg in the default VPC.

Delete the key pair
  • In the EC2 console, navigate to Network & Security, then Key Pairs.
  • Select my-ec2-keypair. Click Actions, then click Delete. Type Delete to confirm.
  • Delete the local .pem file from your machine. Open File Explorer, navigate to C:\Users\YourName\.ssh\, and delete my-ec2-keypair.pem.
Delete the IAM user
  • Navigate to IAM in the AWS Console, then click Users.
  • Select the IAM user you created for this project.
  • Click the Security credentials tab. Under Access keys, click Actions, then Delete. Confirm the deletion of the access key.
  • Return to the user summary. Click Delete in the top right. Type the username to confirm, then click Delete user.
Uninstall the AWS CLI (optional)
  • Open Control Panel, then click Programs and Features.
  • Select AWS Command Line Interface, then click Uninstall.
  • Confirm the uninstallation.
  • Optionally, delete the .aws configuration folder. Open File Explorer and delete the folder at C:\Users\YourName\.aws\. This removes your stored credentials and configuration.

That's a Wrap!

That's a Wrap!

Nice work! You just deployed your first cloud infrastructure on AWS, from an empty console to a live web server accessible from anywhere in the world.

You've learned how to:

  • Configured the AWS CLI and created an IAM user with programmatic access and EC2 permissions.
  • Launched a free-tier EC2 instance with a Security Group controlling exactly which traffic reaches your server.
  • Connected via SSH from your Windows machine and deployed a live Nginx web server serving a custom HTML page to the internet.
  • Built a custom VPC from scratch with public and private subnets, an internet gateway, and route tables.

Ready to quiz yourself?