← All posts
2 min read

EC2 from Zero: launch your first instance

#aws#ec2#linux#cli
📑 On this page

Part 8 of AWS from Zero. EC2 is AWS virtual machines.

Today we create the smallest useful flow:

  1. Find a VPC.
  2. Create a security group.
  3. Create a key pair.
  4. Find an Amazon Linux AMI.
  5. Launch an instance.
  6. SSH into it.
  7. Terminate it.

Set variables

REGION="ap-south-1"
KEY_NAME="aws-zero-key"
SG_NAME="aws-zero-ssh"

Find your default VPC:

VPC_ID=$(aws ec2 describe-vpcs \
  --region "$REGION" \
  --filters "Name=is-default,Values=true" \
  --query "Vpcs[0].VpcId" \
  --output text)

Check it:

echo "$VPC_ID"

Create a key pair

aws ec2 create-key-pair \
  --region "$REGION" \
  --key-name "$KEY_NAME" \
  --query "KeyMaterial" \
  --output text > "$KEY_NAME.pem"

Protect it:

chmod 400 "$KEY_NAME.pem"

On Windows, use a secure folder and OpenSSH. If permissions complain, adjust file ACLs or use Windows Terminal with the built-in SSH client.

Create a security group

SG_ID=$(aws ec2 create-security-group \
  --region "$REGION" \
  --group-name "$SG_NAME" \
  --description "SSH access for AWS from Zero" \
  --vpc-id "$VPC_ID" \
  --query "GroupId" \
  --output text)

Allow SSH from your current public IP:

MY_IP=$(curl -s https://checkip.amazonaws.com)
aws ec2 authorize-security-group-ingress \
  --region "$REGION" \
  --group-id "$SG_ID" \
  --protocol tcp \
  --port 22 \
  --cidr "$MY_IP/32"

Find an Amazon Linux AMI

AMI_ID=$(aws ec2 describe-images \
  --region "$REGION" \
  --owners amazon \
  --filters "Name=name,Values=al2023-ami-*-x86_64" "Name=state,Values=available" \
  --query "sort_by(Images, &CreationDate)[-1].ImageId" \
  --output text)

Launch the instance

INSTANCE_ID=$(aws ec2 run-instances \
  --region "$REGION" \
  --image-id "$AMI_ID" \
  --instance-type t3.micro \
  --key-name "$KEY_NAME" \
  --security-group-ids "$SG_ID" \
  --tag-specifications "ResourceType=instance,Tags=[{Key=Project,Value=aws-from-zero},{Key=Name,Value=aws-zero-ec2}]" \
  --query "Instances[0].InstanceId" \
  --output text)

Wait until it is running:

aws ec2 wait instance-running --region "$REGION" --instance-ids "$INSTANCE_ID"

Get the public IP:

PUBLIC_IP=$(aws ec2 describe-instances \
  --region "$REGION" \
  --instance-ids "$INSTANCE_ID" \
  --query "Reservations[0].Instances[0].PublicIpAddress" \
  --output text)

SSH:

ssh -i "$KEY_NAME.pem" ec2-user@"$PUBLIC_IP"

Cleanup

Exit SSH, then terminate:

aws ec2 terminate-instances --region "$REGION" --instance-ids "$INSTANCE_ID"
aws ec2 wait instance-terminated --region "$REGION" --instance-ids "$INSTANCE_ID"

Delete the security group and key pair:

aws ec2 delete-security-group --region "$REGION" --group-id "$SG_ID"
aws ec2 delete-key-pair --region "$REGION" --key-name "$KEY_NAME"
rm "$KEY_NAME.pem"

In part 9, we stop relying on the default VPC and build networking pieces ourselves.