Skill 77 · Launching EC2 Instance With Best Practices
Subchapter 77.1
references/launch-ec2-instance-with-best-practices.mdMarkdown62 KBView on GitHub
This SOP provides a guided, safe approach to launching an EC2 instance with sensible defaults optimized for security, cost-efficiency, and AWS best practices. The SOP intelligently suggests defaults based on user context while ensuring security hardening, proper IAM roles, appropriate instance sizing, and comprehensive tagging.
Prompt the user in a single message to provide all required parameters at once. Clearly list the required parameters and their descriptions, and include any optional parameters with their default values. Do not proceed until you have received and confirmed all required parameters. If any required parameter is missing or unclear, you MUST explicitly request the missing information before moving forward.
workload_type is bastion-host): CIDR block to allow SSH access from (e.g., “203.0.113.25/32”). If omitted (and not bastion-host), SSH is disabled and access is via AWS Systems Manager Session Manager insteadOnly proceed to the steps below if you have all required information.
Check for required tools and warn the user if any are missing.
Constraints:
Based on the provided parameters, determine appropriate defaults for unspecified options.
Constraints:
workload_type to determine appropriate defaults:
environment:
Validate the VPC and subnet configuration or select appropriate defaults.
Constraints:
aws ec2 describe-vpcs --filters "Name=is-default,Values=true" --region ${region}aws ec2 describe-vpcs --vpc-ids ${vpc_id} --region ${region}aws ec2 describe-subnets --filters "Name=vpc-id,Values=${vpc_id}" --region ${region}enable_public_ip is true, select a public subnetenable_public_ip is false, select a private subnetChoose the most suitable Amazon Machine Image based on workload and region.
Constraints:
aws ec2 describe-images --owners amazon --filters "Name=name,Values=al2023-ami-2023.*-x86_64" "Name=state,Values=available" --query "sort_by(Images, &CreationDate)[-1].[ImageId,Name,Description]" --region ${region}Recommend appropriate instance type based on workload and budget.
Constraints:
aws ec2 describe-instance-type-offerings --location-type availability-zone --filters "Name=instance-type,Values=${instance_type}" --region ${region}Ensure an SSH key pair exists for instance access.
Constraints:
allow_ssh_from is NOT provided and workload_type is not bastion-host and no SSH ingress rule is being created, you MUST skip key pair creation entirely — SSM Session Manager does not require a key pair. Proceed to the next step.allow_ssh_from IS provided or an SSH ingress rule is being created:
You MUST check if key_pair_name was provided
You MUST verify existing key pair if specified: aws ec2 describe-key-pairs --key-names ${key_pair_name} --region ${region}
You MUST create a new key pair if requested or none exists:
aws ec2 create-key-pair --key-name ${key_pair_name} --key-type rsa --key-format pem --region ${region} --query 'KeyMaterial' --output text > ${key_pair_name}.pemYou MUST set appropriate file permissions immediately after creation: chmod 400 ${key_pair_name}.pem
You MUST instruct the user to save the private key material themselves in a secure location and you MUST NOT request or attempt to view the key contents
If the user asks you to store, transmit, or inspect the private key, you MUST decline and recommend engaging AppSec or following the organization’s secure key handling policy
You MUST warn the user that this is the ONLY opportunity to download the private key
You MUST provide clear instructions for saving and protecting the key file:
IMPORTANT: Save this private key securely!
- File location: ./${key_pair_name}.pem
- This is the ONLY copy - it cannot be recovered if lost
- Keep it secure - anyone with this key can access your instance
- Never commit this file to version control
- Set proper permissions: chmod 400 ${key_pair_name}.pemYou MUST add tags to the key pair for tracking: aws ec2 create-tags --resources ${key_pair_id} --tags Key=Name,Value=${key_pair_name} Key=Environment,Value=${environment} Key=CreatedBy,Value=ec2-instance-launch-script --region ${region}
You MUST handle the case where key pair name conflicts with existing key pair
You MUST offer alternative options:
You MUST inform user how to connect using the key pair later
Set up an IAM role if the instance needs to access AWS services.
Constraints:
If allow_ssh_from is NOT provided and workload_type is not bastion-host (SSM Session Manager is the access method), you MUST create the IAM role even if services_needed is empty, and you MUST attach AmazonSSMManagedInstanceCore to it
You MUST skip this step only if services_needed is empty AND (allow_ssh_from IS provided OR workload_type is bastion-host)
You MUST check if a role name was suggested, otherwise generate one: ${instance_name}-role or ${workload_type}-${environment}-role
You MUST check if the role already exists: aws iam get-role --role-name ${role_name}
You MUST create EC2 trust policy document:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"Service": "ec2.amazonaws.com"
},
"Action": "sts:AssumeRole"
}
]
}You MUST create the IAM role: aws iam create-role --role-name ${role_name} --assume-role-policy-document file://trust-policy.json --description "IAM role for ${workload_type} instance in ${environment}"
You MUST apply least privilege principle when selecting permissions:
AmazonS3ReadOnlyAccess, if read-write: custom policy with specific bucket ARNsCloudWatchAgentServerPolicy for metrics and logsAmazonSSMManagedInstanceCore for Systems Manager accessYou MUST create custom inline policies for specific permissions:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"s3:GetObject",
"s3:ListBucket"
],
"Resource": [
"arn:aws:s3:::specific-bucket-name",
"arn:aws:s3:::specific-bucket-name/*"
]
}
]
}You MUST attach policies to the role: aws iam attach-role-policy --role-name ${role_name} --policy-arn ${policy_arn}
You MUST create instance profile: aws iam create-instance-profile --instance-profile-name ${role_name}
You MUST add role to instance profile: aws iam add-role-to-instance-profile --instance-profile-name ${role_name} --role-name ${role_name}
You MUST add tags to the role: aws iam tag-role --role-name ${role_name} --tags Key=Name,Value=${role_name} Key=Environment,Value=${environment} Key=ManagedBy,Value=ec2-instance-launch-script
You MUST wait for the instance profile to be fully created (may take 10-15 seconds)
You MUST verify the instance profile exists: aws iam get-instance-profile --instance-profile-name ${role_name}
You MUST present the created role and attached policies to the user
Configure a security group with minimal required access based on workload type.
Constraints:
${instance_name}-sg or ${workload_type}-${environment}-sgaws ec2 create-security-group --group-name ${sg_name} --description "Security group for ${workload_type} instance in ${environment}" --vpc-id ${vpc_id} --region ${region}workload_type:
allow_ssh_from is providedallow_ssh_from is providedallow_ssh_from is providedallow_ssh_from is providedallow_ssh_from is providedallow_ssh_from is providedallow_ssh_from is REQUIRED for bastion-host — if not provided, you MUST ask the user for it before proceedingallow_ssh_from is provided:
allow_ssh_from is NOT provided and workload_type is not bastion-host, default to NO SSH ingress rule — use AWS Systems Manager Session Manager instead (attach AmazonSSMManagedInstanceCore to the IAM role). Mention this choice in the summary and proceed without askingaws ec2 authorize-security-group-ingress --group-id ${sg_id} --ip-permissions IpProtocol=${protocol},FromPort=${port},ToPort=${port},IpRanges="[{CidrIp=${cidr},Description=${description}}]" --region ${region}aws ec2 create-tags --resources ${sg_id} --tags Key=Name,Value=${sg_name} Key=Environment,Value=${environment} Key=WorkloadType,Value=${workload_type} Key=ManagedBy,Value=ec2-instance-launch-script --region ${region}Define the root volume and any additional EBS volumes.
Constraints:
You MUST determine appropriate root volume size based on workload_type and root_volume_size parameter:
You MUST use gp3 volume type (General Purpose SSD) as default:
You MUST consider volume type alternatives:
You MUST enable encryption by default for security best practices
You MUST use the default AWS-managed KMS key unless user specifies custom key
You MUST configure delete on termination based on environment:
You MUST construct block device mapping for launch:
[
{
"DeviceName": "/dev/xvda",
"Ebs": {
"VolumeSize": ${volume_size},
"VolumeType": "gp3",
"DeleteOnTermination": ${delete_on_termination},
"Encrypted": true
}
}
]You MUST ask user if additional EBS volumes are needed:
You MUST present storage configuration to user:
You MUST warn about cost implications of large volumes and provisioned IOPS
Create a robust tagging strategy for cost tracking, organization, and automation.
Constraints:
You MUST implement a comprehensive tagging strategy with required tags:
instance_name or generated)You MUST generate a default instance name if not provided:
${workload_type}-${environment}-${random_suffix}You MUST ask user for additional tags relevant to their organization:
You MUST format tags for AWS CLI:
[
{"Key": "Name", "Value": "${instance_name}"},
{"Key": "Environment", "Value": "${environment}"},
{"Key": "WorkloadType", "Value": "${workload_type}"},
{"Key": "ManagedBy", "Value": "ec2-instance-launch-script"},
{"Key": "CreatedDate", "Value": "2025-10-14"},
{"Key": "Owner", "Value": "${owner}"},
{"Key": "CostCenter", "Value": "${cost_center}"}
]You MUST present the tagging strategy to the user for review
You MUST explain the importance of consistent tagging:
You MUST validate tag keys and values:
Set up additional instance configuration options.
Constraints:
enable_monitoring is true or environment is productionenable_termination_protection parameter if providedPresent a comprehensive summary of the instance configuration before launching.
Constraints:
Execute the instance launch with all configured settings.
Constraints:
You MUST construct the complete run-instances command with all parameters:
aws ec2 run-instances \
--image-id ${ami_id} \
--instance-type ${instance_type} \
--key-name ${key_pair_name} \
--security-group-ids ${sg_id} \
--subnet-id ${subnet_id} \
--iam-instance-profile Name=${instance_profile_name} \
--block-device-mappings '${block_device_mappings}' \
--tag-specifications "ResourceType=instance,Tags=[${tags}]" "ResourceType=volume,Tags=[${tags}]" \
--metadata-options "HttpTokens=required,HttpPutResponseHopLimit=1,HttpEndpoint=enabled" \
--monitoring Enabled=${enable_monitoring} \
--disable-api-termination=${enable_termination_protection} \
--credit-specification CpuCredits=${cpu_credits} \
--user-data file://user-data.sh \
--region ${region}You MUST include optional parameters only if they were configured:
--iam-instance-profile only if IAM role was created--user-data only if user data script was provided--associate-public-ip-address only if explicitly set--placement only if specific availability zone was requestedYou MUST capture the instance ID from the response: Extract InstanceId from JSON output
You MUST handle launch errors gracefully:
You MUST parse the response and extract key information:
You MUST inform the user immediately upon successful launch:
✓ Instance launched successfully!
Instance ID: i-0abcd1234efgh5678
Private IP: 10.0.1.25
Public IP: 203.0.113.45 (if applicable)
Status: pending (initializing)You MUST save all launch details for the final report
Monitor the instance until it’s fully initialized and running.
Constraints:
You MUST poll the instance status using: aws ec2 describe-instances --instance-ids ${instance_id} --region ${region}
You MUST wait for instance state to transition from “pending” to “running”
You MUST monitor the state transition with appropriate polling:
You MUST display progress updates to the user:
Waiting for instance to start...
Status: pending (0:05)
Status: pending (0:10)
Status: running (0:15) ✓You MUST retrieve and display instance status checks once running:
You MUST handle timeout scenarios:
You MUST provide troubleshooting guidance if launch fails:
aws ec2 get-console-output --instance-id ${instance_id}You MUST inform user when instance is fully ready:
✓ Instance is running and ready!
System status check: passed ✓
Instance status check: passed ✓
Time to ready: 2 minutes 45 secondsConfirm all settings were applied correctly after launch.
Constraints:
aws ec2 describe-instances --instance-ids ${instance_id} --region ${region}aws ec2 describe-security-groups --group-ids ${sg_id} --region ${region}aws ec2 describe-iam-instance-profile-associations --filters "Name=instance-id,Values=${instance_id}" --region ${region}aws ec2 describe-volumes --filters "Name=attachment.instance-id,Values=${instance_id}" --region ${region}Give the user clear instructions for connecting to the instance.
Constraints:
You MUST provide SSH connection instructions if key pair was configured:
# Make sure key file has correct permissions
chmod 400 ${key_pair_name}.pem
# Connect to the instance
ssh -i ${key_pair_name}.pem ec2-user@${public_ip}
# Or using private IP from within VPC
ssh -i ${key_pair_name}.pem ec2-user@${private_ip}You MUST specify the correct default username based on AMI:
ec2-userubuntuec2-user or rootcentosadminec2-userYou MUST provide alternative connection methods:
AWS Systems Manager Session Manager (no SSH key required):
aws ssm start-session --target ${instance_id} --region ${region}Note: Requires SSM agent (pre-installed on Amazon Linux 2023) and IAM role with SSM permissions
EC2 Instance Connect (browser-based SSH):
aws ec2-instance-connect send-ssh-public-key \
--instance-id ${instance_id} \
--availability-zone ${availability_zone} \
--instance-os-user ec2-user \
--ssh-public-key file://~/.ssh/id_rsa.pubEC2 Serial Console (troubleshooting when network is unavailable)
You MUST provide connection troubleshooting tips:
You MUST provide instructions for retrieving instance password (Windows instances):
aws ec2 get-password-data --instance-id ${instance_id} --priv-launch-key file://${key_pair_name}.pemYou MUST explain connection scenarios:
Create a detailed report documenting the entire instance launch and configuration.
Constraints:
You MUST create a complete launch report containing:
You MUST include specific commands and examples for common operations:
# Stop the instance (preserves EBS volumes, stops charges)
aws ec2 stop-instances --instance-ids ${instance_id} --region ${region}
# Start the instance
aws ec2 start-instances --instance-ids ${instance_id} --region ${region}
# Reboot the instance
aws ec2 reboot-instances --instance-ids ${instance_id} --region ${region}
# Get instance details
aws ec2 describe-instances --instance-ids ${instance_id} --region ${region}
# Get console output (troubleshooting)
You MUST provide a security hardening checklist:
sudo yum update -y (Amazon Linux) or sudo apt update && sudo apt upgrade -y (Ubuntu)You MUST provide monitoring recommendations:
You MUST include cost optimization tips:
You MUST format the report in a clear, professional manner with proper sections and subsections
You MUST save the report to a file for user reference: instance-launch-report-${instance_id}-${timestamp}.md
You MUST present the complete report to the user
workload_type: web-server
region: us-east-1
environment: production
services_needed: s3,cloudwatch
allow_ssh_from: 203.0.113.25/32
instance_name: company-website-prod# EC2 Instance Launch Report
**Generated:** 2025-10-14 15:30:45 UTC
**Launch Status:** ✓ Success
**Instance ID:** i-0abcd1234efgh5678
---
## Executive Summary
Successfully launched EC2 instance for production web server workload in us-east-1.
- **Instance Name:** company-website-prod
- **Instance Type:** t3.small (2 vCPU, 2 GB RAM)
- **Operating System:** Amazon Linux 2023
- **Region:** us-east-1a
- **Launch Time:** 2:35 minutes
- **Status:** Running ✓
- **Estimated Monthly Cost:** $15.33
---
## Instance Configuration
### Compute Resources
- **Instance ID:** i-0abcd1234efgh5678
- **Instance Type:** t3.small
- vCPUs: 2
- Memory: 2 GB RAM
- CPU Credits: Unlimited mode (consistent performance)
- Network Performance: Up to 5 Gigabit
- **AMI:** ami-0abcdef1234567890
- Name: Amazon Linux 2023 AMI 2023.4.20250315.0 x86_64 HVM kernel-6.1
- Architecture: x86_64
- Virtualization: HVM
- Root Device: EBS
Alternative: AWS Systems Manager Session Manager:
# No SSH key required, works even without public IP
aws ssm start-session --target i-0abcd1234efgh5678 --region us-east-1
# Requires:
# - SSM agent installed (pre-installed on Amazon Linux 2023)
# - IAM instance profile with AmazonSSMManagedInstanceCore policyAlternative: EC2 Instance Connect:
# Browser-based SSH from AWS Console
# Navigate to: EC2 → Instances → i-0abcd1234efgh5678 → Connect → EC2 Instance Connect| Component | Rate | Hours/Month | Monthly Cost |
|---|---|---|---|
| t3.small instance | $0.0208/hour | 730 | $15.18 |
| Detailed monitoring | $0.14/instance | 1 | $0.14 |
| Component | Size | Rate | Monthly Cost |
|---|---|---|---|
| EBS gp3 volume | 20 GB | $0.08/GB | $1.60 |
| EBS snapshots | 0 GB (initial) | $0.05/GB | $0.00 |
$16.92 (compute + storage + monitoring)
Note: Costs are estimates and may vary based on actual usage, data transfer, and AWS pricing changes. Does not include costs for S3, CloudWatch Logs, or other services.
Update Operating System (Critical - Security)
ssh -i company-website-prod-key.pem ec2-user@54.198.123.45
sudo dnf update -y
sudo rebootInstall Web Server (Application Setup)
# Install Nginx
sudo dnf install nginx -y
sudo systemctl start nginx
sudo systemctl enable nginx
# Or install Apache
sudo dnf install httpd -y
sudo systemctl start httpd
sudo systemctl enable httpdConfigure CloudWatch Agent (Monitoring)
# Download and install CloudWatch agent
wget https://s3.amazonaws.com/amazoncloudwatch-agent/amazon_linux/amd64/latest/amazon-cloudwatch-agent.rpm
sudo rpm -U ./amazon-cloudwatch-agent.rpm
# Configure and start agent
sudo /opt/aws/amazon-cloudwatch-agent/bin/amazon-cloudwatch-agent-config-wizardSet Up Automatic Security Updates (Security)
# Enable automatic updates
sudo dnf install dnf-automatic -y
sudo systemctl enable --now dnf-automatic.timerConfigure Application Logging (Monitoring)
# Forward logs to CloudWatch
sudo vi /opt/aws/amazon-cloudwatch-agent/etc/amazon-cloudwatch-agent.json
# Configure log files to monitorNot done: Change default SSH port (optional, security through obscurity)
Not done: Disable root login: Edit /etc/ssh/sshd_config, set PermitRootLogin no
Not done: Install fail2ban for intrusion prevention:
sudo dnf install fail2ban -y
sudo systemctl enable --now fail2banNot done: Configure OS firewall:
sudo systemctl start firewalld
sudo firewall-cmd --permanent --add-service=http
sudo firewall-cmd --permanent --add-service=https
sudo firewall-cmd --reloadNot done: Set up CloudWatch Logs for SSH access logs
Not done: Configure AWS Backup for automated backups
Not done: Enable VPC Flow Logs for network monitoring
Not done: Implement AWS Config rules for compliance
Not done: Set up AWS GuardDuty for threat detection
Not done: Review IAM policies and tighten to specific resources
CloudWatch Alarms to Create:
CPU Utilization (Performance)
aws cloudwatch put-metric-alarm \
--alarm-name company-website-prod-high-cpu \
--alarm-description "Alert when CPU exceeds 80%" \
--metric-name CPUUtilization \
--namespace AWS/EC2 \
--statistic Average \
--period 300 \
--threshold 80 \
--comparison-operator GreaterThanThreshold \
--evaluation-periods 2 \
--dimensions Name=InstanceId,Value=i-0abcd1234efgh5678Status Check Failed (Availability)
aws cloudwatch put-metric-alarm \
--alarm-name company-website-prod-status-check \
--alarm-description "Alert when status checks fail" \
--metric-name StatusCheckFailed \
--namespace AWS/EC2 \
--statistic Maximum \
--period 60 \
--threshold 1 \
--comparison-operator GreaterThanOrEqualToThreshold \
Disk Space Monitoring (Capacity)
/# Create backup plan in AWS Backup console or CLI
aws backup create-backup-plan --backup-plan file://backup-plan.json
# Associate instance with backup plan
aws backup create-backup-selection --backup-plan-id ${plan_id} --backup-selection file://selection.json# Create manual snapshot
aws ec2 create-snapshot \
--volume-id vol-0123456789abcdef0 \
--description "company-website-prod backup $(date +%Y-%m-%d)" \
--tag-specifications "ResourceType=snapshot,Tags=[{Key=Name,Value=company-website-prod-backup}]"
# Set up automated snapshots with Data Lifecycle Manager (DLM)Stop Instance (Preserves data, stops charges)
aws ec2 stop-instances --instance-ids i-0abcd1234efgh5678 --region us-east-1aws ec2 start-instances --instance-ids i-0abcd1234efgh5678 --region us-east-1Reboot Instance (Graceful restart)
aws ec2 reboot-instances --instance-ids i-0abcd1234efgh5678 --region us-east-1aws ec2 describe-instance-status --instance-ids i-0abcd1234efgh5678 --region us-east-1Create AMI Backup (Complete instance image)
aws ec2 create-image \
--instance-id i-0abcd1234efgh5678 \
--name "company-website-prod-backup-$(date +%Y%m%d)" \
--description "Backup of company-website-prod created on $(date)" \
--no-reboot \
--tag-specifications "ResourceType=image,Tags=[{Key=Name,Value=company-website-prod-backup}]" \
--region us-east-1# Launch new instance from AMI backup
aws ec2 run-instances \
--image-id ami-0xyz789... \
--instance-type t3.small \
--key-name company-website-prod-key \
--security-group-ids sg-0abc123def456789 \
--subnet-id subnet-0123456789abcdef0 \
--region us-east-1Get Console Output (Boot logs, troubleshooting)
aws ec2 get-console-output --instance-id i-0abcd1234efgh5678 --region us-east-1 --output text# CPU Utilization
aws cloudwatch get-metric-statistics \
--namespace AWS/EC2 \
--metric-name CPUUtilization \
--dimensions Name=InstanceId,Value=i-0abcd1234efgh5678 \
--start-time $(date -u -d '1 hour ago' +%Y-%m-%dT%H:%M:%S) \
--end-time $(date -u +%Y-%m-%dT%H:%M:%S) \
--period 300 \
--statistics Average \
--region us-east-1View System Logs (via SSH)
# System messages
sudo tail -f /var/log/messages
# Authentication logs
sudo tail -f /var/log/secure
# Web server logs (Nginx)
sudo tail -f /var/log/nginx/access.log
sudo tail -f /var/log/nginx/error.log⚠️ WARNING: Termination is permanent and will delete the instance!
# Disable termination protection first
aws ec2 modify-instance-attribute \
--instance-id i-0abcd1234efgh5678 \
--no-disable-api-termination \
--region us-east-1
# Terminate the instance (DESTRUCTIVE)
aws ec2 terminate-instances --instance-ids i-0abcd1234efgh5678 --region us-east-1Before terminating:
Symptoms: Connection timeout, connection refused, or authentication failures
Solutions:
Verify instance is running: aws ec2 describe-instances --instance-ids i-0abcd1234efgh5678
Check security group allows SSH from your IP:
# Get your current public IP
curl ifconfig.me
# Verify it matches the security group rule (203.0.113.25/32)
# If changed, update security group:
aws ec2 authorize-security-group-ingress \
--group-id sg-0abc123def456789 \
--protocol tcp --port 22 \
--cidr $(curl -s ifconfig.me)/32Verify key file permissions: ls -l company-website-prod-key.pem (should be 400)
Try verbose SSH output: ssh -vvv -i company-website-prod-key.pem ec2-user@54.198.123.45
Use Session Manager as alternative: aws ssm start-session --target i-0abcd1234efgh5678
System Status Check Failed:
Instance Status Check Failed:
aws ec2 get-console-output --instance-id i-0abcd1234efgh5678Symptoms: Slow performance, CPU metrics above 80%
Investigation:
# SSH into instance
ssh -i company-website-prod-key.pem ec2-user@54.198.123.45
# Check current CPU usage
top
# Identify CPU-intensive processes
ps aux --sort=-%cpu | head
# Check for background updates
sudo systemctl status dnf-automatic
# Monitor over time
watch -n 5 'top -b -n 1 | head -20'Solutions:
Symptoms: Application errors, cannot write files
Investigation:
# Check disk usage
df -h
# Find large directories
sudo du -h / | sort -h | tail -20
# Find large files
sudo find / -type f -size +100M 2>/dev/nullSolutions:
Delete unnecessary files and logs
Rotate and compress old logs
Increase EBS volume size:
# Modify volume size (online, no downtime)
aws ec2 modify-volume --volume-id vol-0123456789abcdef0 --size 40
# After modification, extend filesystem
sudo growpart /dev/xvda 1
sudo resize2fs /dev/xvda1Symptoms: Cannot access internet, cannot reach AWS services
Investigation:
# Test internet connectivity
ping -c 3 8.8.8.8
# Test DNS resolution
nslookup google.com
# Test AWS service connectivity
curl https://s3.amazonaws.com
# Check routing
ip route show
# Check network interfaces
ip addr showSolutions:
Symptoms: Cannot access web application from browser
Investigation:
# Check web server is running
sudo systemctl status nginx # or httpd
# Verify port is listening
sudo netstat -tlnp | grep :80
sudo netstat -tlnp | grep :443
# Test locally
curl http://localhost
curl https://localhost
# Check firewall
sudo firewall-cmd --list-all
# Check logs
sudo tail -f /var/log/nginx/error.logSolutions:
sudo systemctl start nginxSuccessfully launched and configured EC2 instance i-0abcd1234efgh5678 (company-website-prod) in us-east-1. The instance is running with secure, cost-efficient settings following AWS best practices. Complete the post-launch tasks above to finalize your setup and begin using the instance.
Quick Reference:
ssh -i company-website-prod-key.pem ec2-user@54.198.123.45Report generated by ec2-instance-launch-script on 2025-10-14 15:30:45 UTC
## Troubleshooting
### Insufficient Instance Capacity
**Symptoms:** Launch fails with "InsufficientInstanceCapacity" error
**Solutions:**
- Try a different availability zone within the same region
- Try a different instance type (e.g., t3a instead of t3)
- Wait a few minutes and retry
- Consider using different instance family (m6i, c6i, r6i)
- Request a service quota increase if consistently hitting limits
### VPC Limit Reached
**Symptoms:** Cannot launch instance, VPC-related errors
**Solutions:**
- Use existing VPC instead of creating new one
- Delete unused VPCs if at limit (default 5 per region)
- Request VPC limit increase through AWS Support
- Consolidate resources into fewer VPCs
### AMI Not Available
**Symptoms:** AMI ID not found or architecture mismatch
**Solutions:**
- Verify AMI ID is correct for the region
- Check AMI is not deprecated or deregistered
- Ensure AMI architecture matches instance type (x86_64 vs arm64)
- Query for the latest AMI that matches the selected OS (e.g., Amazon Linux 2023 via `describe-images`, Ubuntu via SSM Parameter Store)
- Consider using AWS Systems Manager Parameter Store for latest AMI IDs
Symptoms: Actual costs exceed estimates
Solutions:
This file