Amazon EC2 explained
Virtual servers on AWS: how to choose one, get into it, and know what you keep and what you lose when it stops.
Checked against the AWS documentation · 21 October 2026
On this page · 17 sections
The short answer
Amazon EC2 (Elastic Compute Cloud) rents you virtual servers, called instances. You choose an instance type (how much CPU and memory), an AMI (the disk image it boots from), a subnet in a VPC, a security group, and how you will log in. Seconds later it is running, and it bills until you stop or terminate it.
The two things that surprise people most: stopping and starting an instance gives it a new public IP address, and terminating it deletes its root disk by default.
An analogy, and where it breaks
An instance is like a rented desk in a co-working space. You pick the size of desk (the instance type) and arrive with your laptop already set up (the AMI). Your locker (the EBS root volume) stays yours when you go home for the night (stop), but someone else may get your desk tomorrow, and your desk phone number (the public IP) changes. Hand back the keys (terminate) and the locker is emptied.
Where it breaks:
- Some instances have a drawer that is emptied every night. Instance store volumes are fast local disks whose data is erased on stop, hibernate and terminate. Only a reboot keeps it.
- You can rent a phone number that follows you. An Elastic IP stays associated through stop and start, but it is charged, as every public IPv4 address now is.
- Going home does not stop the locker rent. A stopped instance stops instance charges; its EBS volumes are still billed.
Instance types and their names
A name such as m7g.large reads in parts. The first letter is the series: m general purpose, c compute optimized, r memory optimized, t burstable, g and p GPU. The number is the generation. The letters after it are options: g AWS Graviton (Arm), a AMD, i Intel, d local instance store disks, n network and EBS optimized. After the dot comes the size, from nano to metal.
The T family (current generations T8i, T4g, T3a and T3; T2 is previous generation) gives a baseline of CPU with the ability to burst above it, which suits web servers and small databases that are mostly idle. Graviton (g) types run Arm, so your software and container images must be built for arm64.
What a launch needs
- An AMI: the operating system image. Its default username matters later.
- A subnet and security group: where it lives and what may reach it. The VPC guide explains both.
- A way in: a key pair for SSH, or nothing at all if you use Session Manager.
- An IAM role (through an instance profile) if software on it calls AWS. Never put access keys on an instance; the IAM guide explains roles.
- Storage: an EBS root volume, which by default is deleted when the instance is terminated.
Connecting to an instance
| Method | Needs | Good for |
|---|---|---|
| SSH client | Public IP (or a route to the private one), port 22 open to you, the key pair’s .pem | Quick access you already know |
| EC2 Instance Connect Endpoint | An endpoint in the VPC; no public IP on the instance | SSH to private instances without a bastion host |
| Session Manager | The instance managed by Systems Manager, and an IAM role with AmazonSSMManagedInstanceCore | No open inbound ports and no keys to manage |
For SSH, the username depends on the AMI:
| AMI | Username |
|---|---|
| Amazon Linux | ec2-user |
| Ubuntu | ubuntu |
| Debian | admin |
| RHEL | ec2-user or root |
| SUSE | ec2-user or root |
| Fedora | fedora or ec2-user |
| CentOS | centos or ec2-user |
| FreeBSD | ec2-user |
chmod 400 my-key.pem ssh -i my-key.pem ec2-user@203.0.113.10
Stop, reboot, hibernate, terminate: what survives
From the EC2 User Guide’s own comparison. Stop and hibernate work only for instances whose root volume is EBS.
| Reboot | Stop, then start | Hibernate | Terminate | |
|---|---|---|---|---|
| Host computer | Same host | Usually a new host | Usually a new host | None |
| Private IPv4 | Kept | Kept | Kept | None |
| Public IPv4 | Kept | New address | New address | None |
| Elastic IP | Stays associated | Stays associated | Stays associated | Disassociated |
| IPv6 | Kept | Kept | Kept | None |
| Instance store data | Kept | Erased | Erased | Erased |
| Root EBS volume | Kept | Kept | Kept | Deleted by default |
| Memory (RAM) | Erased | Erased | Saved to the root volume | Erased |
| Instance charges | Unchanged | Stop at stopping | Stop at stopped | Stop at shutting-down |
- A start after a stop begins a new billing period with a minimum of one minute.
- An instance keeps its public IPv4 address through stop and start only through an Elastic IP associated with it (or with a secondary network interface or private address).
- Shutting down from inside the OS stops an EBS-backed instance by default; that can be changed to terminate. An instance store-backed instance always terminates.
Copy anything on instance store volumes to EBS or S3 before you stop an instance: the data is erased, not paused.
Public and Elastic IP addresses
An instance in a subnet that assigns public addresses gets a public IPv4 address from AWS’s pool. It is released when the instance stops or terminates, which is why a start brings a new one. An Elastic IP is an address you allocate and keep until you release it. AWS charges for all public IPv4 addresses, in use or idle, including Elastic IPs; the Amazon VPC pricing page lists the rate.
Instance metadata and IMDSv2
From inside an instance, 169.254.169.254 answers questions about it: its ID, its Region and the temporary credentials of its IAM role. Version 2 (IMDSv2) answers only with a session token, which must be fetched with a PUT first. AWS describes it as defence in depth against open firewalls, reverse proxies and server-side request forgery: a bug that lets an attacker make your application fetch a URL with a plain GET is no longer enough to read the role’s credentials. Amazon Linux 2023 disables IMDSv1 by default; require IMDSv2 everywhere.
# On the instance: get a token, then use it. TOKEN=$(curl -s -X PUT "http://169.254.169.254/latest/api/token" -H "X-aws-ec2-metadata-token-ttl-seconds: 21600") curl -s -H "X-aws-ec2-metadata-token: $TOKEN" http://169.254.169.254/latest/meta-data/
# From your machine: refuse IMDSv1 on an existing instance. aws ec2 modify-instance-metadata-options --instance-id "$ID" --http-tokens required
User data
User data is a script (or cloud-init configuration) you pass at launch. It runs as root, once, on the first boot by default, is limited to 16 KB before base64 encoding, and writes its output to /var/log/cloud-init-output.log. Because it runs once, treat it as setup for a fresh instance, not as configuration you can change later and reboot to apply.
Ways to pay
- On-Demand: pay by the second for what you run.
- Savings Plans: commit to an hourly spend for 1 or 3 years, for any instance type.
- Reserved Instances: commit to an instance configuration in a Region for 1 or 3 years.
- Spot: spare capacity at a large discount, which AWS can reclaim with a two-minute notice. For work that can be interrupted.
- Dedicated Hosts and Instances, Capacity Reservations: for licensing, isolation or guaranteed capacity.
Try it with the AWS CLI
Inspecting, stopping and starting an instance you already have, and giving it a stable address. These commands were checked against the AWS CLI’s own help (version 2.32.5); they were not run against a live account for this page.
ID=i-1234567890abcdef0 aws ec2 describe-instances --instance-ids "$ID" \ --query 'Reservations[].Instances[].[State.Name,InstanceType,PublicIpAddress,PrivateIpAddress]' --output table
aws ec2 stop-instances --instance-ids "$ID" aws ec2 start-instances --instance-ids "$ID" # Same query again: the public IP has changed, the private IP has not.
# A stable public address: allocate an Elastic IP and associate it. ALLOC=$(aws ec2 allocate-address --domain vpc --query AllocationId --output text) aws ec2 associate-address --instance-id "$ID" --allocation-id "$ALLOC"
An Elastic IP is charged until you release it, associated or not. Release it with aws ec2 release-address --allocation-id "$ALLOC" when the lab is done.
Troubleshooting
ssh: Connection timed out
Nothing answered on port 22. That is the network, not the key: no security group rule for your address, no route to an internet gateway, no public IP, or a network ACL in the way.
aws ec2 describe-instances --instance-ids "$ID" \ --query 'Reservations[].Instances[].[State.Name,PublicIpAddress,SubnetId,SecurityGroups[].GroupId]'
Running, with a public IP? Then check that one of the security groups allows TCP 22 from your current public address, which changes on many home and office networks.
- Allow port 22 from your address (or your network's range) in the security group.
- Check the subnet's route table sends 0.0.0.0/0 to an internet gateway: the VPC guide explains why a subnet is public.
- Or skip the public address entirely: EC2 Instance Connect Endpoint or Session Manager.
Permission denied (publickey)
The server answered and refused the key. Almost always the wrong username for the AMI, or the wrong .pem file for the key pair the instance was launched with.
ssh -i my-key.pem ec2-user@203.0.113.10
Amazon Linux uses ec2-user, Ubuntu ubuntu, Debian admin: the table above lists the rest.
- Use the AMI's username and the key pair named on the instance's Details tab.
WARNING: UNPROTECTED PRIVATE KEY FILE
OpenSSH refuses a private key that other users can read, and then reports Permission denied (publickey).
chmod 400 my-key.pem
Readable by you only. On Windows, remove inherited permissions so only your user can read the file.
- Run the chmod, then connect again.
The public IP changed after a restart
Stopping and starting gives an instance a new public IPv4 address, by design. A reboot keeps it.
aws ec2 describe-instances --instance-ids "$ID" --query 'Reservations[].Instances[].PublicIpAddress'
The current address.
- Point DNS at an Elastic IP, which stays with the instance through stop and start (and is charged like every public IPv4 address).
- Better still, put a load balancer in front and stop caring about the instance's address.
The user data script did not run (or ran only once)
By default, user data runs once, on the first boot after launch, as root. Editing it later and rebooting runs nothing.
sudo tail -n 50 /var/log/cloud-init-output.log
Everything the script printed, and its errors.
- Fix the script and launch a new instance, or configure cloud-init to run it on every boot.
A status check is failing
A failed system check is AWS's hardware or network; a failed instance check is your instance, such as a full disk, a kernel that will not boot or a broken network configuration.
aws ec2 describe-instance-status --instance-ids "$ID"
SystemStatus and InstanceStatus separately.
aws ec2 get-console-output --instance-id "$ID" --latest --output text
The boot log, readable even when you cannot connect.
- System check: stop and start an EBS-backed instance, which usually moves it to a new host.
- Instance check: read the console output, then fix the configuration; a reboot helps only some causes.
Production practice
- No inbound SSH from the internet. Use Session Manager or an Instance Connect Endpoint, and keep port 22 closed.
- Roles, never keys. Software on the instance gets credentials from its IAM role through the metadata service, with IMDSv2 required.
- Treat instances as replaceable. Build them from an AMI and user data, keep state on EBS, S3 or a database, and run more than one behind a load balancer across Availability Zones.
- Alarm on status checks, and read the console output before rebooting a sick instance.
- Right-size and commit. Burstable types for mostly idle servers; Savings Plans for the steady baseline; Spot for interruptible batch work.
Common mistakes
- Hard-coding an instance’s public IP in DNS or config, then stopping it.
- Keeping data on instance store volumes and stopping the instance.
- Terminating an instance and expecting its root volume to remain.
- Opening port 22 to
0.0.0.0/0“for now”. - Editing user data and rebooting, expecting the script to run again.
- Running x86 container images on a Graviton (
g) instance. - Leaving an Elastic IP allocated after the instance is gone.
Interview questions
What is the difference between stopping and terminating an instance?
Stop keeps the instance and its EBS volumes, stops instance charges and gives it a new public IP when started again. Terminate deletes the instance and, by default, its root volume. Neither keeps instance store data.
How do you keep an instance’s public IP across a stop and start?
Associate an Elastic IP. Or, better, do not depend on it: put a load balancer or DNS name in front.
Why require IMDSv2?
Its session token must be fetched with a PUT first, so a server-side request forgery that can only make a plain GET cannot read the instance role’s credentials.
A status check failed. What do you do?
If it is the system check, stop and start the instance to move it to new hardware. If it is the instance check, read the console output and fix what the OS reports: disk, kernel, network configuration.
Questions people ask
Does a stopped instance cost anything?
No instance charges, but its EBS volumes and any Elastic IP are still billed.
Can I change an instance’s type?
Yes, for an EBS-backed instance: stop it, change the type, start it. The new type must be compatible with the instance’s configuration, such as its architecture, and the stop means downtime.
Why can I not SSH into an instance in a private subnet?
It has no route from the internet, by design. Use an EC2 Instance Connect Endpoint or Session Manager.
Where to go next
- The network an instance lives in, and why a subnet is public: Amazon VPC explained.
- Roles for instances, and why a request is denied: AWS IAM explained.
- Where to keep files that must outlive an instance: Amazon S3 explained.
- The SSH key error in more depth: Permission denied (publickey).
- Launching an EC2 instance step by step: AWS EC2 and VPC: Building Your First Cloud Infrastructure.
Sources
Every fact on this page comes from these AWS pages, read on 21 October 2026.
- Amazon EC2 User Guide: What is Amazon EC2?
- Amazon EC2 Instance Types Guide: Instance type naming conventions
- Amazon EC2 User Guide: Burstable performance instances
- Amazon EC2 User Guide: Billing and purchasing options
- Amazon EC2 User Guide: Spot Instances
- Amazon EC2 User Guide: Instance state changes (differences between instance states)
- Amazon EC2 User Guide: Stop and start
- Amazon EC2 User Guide: Instance IP addressing
- Amazon EC2 User Guide: Elastic IP addresses
- Amazon EC2 User Guide: Create a key pair
- Amazon EC2 User Guide: Connect using an SSH client
- Amazon EC2 User Guide: Connect using EC2 Instance Connect Endpoint
- Amazon EC2 User Guide: Connect using Session Manager
- Amazon EC2 User Guide: Troubleshoot Linux instance SSH issues
- Amazon EC2 User Guide: Transition to IMDSv2
- Amazon EC2 User Guide: Access instance metadata
- Amazon EC2 User Guide: Run commands at launch with user data
- Amazon EC2 User Guide: Status checks
- Amazon EC2 User Guide: IAM roles for Amazon EC2
Did this get you to an answer?
No text box on purpose — please do not paste production logs anywhere
Something wrong or out of date? Report it