EC2 Lab: How to Launch EC2 Instance on AWS: Step-by-Step Apache & SSH Guide


Introduction

Here’s the thing about EC2—it’s deceptively simple on the surface. You click a few buttons, an instance spins up, and suddenly you have a server running in AWS. But that simplicity hides a dozen decisions that can make or break your production workloads down the road.

I’ve been deploying EC2 instances for nearly a decade now, and I still remember my first one. I launched it, couldn’t connect via SSH, panicked, terminated it, and started over three times before realizing I’d attached the wrong security group. That was a Tuesday afternoon I’ll never get back.

This lab walks you through launching your very first EC2 instance and getting Apache running on it. More importantly, I’ll explain why each step matters—because understanding the reasoning behind the clicks is what separates someone who can follow a tutorial from someone who can troubleshoot at 2 AM when things break.

EC2 remains the backbone of most AWS architectures I design. Sure, containers and serverless get all the attention these days, but when a client needs a bastion host, a build server, a legacy application migration, or just raw compute power they control completely, EC2 is where we land. It’s not glamorous, but it’s essential.

The mistakes I see beginners make? They skip the fundamentals. They don’t understand why key pairs matter, leave SSH open to the world, and then wonder why their instance got compromised within hours. By the end of this lab, you won’t be that person.


Lab Overview

Objectives

By completing this lab, you will:

  • Create and securely store an EC2 key pair
  • Launch an Amazon Linux 2 instance with proper network configuration
  • Configure security groups with least-privilege access
  • Connect to your instance via SSH
  • Install and configure Apache web server
  • Validate your setup with real testing commands

Architecture Overview

We’re building the simplest possible web server architecture: a single EC2 instance sitting in a public subnet, accessible via SSH for administration and HTTP for serving web content. An Internet Gateway provides the path to the public internet, and security groups act as our virtual firewall.

This architecture is the foundation for countless production patterns—auto-scaled web tiers, bastion hosts for secure access, development environments, and disaster recovery testing servers all start here.

Expected Outcomes

When you finish, you’ll have a running Apache web server displaying a custom message, accessible from your browser. More valuable than the running server is the understanding you’ll gain about how these components connect.

Real-World Scenarios

This exact pattern appears in production constantly. I’ve used variations of it for scaling web server fleets behind load balancers, setting up secure bastion hosts for accessing private resources, deploying test environments for disaster recovery validation, and running quick proof-of-concept demos for clients. The fundamentals never change—only the scale.


Prerequisites

Before starting, make sure you have:

  • An active AWS account (free tier works perfectly for this lab)
  • An IAM user with EC2 and VPC permissions—avoid using root credentials
  • Basic comfort with Linux command line (navigating directories, running commands)
  • Understanding of VPC concepts: subnets, route tables, internet gateways
  • An SSH client installed (Terminal on Mac/Linux, PuTTY or Windows Terminal on Windows)
  • The default VPC in your region (AWS creates one automatically, but verify it exists)

If VPC concepts feel fuzzy, check out our VPC Fundamentals Guide before continuing. Trust me, it’ll save you confusion later.


Step-by-Step Hands-On Lab

Step 1: Create a Key Pair

What you’ll do: Generate an RSA key pair that AWS stores the public half of while you download the private half.

Navigate to: EC2 Console → Network & Security → Key Pairs → Create key pair

Configuration:

  • Name: ec2-lab-key (or something memorable)
  • Key pair type: RSA
  • Private key file format: .pem (standard for Mac, Linux, and Windows 10/11 PowerShell). Only choose .ppk if you specifically plan to use the legacy PuTTY tool.

Click Create, and your browser downloads the private key file immediately.

Why this matters: This key pair is your only way into the instance. AWS doesn’t store passwords for EC2 instances—authentication happens entirely through these cryptographic keys. Lose the private key, and you’ve lost access. There’s no “forgot password” option.

Expected output: A file named ec2-lab-key.pem downloads to your machine.

Critical step for Mac/Linux users: Immediately restrict the key file permissions:

chmod 400 ~/Downloads/ec2-lab-key.pem

SSH refuses to use key files with open permissions. This single command prevents the “Permissions 0644 are too open” error that trips up nearly everyone on their first attempt.

Mistakes I’ve seen: Engineers download the key, forget where they saved it, launch the instance, then can’t connect. Others email themselves the key file or upload it to Slack. Please don’t do that—your private key should stay private.


Step 2: Launch an Amazon Linux 2 EC2 Instance

Navigate to: EC2 Console → Instances → Launch instances

Configuration walkthrough:

Name and tags:
Enter WebServer-Lab01. Proper naming saves hours of confusion when you have dozens of instances running.

Application and OS Images (AMI):
Select Amazon Linux 2023 AMI. It is the modern standard and what you should learn on. Note: You might see tutorials referencing Amazon Linux 2—that version is entering its end-of-life phase. We’re using AL2023 to ensure you’re learning on current infrastructure.

Instance type:
Choose t2.micro (free tier eligible). This gives you 1 vCPU and 1 GB RAM—plenty for a basic web server.

A word about CPU credits: T2 and T3 instances use a “burstable” performance model. You accumulate CPU credits when idle and spend them when busy. A t2.micro earns 6 credits per hour and can burst up to 10% baseline. For this lab, you’ll never notice. In production under sustained load, you absolutely will. I’ve watched instances grind to a halt because teams didn’t understand this model. Monitor your CPU credit balance in CloudWatch if you’re running anything important on burstable instances.

Key pair:
Select the ec2-lab-key you created in Step 1.

Network settings:
Click Edit, then:

  • VPC: Select your default VPC
  • Subnet: Choose any subnet marked “public” (or the default subnet)
  • Auto-assign public IP: Enable

Firewall (security groups):
Select “Create security group” and name it WebServer-SG. We’ll configure the rules properly in the next step.

Storage:
Default 8 GB gp2 is fine for this lab. In production, you’d size based on actual needs and likely choose gp3 for better price-performance.

Launch the instance.

Expected output: The console shows “Successfully initiated launch of instance i-xxxxxxxxx” with the instance entering “Pending” then “Running” state within 30-60 seconds.


Step 3: Configure Security Group Rules

Navigate to: EC2 Console → Network & Security → Security Groups → Select WebServer-SG

Add inbound rules:

Rule 1 – SSH Access:

  • Type: SSH
  • Port: 22
  • Source: My IP (AWS auto-detects your current IP address)

Rule 2 – HTTP Access:

  • Type: HTTP
  • Port: 80
  • Source: Anywhere (0.0.0.0/0) for testing purposes

Why port 22 open to the world is dangerous: Within minutes of launching an instance with SSH open to 0.0.0.0/0, you’ll see automated scanners attempting logins. I’ve reviewed CloudTrail logs showing thousands of brute-force attempts within the first hour. Restrict SSH to specific IPs—always. In production environments, consider replacing SSH entirely with AWS Systems Manager Session Manager.

Architect best practice: In real deployments, I create separate security groups for each function. One for SSH access (attached only when needed), one for application traffic. This separation lets you audit and modify rules without accidentally breaking something else.

Mistakes I’ve seen: Teams add “All traffic” from “Anywhere” because “it wasn’t working” and they were frustrated. That’s how breaches happen. Troubleshoot the actual problem instead.


Step 4: Connect via SSH

Find your instance’s public IP: EC2 Console → Instances → Select your instance → Copy the Public IPv4 address.

Connect from your terminal:

ssh -i ~/Downloads/ec2-lab-key.pem ec2-user@<your-public-ip>

Replace <your-public-ip> with the actual IP address.

Expected first login output:

The authenticity of host '54.xxx.xxx.xxx' can't be established.
ECDSA key fingerprint is SHA256:xxxxxxxxxxx.
Are you sure you want to continue connecting (yes/no)? yes
Warning: Permanently added '54.xxx.xxx.xxx' (ECDSA) to the list of known hosts.

       __|  __|_  )
       _|  (     /   Amazon Linux 2 AMI
      ___|\___|___|

https://aws.amazon.com/amazon-linux-2/
[ec2-user@ip-172-31-xx-xx ~]$

Type yes when prompted about the host authenticity—that’s normal for first connections.

Troubleshooting permission errors:

If you see “Permission denied (publickey)”, verify:

  • You’re using ec2-user as the username (not root, not ubuntu)
  • The .pem file permissions are 400
  • You’re using the correct key pair for this instance

If you see “Connection timed out”:

  • Security group doesn’t allow SSH from your IP
  • Instance isn’t in a public subnet
  • No route to Internet Gateway in the route table

Step 5: Install Apache and Host a Web Page

Now the fun part. Run these commands in sequence:

Note: We’re using yum commands below. On Amazon Linux 2023, the package manager is technically dnf, but AWS includes a yum alias so these commands work identically on both versions.

# Update all packages to latest versions
sudo yum update -y

# Install Apache web server
sudo yum install -y httpd

# Start Apache service
sudo systemctl start httpd

# Enable Apache to start on boot
sudo systemctl enable httpd

# Create a simple test page
echo "Hello from Apache on EC2!" | sudo tee /var/www/html/index.html

What each command does:

yum update -y refreshes package metadata and upgrades installed packages. The -y flag auto-confirms prompts.

yum install -y httpd installs Apache (called httpd on Amazon Linux).

systemctl start httpd launches the Apache process immediately.

systemctl enable httpd creates symlinks so Apache starts automatically after reboots.

The echo and tee combination writes your custom message to the default web root.

Expected output after starting Apache:

sudo systemctl status httpd

Should show:

● httpd.service - The Apache HTTP Server
   Loaded: loaded (/usr/lib/systemd/system/httpd.service; enabled; vendor preset: disabled)
   Active: active (running) since...

Common issues:

If Apache won’t start, check if something else is binding port 80:

sudo netstat -tlnp | grep :80

SELinux occasionally causes problems with custom configurations. For this basic lab, it shouldn’t interfere, but in production you’d see errors in /var/log/audit/audit.log.


Real Lab Experience: Architect Insights

Let me share what years of production EC2 work have taught me—the stuff that doesn’t make it into official documentation.

User data scripts fail silently. When you use EC2 user data for bootstrap automation, there’s no flashing red alert if something goes wrong. Your instance launches “successfully” while your script crashes on line 3. Always add logging at the beginning of user data scripts:

exec > /var/log/user-data.log 2>&amp;1
set -x

This redirects all output to a log file you can actually review.

The “works in dev, fails in prod” syndrome is real. I once watched a team spend two full days debugging an EC2 instance that couldn’t reach the internet. Security groups looked fine. NACLs looked fine. The instance had a public IP. Turns out, someone had deleted the route to the Internet Gateway in the route table during a “cleanup.” Two days, dozens of engineers, one missing route.

Leaving port 22 open to 0.0.0.0/0 is an invitation. I’ve pulled CloudWatch logs showing SSH brute-force attempts starting within 90 seconds of instance launch. Automated scanners constantly probe AWS IP ranges. Restrict your SSH source IPs, or better yet, use Session Manager.

Always know your instance’s perspective. When troubleshooting, don’t just look at the console. SSH in and check what the instance sees. Can it resolve DNS? Can it reach the metadata service? These commands have saved me countless hours:

curl -s http://169.254.169.254/latest/meta-data/instance-id
ping -c 3 google.com

Termination protection exists for a reason. Enable it for any instance that matters. I’ve seen accidental terminations take down production services because someone clicked the wrong instance in a list of similarly-named servers.


Architecture Diagram Description

For graphic designer:

Create a diagram showing a single VPC containing one public subnet. Inside the public subnet, place an EC2 instance icon labeled “WebServer-Lab01” with the Amazon Linux logo. Attach a security group badge showing “Port 22 (SSH) – My IP” and “Port 80 (HTTP) – 0.0.0.0/0”.

Connect the VPC to an Internet Gateway at the top. Show a laptop icon outside the AWS cloud with two arrows: one labeled “SSH :22” and one labeled “HTTP :80” both pointing to the EC2 instance through the Internet Gateway. Include a route table snippet showing “0.0.0.0/0 → igw-xxxxx” to illustrate the internet route.


Validation and Testing

Verify SSH Connectivity

If you’re still connected via SSH, you’re validated. If not:

ssh -i ~/Downloads/ec2-lab-key.pem ec2-user@&lt;public-ip>

Test Apache from Browser

Open your browser and navigate to:

http://&lt;your-public-ip>

You should see: Hello from Apache on EC2!

Verify Apache Service Status

sudo systemctl status httpd

Look for Active: active (running).

Check Apache Logs

sudo journalctl -u httpd --no-pager -n 20

This shows the last 20 log entries for the Apache service. No errors should appear for a fresh installation.

Test from Command Line

curl http://localhost

Should return: Hello from Apache on EC2!


Troubleshooting Guide

SSH Connection Timeout

Symptoms: Connection hangs, then times out after 30+ seconds.

Diagnosis:

  • Security group missing SSH rule for your IP
  • Instance is in a private subnet without NAT
  • Route table lacks Internet Gateway route
  • Instance hasn’t finished booting

Commands:

# Check if instance is reachable at all
ping &lt;public-ip>

Permission Denied (publickey)

Symptoms: Immediate rejection with “Permission denied.”

Diagnosis:

  • Wrong username (use ec2-user for Amazon Linux)
  • Wrong key pair file
  • Key file permissions too open

Fix:

chmod 400 ~/Downloads/ec2-lab-key.pem

Apache Fails to Start

Symptoms: systemctl start httpd shows errors.

Diagnosis:

sudo journalctl -xe
sudo cat /var/log/httpd/error_log

Common cause: Another process binding port 80.

Instance Stuck in “Pending”

Symptoms: Instance never reaches “Running” state.

Diagnosis: Usually capacity issues in that Availability Zone. Try launching in a different AZ.

No Public IP Assigned

Symptoms: Instance running but Public IPv4 shows blank.

Cause: Auto-assign public IP was disabled during launch.

Fix: Allocate an Elastic IP and associate it with the instance.

Can’t Reach Website from Browser

Symptoms: SSH works, but HTTP doesn’t load.

Diagnosis:

sudo systemctl status httpd
curl http://localhost

If localhost works but external doesn’t, it’s a security group issue—verify port 80 is open.

Metadata Service Unreachable

Symptoms: Instance can’t retrieve its own metadata.

Test:

curl -I http://169.254.169.254/latest/meta-data/

Should return HTTP 200. If it times out, check route tables and NACLs.


AWS Best Practices

Security

Restrict SSH access to specific IP addresses or CIDR blocks—never 0.0.0.0/0 in production. Use IAM roles attached to instances instead of storing credentials on the instance. Rotate key pairs periodically and use AWS Systems Manager Session Manager to eliminate SSH exposure entirely.

Cost Optimization

Stop instances when not in use—stopped instances don’t incur compute charges (though EBS volumes do). Right-size instances based on actual utilization data from CloudWatch. Consider Spot Instances for fault-tolerant workloads at up to 90% discount.

Monitoring

Enable detailed CloudWatch monitoring for production instances. Create alarms for CPU utilization, status checks, and network metrics. Forward Apache logs to CloudWatch Logs for centralized analysis.

Resilience

Never run production workloads on a single instance. Use Auto Scaling groups even for “single instance” deployments—they’ll automatically replace failed instances. Spread instances across multiple Availability Zones.

Tagging Strategy

Tag every resource with at minimum: Name, Environment (dev/staging/prod), Owner, and Project. This enables cost allocation, automated operations, and saves sanity when managing dozens of resources.

Backups

Create AMIs of configured instances before making changes. Enable EBS snapshots on a schedule. Test your restore process before you need it desperately at 3 AM.


Frequently Asked Questions

What is an EC2 instance in AWS?

An EC2 instance is a virtual server running in Amazon’s cloud infrastructure. Think of it as renting a computer from AWS—you choose the operating system, CPU, memory, and storage, then pay only for the time it runs. EC2 instances power everything from simple websites to complex machine learning workloads, giving you full control over the server environment without managing physical hardware.

How do I launch my first EC2 instance?

To launch your first EC2 instance, sign into the AWS Console, navigate to EC2, and click “Launch Instance.” Select an Amazon Machine Image (Amazon Linux 2023 recommended for beginners), choose an instance type (t2.micro for free tier), create or select a key pair for SSH access, configure a security group allowing SSH on port 22, and click Launch. Your instance will be running within 60 seconds.

How do I connect to an EC2 instance via SSH?

Connect to your EC2 instance by opening a terminal and running ssh -i /path/to/your-key.pem ec2-user@your-public-ip. Replace the key path with your actual .pem file location and use the public IP address shown in the EC2 console. For Amazon Linux instances, the default username is ec2-user. Ensure your key file has restricted permissions (chmod 400) before connecting.

Why can’t I SSH into my EC2 instance?

SSH connection failures typically stem from four causes: incorrect key file permissions (run chmod 400 your-key.pem), wrong username (use ec2-user for Amazon Linux), security group missing an inbound rule for SSH port 22 from your IP address, or the instance lacking a route to the internet. Verify each of these in order, as security group misconfiguration is the most common culprit.

How do I install Apache on an EC2 instance?

Install Apache on an Amazon Linux EC2 instance by connecting via SSH and running three commands: sudo yum install -y httpd to install Apache, sudo systemctl start httpd to start the service, and sudo systemctl enable httpd to ensure it starts automatically after reboots. Place your web files in /var/www/html/ and ensure your security group allows HTTP traffic on port 80.

What is the difference between Amazon Linux 2 and Amazon Linux 2023?

Amazon Linux 2023 is the current generation operating system from AWS, while Amazon Linux 2 is entering end-of-life status. AL2023 uses the dnf package manager (with yum compatibility), includes newer kernel versions, provides enhanced security defaults, and follows a predictable two-year release cycle. New projects should use Amazon Linux 2023 for long-term support and security updates.

How much does an EC2 instance cost?

EC2 pricing varies by instance type, region, and usage model. A t2.micro instance (1 vCPU, 1GB RAM) costs approximately $0.0116 per hour in US East, roughly $8.50 monthly if running continuously. AWS offers a free tier including 750 hours of t2.micro or t3.micro usage per month for the first 12 months. Stopped instances incur no compute charges, though attached EBS storage continues billing.

What security group rules do I need for a web server?

A basic web server requires two security group rules: SSH (port 22) restricted to your specific IP address for administrative access, and HTTP (port 80) open to 0.0.0.0/0 for public web traffic. For HTTPS sites, add port 443. Never open SSH to 0.0.0.0/0 in production—automated scanners will find and probe your instance within minutes of launch.

How do I check if Apache is running on EC2?

Verify Apache is running by executing sudo systemctl status httpd on your EC2 instance. The output should show “active (running)” in green text. You can also test locally with curl http://localhost which should return your web page content, or access http://your-public-ip from a browser. If Apache isn’t running, check logs with sudo journalctl -u httpd for error details.

What is an EC2 key pair and why do I need one?

An EC2 key pair is a cryptographic key set used for secure SSH authentication. AWS stores the public key on your instance while you download and keep the private key (.pem file). This replaces password-based login with stronger security. Without the private key file, you cannot access your instance—there’s no password reset option. Store your private key securely and never share it.

Can I change the instance type after launching EC2?

Yes, you can change an EC2 instance type after launch, but the instance must be stopped first. In the EC2 console, select your stopped instance, choose Actions → Instance Settings → Change Instance Type, select your new type, and start the instance. This is useful for right-sizing—start small, monitor performance with CloudWatch, then scale up only if metrics show you need more resources.

How do I stop vs terminate an EC2 instance?

Stopping an EC2 instance is like shutting down a computer—the instance halts but your data on EBS volumes persists, and you can restart it later. Terminating permanently deletes the instance and, by default, its root volume. Stopped instances don’t incur compute charges but EBS storage still bills. Use stop for temporary pauses; terminate only when you’re completely finished with the instance.


Conclusion

You’ve just completed the foundation that everything else in EC2 builds upon. You launched an instance, secured it properly, connected via SSH, and deployed a web server. More importantly, you understand why each piece matters.

The patterns you learned here—key pairs for authentication, security groups for access control, public subnets for internet connectivity—appear in every AWS architecture I design. Master these fundamentals, and the advanced topics become logical extensions rather than mysterious configurations.

Next up: IAM Roles for EC2: Grant S3 Read-Only Access (Hands-On Lab 0.2)

Related reading: VPC Fundamentals: Subnets, Route Tables, and Internet Gateways


Have questions about this lab? Found an issue? Drop a comment below or reach out on [Twitter/LinkedIn]. Happy building!

Similar Posts

2 Comments

Leave a Reply