🛠️ Hands-On Lab Guide: L1 Support Engineer Skills
Lab 1: Windows Server + IIS Setup (Core L1 Skill)
Objective
Launch a Windows Server EC2, install IIS, deploy a test website, and practice troubleshooting.
Step-by-Step
1. Launch a Windows EC2 Instance
AWS Console → EC2 → Launch Instance
Name: L1-Lab-Windows-IIS
AMI: Microsoft Windows Server 2022 Base
Instance type: t3.medium
Key pair: Create new → "l1-lab-key" → Download .pem
Security Group: Create new with these rules:
- RDP (port 3389) → My IP
- HTTP (port 80) → 0.0.0.0/0
- HTTPS (port 443) → 0.0.0.0/0
Click "Launch Instance"
2. Connect via RDP

Password:
6xr&;(LfLeaZyayHGSpjA9c@!OgA$xBF
Private IP address
172.31.7.190
1. Select your instance → Click "Connect"
2. Go to "RDP Client" tab
3. Click "Get password" → Upload your .pem key file → Decrypt
4. Download the RDP file
5. Open it with Remote Desktop Connection
6. Enter the decrypted password
7. You're now on a Windows Server!
3. Install IIS (Internet Information Services)
Open PowerShell as Administrator on the Windows Server:
# Install IIS with management tools
Install-WindowsFeature -Name Web-Server -IncludeManagementTools
# Verify IIS is running
Get-Service W3SVC
# Check IIS is serving the default page
Invoke-WebRequest -Uri http://localhost -UseBasicParsing | Select-Object StatusCode
4. Deploy a Test Website
# Navigate to the default website directory
cd C:\inetpub\wwwroot
# Backup the default page
Rename-Item .\iisstart.htm .\iisstart.htm.bak
# Create a custom test page
@"
<!DOCTYPE html>
<html>
<head><title>L1 Lab - Test Application</title></head>
<body>
<h1>L1 Support Lab - Application Running</h1>
<p>Server: $(hostname)</p>
<p>Time: <span id="time"></span></p>
<p>Status: <span style="color:green;">HEALTHY</span></p>
<script>
document.getElementById('time').textContent = new Date().toISOString();
</script>
</body>
</html>
"@ | Out-File -FilePath .\index.html -Encoding UTF8
5. Verify — Open a browser and navigate to your EC2 Public IP:
http://<your-ec2-public-ip>
You should see your test page. ✅
🔥 Troubleshooting Exercises
Exercise A: Simulate "Website Down" (IIS Stopped)
# Stop IIS
Stop-Service W3SVC
# Now try accessing the website in browser — it fails!
# This simulates a P1 incident: "Website is down"
# How to diagnose:
Get-Service W3SVC # Shows "Stopped"
# How to fix:
Start-Service W3SVC
# Verify:
Invoke-WebRequest -Uri http://localhost -UseBasicParsing | Select-Object StatusCode
Exercise B: Simulate "Port Blocked"
# Block port 80 in Windows Firewall
New-NetFirewallRule -DisplayName "Block HTTP" -Direction Inbound -LocalPort 80 -Protocol TCP -Action Block
# Website now unreachable from outside, but IIS is running!
# This simulates: "IIS is running but website not accessible"
# Diagnose:
Get-NetFirewallRule -DisplayName "Block HTTP"
# Fix:
Remove-NetFirewallRule -DisplayName "Block HTTP"
Exercise C: Check Event Viewer for Errors
# View recent IIS-related events
Get-EventLog -LogName System -Source "IIS*" -Newest 10
# View application errors
Get-EventLog -LogName Application -EntryType Error -Newest 20
# This is how you find error evidence for incident reports
Lab 2: Linux Server + Log Analysis (Core L1 Skill)
Objective
Launch a Linux EC2, practice essential commands, analyze logs, and simulate issues.
Step-by-Step
1. Launch a Linux EC2 Instance
AWS Console → EC2 → Launch Instance
Name: L1-Lab-Linux
AMI: Amazon Linux 2023
Instance type: t3.micro (save your t3.medium for IIS)
Key pair: Use same "l1-lab-key"
Security Group: Allow SSH (port 22) from My IP
Click "Launch Instance"
2. Connect via SSH
From your local terminal (or use EC2 Instance Connect in the browser):
# If using terminal (convert .pem permissions first on Linux/Mac)
ssh -i "l1-lab-key.pem" ec2-user@<your-linux-public-ip>
# Or: AWS Console → Select Instance → Connect → EC2 Instance Connect → Connect
3. Essential L1 Commands — Practice Each One
# ===== SYSTEM INFORMATION =====
# Check who you are
whoami
# Check server hostname
hostname
# Check OS version
cat /etc/os-release
# Check uptime (how long server has been running)
uptime
# ===== CPU & MEMORY =====
# Check CPU usage (press 'q' to exit)
top
# Check memory usage
free -m
# Detailed memory info
cat /proc/meminfo | head -5
# ===== DISK SPACE =====
# Check disk usage (human-readable)
df -h
# Check which directories are using most space
du -sh /var/log/*
# ===== PROCESSES =====
# List all running processes
ps aux
# Find a specific process
ps aux | grep httpd
# Count running processes
ps aux | wc -l
# ===== NETWORK =====
# Check network interfaces
ip addr show
# Check open ports
ss -tlnp
# Test if a remote service is reachable
curl -I http://google.com
4. Log Analysis — The Core L1 Skill
# ===== VIEWING LOGS =====
# View system logs
sudo cat /var/log/messages | tail -50
# Follow logs in real-time (CRITICAL L1 SKILL)
sudo tail -f /var/log/messages
# (Press Ctrl+C to stop)
# Search logs for errors
sudo grep -i "error" /var/log/messages
# Search for specific timestamps
sudo grep "Aug 17" /var/log/messages
# Count how many errors occurred
sudo grep -ic "error" /var/log/messages
# ===== JOURNALCTL (systemd logs) =====
# View recent logs
sudo journalctl -n 50
# View logs since a specific time
sudo journalctl --since "1 hour ago"
# View logs for a specific service
sudo journalctl -u sshd -n 20
# Follow logs live
sudo journalctl -f
5. Simulate and Analyze Errors
# Create a fake application log for practice
sudo bash -c 'cat > /var/log/test-app.log << EOF
2026-08-17 10:00:01 INFO Application started successfully
2026-08-17 10:00:02 INFO Database connection established
2026-08-17 10:05:15 WARN Slow query detected: 3200ms on /api/users
2026-08-17 10:05:16 WARN Connection pool usage at 85%
2026-08-17 10:10:30 ERROR Database connection timeout after 30000ms
2026-08-17 10:10:31 ERROR java.sql.SQLException: Cannot acquire connection from pool
2026-08-17 10:10:32 ERROR HTTP 500 returned for GET /api/users/123
2026-08-17 10:10:33 ERROR HTTP 500 returned for POST /api/orders
2026-08-17 10:10:34 WARN Retry attempt 1 for database connection
2026-08-17 10:10:35 WARN Retry attempt 2 for database connection
2026-08-17 10:10:36 ERROR All retry attempts exhausted. Service degraded.
2026-08-17 10:15:00 INFO Database connection re-established
2026-08-17 10:15:01 INFO Service recovered. All endpoints healthy.
EOF'
# Now practice analysis:
# Find all errors
grep "ERROR" /var/log/test-app.log
# Find when errors started
grep "ERROR" /var/log/test-app.log | head -1
# Find when service recovered
grep "recovered" /var/log/test-app.log
# Count errors vs warnings
echo "Errors: $(grep -c 'ERROR' /var/log/test-app.log)"
echo "Warnings: $(grep -c 'WARN' /var/log/test-app.log)"
# Find the root cause pattern
grep -E "timeout|connection" /var/log/test-app.log
[!TIP]
Practice narrating your findings out loud:
"Errors started at 10:10:30. The root cause appears to be database connection timeout. The connection pool was already at 85% utilization at 10:05. This caused HTTP 500 errors on multiple endpoints. Service auto-recovered at 10:15 after database connection was re-established."
This is exactly how you'd communicate during a P1 bridge call.
Lab 3: AWS CloudWatch Monitoring (Monitoring Skill)
Objective
Set up CloudWatch dashboards and alarms for your EC2 instances.
Step-by-Step
1. View Default EC2 Metrics
AWS Console → CloudWatch → Metrics → All metrics
Click: EC2 → Per-Instance Metrics
Find your instances. Select:
✅ CPUUtilization
✅ NetworkIn
✅ NetworkOut
✅ StatusCheckFailed
Click "Graphed metrics" tab to see the charts
2. Create a CloudWatch Dashboard
CloudWatch → Dashboards → Create Dashboard
Name: "L1-Lab-Monitoring"
Add Widget → Line chart → Select:
- EC2 > Per-Instance > CPUUtilization (for both instances)
Add Widget → Number → Select:
- EC2 > Per-Instance > StatusCheckFailed
Add Widget → Line chart → Select:
- EC2 > Per-Instance > NetworkIn + NetworkOut
Save Dashboard
3. Create a CloudWatch Alarm (P1 Simulation)
CloudWatch → Alarms → Create Alarm
Select Metric: EC2 → Per-Instance → CPUUtilization
Select your Windows IIS instance
Conditions:
Threshold type: Static
Greater than: 80
Period: 1 minute
Datapoints: 1 out of 1
Notification:
Create new SNS topic: "L1-Lab-Alerts"
Email: your-email@example.com
Alarm name: "High-CPU-IIS-Server"
Description: "CPU above 80% on IIS production server"
Create Alarm
4. Trigger the Alarm (Simulate High CPU)
RDP into your Windows Server and run:
# Simulate CPU load (will spike CPU to ~100%)
# Run this in PowerShell:
$cores = (Get-WmiObject Win32_Processor).NumberOfLogicalProcessors
1..$cores | ForEach-Object {
Start-Job -ScriptBlock {
$end = (Get-Date).AddMinutes(3)
while ((Get-Date) -lt $end) { [math]::Sqrt(12345) | Out-Null }
}
}
# Watch CPU spike in Task Manager
# Check CloudWatch — the alarm should trigger within 2-3 minutes
# Stop the load after testing:
Get-Job | Stop-Job
Get-Job | Remove-Job
5. Check the Alarm
CloudWatch → Alarms → "High-CPU-IIS-Server"
State should change: OK → In alarm
This is exactly what happens in production.
You'd see this alarm, investigate CPU usage, and open an incident.
[!NOTE]
In real-world L1 support, you'd receive this alarm via email/Slack/PagerDuty, investigate the cause (runaway process? traffic spike? deployment?), and either fix it or escalate.
Lab 4: REST API Troubleshooting with Postman + curl
Objective
Test APIs, understand HTTP status codes, and diagnose API failures.
Step-by-Step (No EC2 needed — use your local machine)
1. Install Postman
Download from: https://www.postman.com/downloads/
2. Test a Public API
Method: GET
URL: https://jsonplaceholder.typicode.com/posts/1
Click Send
Expected:
Status: 200 OK
Body: JSON with a post object (userId, id, title, body)
3. Test Different Status Codes
# 200 - Success
GET https://jsonplaceholder.typicode.com/posts/1
# 404 - Not Found
GET https://jsonplaceholder.typicode.com/posts/99999
# Test another API for different codes:
GET https://httpstat.us/200 → Returns 200
GET https://httpstat.us/401 → Returns 401 Unauthorized
GET https://httpstat.us/403 → Returns 403 Forbidden
GET https://httpstat.us/500 → Returns 500 Internal Server Error
GET https://httpstat.us/502 → Returns 502 Bad Gateway
GET https://httpstat.us/503 → Returns 503 Service Unavailable
4. Test POST Request
Method: POST
URL: https://jsonplaceholder.typicode.com/posts
Headers:
Content-Type: application/json
Body (raw JSON):
{
"title": "Test from L1 Lab",
"body": "Testing API creation",
"userId": 1
}
Click Send
Expected:
Status: 201 Created
Body: JSON with id: 101
5. Using curl from Command Line
# GET request
curl -v https://jsonplaceholder.typicode.com/posts/1
# POST request
curl -X POST https://jsonplaceholder.typicode.com/posts \
-H "Content-Type: application/json" \
-d '{"title":"Test","body":"Testing","userId":1}'
# Check only status code
curl -s -o /dev/null -w "%{http_code}" https://jsonplaceholder.typicode.com/posts/1
# Check response headers
curl -I https://jsonplaceholder.typicode.com/posts/1
# Test timeout behavior (useful for troubleshooting)
curl --max-time 5 https://httpstat.us/200?sleep=10000
# This will timeout after 5 seconds — simulates API timeout
6. Practice Scenario: "Client reports API not working"
Client says: "The /users endpoint is returning errors"
Your investigation steps:
1. Test the endpoint:
GET https://jsonplaceholder.typicode.com/users
2. Check status code — is it 200, 401, 500, 503?
3. Check response time — Headers tab in Postman shows duration
4. Check response body — any error messages?
5. Test with different parameters:
GET https://jsonplaceholder.typicode.com/users/1
GET https://jsonplaceholder.typicode.com/users?email=Sincere@april.biz
6. Document your findings:
"Tested /users endpoint at 14:30 UTC.
Status: 200 OK.
Response time: 245ms.
Data returned correctly for all test cases.
Unable to reproduce client's issue.
Requesting client to share:
- Exact URL they're hitting
- Request headers (especially Authorization)
- Screenshot of the error
- Browser/client they're using"
Lab 5: Writing an Incident Report + RCA
Objective
Practice writing a real incident report from the issues you simulated.
Template
# Incident Report
**Incident ID:** INC-2026-0817-001
**Priority:** P2 - High
**Status:** Resolved
## Summary
IIS web server on production EC2 instance became unreachable
at 10:10 UTC on August 17, 2026. Root cause identified as
IIS service failure. Service restored at 10:25 UTC.
Total downtime: 15 minutes.
## Timeline
| Time (UTC) | Event |
|------------|-------|
| 10:10 | CloudWatch alarm triggered: StatusCheckFailed |
| 10:12 | L1 engineer acknowledged the incident |
| 10:13 | Client notification sent: "Investigating reported downtime" |
| 10:15 | RDP to server confirmed IIS service stopped |
| 10:16 | Event Viewer checked — unexpected service termination logged |
| 10:18 | IIS service restarted |
| 10:20 | Website verified accessible |
| 10:22 | CloudWatch alarm returned to OK state |
| 10:25 | Client notified: "Service restored, monitoring for stability" |
## Root Cause
The IIS (W3SVC) service stopped unexpectedly due to [cause].
Event Viewer logs showed [specific error details].
## Impact
- All users accessing the web application were affected
- Duration: 15 minutes
- No data loss occurred
## Resolution
IIS service was restarted manually via PowerShell:
`Start-Service W3SVC`
## Preventive Measures
1. Configure IIS service auto-recovery (restart on failure)
2. Add CloudWatch alarm for W3SVC service status
3. Investigate root cause of service termination
4. Add automated health check endpoint monitoring
## Lessons Learned
- Need automated service recovery configuration
- CloudWatch alarm detected issue 2 minutes before client report
- Communication template was used effectively
[!TIP]
Write at least 3 RCA reports using different scenarios from these labs. This is a frequently asked skill in L1 support interviews.
Lab Checklist — Track Your Progress
| # | Lab | Skill | Done? |
|---|---|---|---|
| 1 | Windows EC2 + IIS | Server management, IIS administration | ☐ |
| 2 | Linux EC2 + Logs | CLI commands, log analysis | ☐ |
| 3 | CloudWatch Monitoring | Metrics, dashboards, alarms | ☐ |
| 4 | Postman + curl | API testing, status codes | ☐ |
| 5 | Incident Report + RCA | Documentation, communication | ☐ |
Quick Reference: Key Commands
Windows (PowerShell)
Get-Service W3SVC # Check IIS status
Start-Service W3SVC # Start IIS
Stop-Service W3SVC # Stop IIS
Restart-Service W3SVC # Restart IIS
Get-EventLog -LogName System -Newest 20 # Recent system events
Get-Process | Sort-Object CPU -Desc | Select -First 10 # Top CPU processes
Test-NetConnection google.com -Port 443 # Test network connectivity
Linux (Bash)
top # CPU/Memory usage (live)
free -m # Memory usage
df -h # Disk space
ps aux # Running processes
tail -f /var/log/messages # Follow logs
grep "ERROR" logfile # Search for errors
journalctl -f # Follow system logs
ss -tlnp # Open ports
curl -I url # Check HTTP response
systemctl status httpd # Check service status
AWS CLI (Bonus)
# Describe your instances
aws ec2 describe-instances --query 'Reservations[*].Instances[*].[InstanceId,State.Name,PublicIpAddress]' --output table
# Get CloudWatch CPU metric
aws cloudwatch get-metric-statistics \
--namespace AWS/EC2 \
--metric-name CPUUtilization \
--dimensions Name=InstanceId,Value=YOUR_INSTANCE_ID \
--start-time 2026-08-17T00:00:00Z \
--end-time 2026-08-17T23:59:59Z \
--period 300 \
--statistics Average
[!IMPORTANT]
Sandbox Time Management: sandbox sessions expire. Prioritize:
- Lab 1 (IIS) — takes ~30 min
- Lab 2 (Linux) — takes ~20 min
- Lab 3 (CloudWatch) — takes ~15 min
Labs 4 and 5 don't need the sandbox. Do them on your local machine anytime.














































































Top comments (0)