AWS EC2 Reference

A reference for AWS EC2: instance types, security groups, key pairs, EBS volumes, and IAM roles.

Instance types

The instance type name encodes its family, generation, and size — e.g. t3.micro: t family (burstable, general purpose), generation 3, size micro.

FamilyGood for
t (t3, t3a, t4g)Burstable general purpose — low baseline CPU that can burst using credits. Cheapest option for a small app or dev/staging box with spiky, low-average load.
m (m6i, m7g)General purpose with steady, non-burstable performance — a production app under consistent load.
c (c6i, c7g)Compute-optimised — CPU-bound workloads like batch processing or video encoding.
r (r6i, r7g)Memory-optimised — in-memory caches, large databases.

A t3.micro running below its baseline CPU accrues "CPU credits"; sustained high CPU spends them faster than they accrue, and once exhausted, performance drops to the (low) baseline. Fine for typical web traffic; not fine for a workload that's CPU-heavy for sustained periods — that calls for an m or c family instance instead.

Key pairs

EC2 injects the public half of a key pair into the instance at launch (via ~/.ssh/authorized_keys) — there's no password login by default. The private half is downloaded once at creation and never stored by AWS again, so losing it on a running instance with no other access configured generally means rebuilding it from a snapshot/AMI with a new key.

chmod 400 my-key.pem
ssh -i my-key.pem ec2-user@PUBLIC_IP   # Amazon Linux
ssh -i my-key.pem ubuntu@PUBLIC_IP     # Ubuntu

Security groups

A security group is a stateful virtual firewall attached to an instance's network interface — stateful meaning a response to an allowed inbound request is automatically allowed back out, so outbound rules rarely need to be touched. Unlike Lightsail's per-instance rule list, a security group is a reusable object that can be attached to many instances at once.

TypePortSource
SSH22Your IP (x.x.x.x/32), not 0.0.0.0/0
HTTP800.0.0.0/0
HTTPS4430.0.0.0/0
Custom (app to DB)e.g. 5432/3306The app's own security group, not a raw IP range

Referencing one security group as the source of a rule in another (rather than a CIDR range) is the standard pattern for "let the app servers talk to the database" — it keeps working automatically as instances are added or replaced, since it's scoped to the group, not to specific IPs.

Elastic IPs

A regular EC2 public IP changes on stop/start, exactly like Lightsail's default IP. An Elastic IP is a static IP you allocate and associate with an instance — free while attached to a running instance, billed hourly if allocated but not attached (a real cost to actually watch for, since it's easy to leave an old one dangling after decommissioning an instance).

EBS volumes

EBS (Elastic Block Store) is the network-attached disk behind most instances — the root volume by default, plus any extra volumes attached for data. Snapshots are incremental (only changed blocks are stored after the first), which makes frequent snapshots cheap relative to their apparent size. A volume can be resized upward live from the console, but the filesystem on top still needs growing to see the extra space:

# after increasing the volume size in the console:
sudo growpart /dev/xvda 1
sudo resize2fs /dev/xvda1   # ext4
# or: sudo xfs_growfs /                for xfs

IAM roles (vs. access keys)

An IAM role attached to an instance grants it temporary, auto-rotating credentials for calling other AWS services (S3, SES, etc.) without ever putting a long-lived access key in .env or on disk. This is the recommended approach over hardcoding AWS_ACCESS_KEY_ID/AWS_SECRET_ACCESS_KEY for anything running on EC2 — the AWS SDK picks the role's credentials up automatically from the instance metadata service with no extra configuration.

User data

A user data script runs once, as root, on an instance's first boot — the standard way to bootstrap a fresh instance (install packages, pull a deploy, write config) without connecting manually:

#!/bin/bash
apt-get update -y
apt-get install -y nginx php8.3-fpm
systemctl enable nginx php8.3-fpm
systemctl start nginx php8.3-fpm