This repository demonstrates how to deploy a custom Apache (httpd) web server on an Amazon Linux 2023 EC2 instance, automatically configured at launch using EC2 User Data. It includes a sample custom webpage and troubleshooting notes from a real run-through.
- Cloud Provider: AWS
- Service: Amazon EC2
- OS: Amazon Linux 2023
- Web Server: Apache (httpd)
- Automation: EC2 User Data (bash script)
- Deliverable: Custom HTML webpage deployed automatically
-
Sign in to the AWS Console → EC2 → Launch Instance.
-
Configure:
-
Launch instance, then open
http://<PUBLIC_IPV4>in your browser.
#!/bin/bash
# Update package list and install Apache
dnf update -y
dnf install -y httpd
# Start and enable Apache service
systemctl start httpd
systemctl enable httpd
# Set permissions for Apache root directory
chown -R ec2-user:ec2-user /var/www/html
# Create a custom index.html page
cat <<'EOF' > /var/www/html/index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Welcome to My Custom Apache Server</title>
<style>
body {
font-family: Arial, sans-serif;
background-color: #f4f4f4;
text-align: center;
padding: 50px;
}
.container {
background: white;
padding: 20px;
border-radius: 10px;
box-shadow: 0px 0px 10px rgba(0, 0, 0, 0.1);
display: inline-block;
}
h1 { color: #333; }
p { color: #666; }
</style>
</head>
<body>
<div class="container">
<h1>Welcome to My Custom Apache Web Server!</h1>
<p>Hosted on an Amazon Linux 2023 EC2 Instance.</p>
<p>This page was deployed automatically using AWS User Data.</p>
</div>
</body>
</html>
EOF
# Restart Apache to apply changes
systemctl restart httpd- In the EC2 Console → Instances, select your instance.
- Copy the Public IPv4 address.
- Open in your browser:
http://<PUBLIC_IPV4>- You should see the custom webpage
- Browser could not reach the page.
- Running
systemctl status httpdreturned:
Unit httpd.service could not be found.
- Security Group initially allowed only SSH (port 22) (no HTTP rule).
- The EC2 User Data did not run correctly at boot, so Apache was never installed.
- Add HTTP inbound rule (Console)
- EC2 → Instances → Select instance → Security → click security group name → Edit inbound rules → Add rule:
- Type: HTTP
- Protocol: TCP
- Port range: 80
- Source:
0.0.0.0/0
- Save rules.
(CLI alternative — requires AWS CLI configured):
aws ec2 authorize-security-group-ingress \
--group-id sg-0123456789abcdef0 \
--protocol tcp \
--port 80 \
--cidr 0.0.0.0/0- SSH into the instance (or use EC2 Instance Connect if no key pair)
ssh ec2-user@<PUBLIC_IPV4>- Check Apache (httpd) status
systemctl status httpdIf you see:
Unit httpd.service could not be found.
→ Apache isn’t installed.
- Install Apache manually
sudo dnf update -y
sudo dnf install -y httpd- Start and enable Apache
sudo systemctl start httpd
sudo systemctl enable httpd- Create or restore the custom index page(Minimal test page)
sudo tee /var/www/html/index.html <<'HTML'
<h1>Hello from Apache on EC2 (Amazon Linux 2023)</h1>
HTMLOr reapply the full HTML from the User Data script (recommended).
- Test locally on the instance
curl http://localhostExpect to see the HTML output.
- Test from your browser
http://<PUBLIC_IPV4>- (Optional) Re-run user data script if automation failed
Check for script saved by cloud-init:
sudo ls -l /var/lib/cloud/instance/scripts/If you find user-data.txt (or similar), re-run:
sudo bash /var/lib/cloud/instance/scripts/user-data.txt- Check cloud-init logs (for debugging)
sudo tail -n 200 /var/log/cloud-init-output.log
sudo tail -n 200 /var/log/cloud-init.logUser Data can fail if:
- A package repo update fails.
- The instance boots before networking is ready.
cloud-initlogs show an error.- The missing
httpdunit meant the install step did not complete.
- Check cloud-init logs:
sudo cat /var/log/cloud-init-output.logIf using IPv6, add ::/0 for HTTP (optional). 0.0.0.0/0 is sufficient for IPv4.
View Apache logs if service fails to start:
sudo journalctl -u httpd -n 100Consider Elastic IP for a stable IP.
Use IAM roles if you automate with CLI.
- Always verify Security Group inbound rules (HTTP is required for web traffic).
systemctloutput — “Unit ... could not be found” usually means the package isn’t installed.- Cloud-init / User Data is powerful but always check its logs to confirm it ran successfully.
- Add HTTPS (ACM + Load Balancer or Nginx + Certbot).
- Provision with Terraform or CloudFormation for reproducible infra.
- Add CI/CD to deploy content changes automatically.
This project is licensed under the MIT License.







