Project Workflow
Introduction
Cloud infrastructure management is often associated with the convenience of graphical interfaces like AWS console. But what if I told you that you could completely set up a fully functional Virtual Private Cloud (VPC) with public and private subnets, internet access, NAT gateways, and EC2 instances, all from the command line?
In this guide, I'll walk you through the entire process, from creating a VPC from scratch, configuring subnets, and launching EC2 instances in both public and private subnets. Everything will be done using the powerful AWS CLI. No clicks. Just pure CLI magic. So, are you ready to dive in? Let’s get started!
Architectural Diagram.
Prerequisites
You must have AWS CLI is installed and configured.
You must have a key pair for SSH access, or create one using the CLI.
Replace placeholders with actual values from your AWS environment.
Step 1: Create a VPC
-
Create a VPC with a CIDR block of your choice (e.g., 10.0.0.0/16).
To do this, use the command,
aws ec2 create-vpc --cidr-block <IP address>
C:\Users\Nsisong>aws ec2 create-vpc --cidr-block 10.0.0.0/16
{
"Vpc": {
"CidrBlock": "10.0.0.0/16",
"DhcpOptionsId": "dopt-04bb9d34aac15e56f",
"State": "pending",
"VpcId": "vpc-086c99e11cde64580",
"OwnerId": "101061110965",
"InstanceTenancy": "default",
"Ipv6CidrBlockAssociationSet": [],
"CidrBlockAssociationSet": [
{
"AssociationId": "vpc-cidr-assoc-054cc70aca2d0823d",
"CidrBlock": "10.0.0.0/16",
"CidrBlockState": {
"State": "associated"
}
}
],
"IsDefault": false
}
}
Create tag or a descriptive name for your VPC.
To do this, use the command
aws ec2 create-tags --resources <Your vpc> --tags Key=Name,Value=<name>
Replace the placeholers with vpc id and with a name.
C:\Users\Nsisong>aws ec2 create-tags --resources vpc-086c99e11cde64580 --tags Key=Name,Value=CLI-VPC
Step 2: Create Subnets
- Create a public subnet
- Use the following command
aws ec2 create-subnet --vpc-id <VpcId> --cidr-block 10.0.1.0/24
- Configure an IP range that is still within your VPC cidr-block.
C:\Users\Nsisong>aws ec2 create-subnet --vpc-id vpc-086c99e11cde64580 --cidr-block 10.0.1.
0/24
{
"Subnet": {
"AvailabilityZone": "us-east-1f",
"AvailabilityZoneId": "use1-az5",
"AvailableIpAddressCount": 251,
"CidrBlock": "10.0.1.0/24",
"DefaultForAz": false,
"MapPublicIpOnLaunch": false,
"State": "available",
"SubnetId": "subnet-090e0fa27cedb8e6a",
"VpcId": "vpc-086c99e11cde64580",
"OwnerId": "101061110965",
"AssignIpv6AddressOnCreation": false, "Ipv6CidrBlockAssociationSet": [],
"SubnetArn": "arn:aws:ec2:us-east-1:101061110965:subnet/subnet-090e0fa27cedb8e6a", "EnableDns64": false,
"Ipv6Native": false,
"PrivateDnsNameOptionsOnLaunch": {
"HostnameType": "ip-name",
"EnableResourceNameDnsARecord": false,
"EnableResourceNameDnsAAAARecord": false
}
}
}
Create tag or a descriptive name for your Public-subnet.
aws ec2 create-tags --resources <subnetId> --tags Key=Name,Value=<name>
For resources, copy and paste your subnetId
For Value, provide a name for Public subnet
C:\Users\Nsisong>aws ec2 create-tags --resources subnet-090e0fa27cedb8e6a --tags Key=Name,Value=CLI-Public-subnet
Create a private subnet
Use the following command
aws ec2 create-subnet --vpc-id <VpcId> --cidr-block 10.0.2.0/24
Replace with your VPC ID.
Configure an IP range that is still within your VPC cidr-block.
C:\Users\Nsisong>aws ec2 create-subnet --vpc-id vpc-086c99e11cde64580 --cidr-block 10.0.2.0/24
{
"Subnet": {
"AvailabilityZone": "us-east-1f",
"AvailabilityZoneId": "use1-az5",
"AvailableIpAddressCount": 251,
"CidrBlock": "10.0.2.0/24",
"DefaultForAz": false,
"MapPublicIpOnLaunch": false,
"State": "available",
"SubnetId": "subnet-0ab4cd05a41dc4882",
"VpcId": "vpc-086c99e11cde64580",
"OwnerId": "101061110965",
"AssignIpv6AddressOnCreation": false,
"Ipv6CidrBlockAssociationSet": [],
"SubnetArn": "arn:aws:ec2:us-east-1:101061110965:subnet/subnet-0ab4cd05a41dc4882",
"EnableDns64": false,
"Ipv6Native": false,
"PrivateDnsNameOptionsOnLaunch": {
"HostnameType": "ip-name",
"EnableResourceNameDnsARecord": false,
"EnableResourceNameDnsAAAARecord": false
}
}
}
Create tag or a descriptive name for your Private-subnet.
aws ec2 create-tags --resources <subnetId> --tags Key=Name,Value=<name>
For resources, copy and paste your subnetId
For Value, provide a name for Private subnet
C:\Users\Nsisong>aws ec2 create-tags --resources subnet-0ab4cd05a41dc4882 --tags Key=Name,Value=CLI-Private-
subnet
Step 3: Create and Attach an Internet Gateway
Create an internet gateway
Use the following command
aws ec2 create-internet-gateway
C:\Users\Nsisong>aws ec2 create-internet-gateway
{
"InternetGateway": {
"Attachments": [],
"InternetGatewayId": "igw-0e9b76329f85c97ca",
"OwnerId": "101061110965",
"Tags": []
}
}
Create tag or a descriptive name for your Internet Gateway.
aws ec2 create-tags --resources <igwId> --tags Key=Name,Value=<name>
For resources, copy and paste your igwId
For Value, provide a name for Internet gateway.
C:\Users\Nsisong>aws ec2 create-tags --resources igw-0e9b76329f85c97ca --tags Key=Name,Value=CLI-internetGat
eway
Now, attach the internet gateway to the VPC.
To do this, use the command
aws ec2 attach-internet-gateway --vpc-id <VpcId> --internet-gateway-id <InternetGatewayId>
For vpc-id, copy and paste your actual VpcId
For internet-gateway-id, copy and paste your InternetGatewayId
C:\Users\Nsisong>aws ec2 attach-internet-gateway --vpc-id vpc-086c99e11cde64580 --internet-gateway-id igw-0e
9b76329f85c97ca
Step 4: Create an Elastic IP and Nat gateway
First, allocate an Elastic IP for the Nat gateway.
To do this, use the command
aws ec2 allocate-address
C:\Users\Nsisong>aws ec2 allocate-address
{
"PublicIp": "34.224.220.87",
"AllocationId": "eipalloc-0b582827c154b315d",
"PublicIpv4Pool": "amazon",
"NetworkBorderGroup": "us-east-1",
"Domain": "vpc"
}
Now, create a Nat gateway in the public subnet
To do this, use the command
aws ec2 create-nat-gateway --subnet-id <PublicSubnetId> --allocation-id <AllocationId>
For subnet-id, copy and paste your PublicSubnetId.
For allocation-id, copy and paste your AllocationId.
C:\Users\Nsisong>aws ec2 create-nat-gateway --subnet-id subnet-090e0fa27cedb8e6a --allocation-id eipalloc-0b
582827c154b315d
{
"ClientToken": "b526971b-6815-4f0e-8cf3-df731c83dbd6",
"NatGateway": {
"CreateTime": "2024-09-17T06:45:43+00:00",
"NatGatewayAddresses": [
{
"AllocationId": "eipalloc-0b582827c154b315d",
"IsPrimary": true,
"Status": "associating"
}
],
"NatGatewayId": "nat-070e891694114824b",
"State": "pending",
"SubnetId": "subnet-090e0fa27cedb8e6a",
"VpcId": "vpc-086c99e11cde64580",
"ConnectivityType": "public"
}
}
Create tag or a descriptive name for your Nat gateway.
aws ec2 create-tags --resources <NatId> --tags Key=Name,Value=<name>
For resources, copy and paste your NatId
For Value, provide a name for Nat gateway
C:\Users\Nsisong>aws ec2 create-tags --resources nat-070e891694114824b --tags Key=Name,Value=CLI-NatGateway
Step 5: Create Route Tables
Create a route table for the public subnet.
To do this, use the command
aws ec2 create-route-table --vpc-id <VpcId>
For vpc-id, copy and paste your VpcId
C:\Users\Nsisong>aws ec2 create-route-table --vpc-id vpc-086c99e11cde64580
{
"RouteTable": {
"Associations": [],
"PropagatingVgws": [],
"RouteTableId": "rtb-06f3188e96a915faa",
"Routes": [
{
"DestinationCidrBlock": "10.0.0.0/16", "GatewayId": "local",
"Origin": "CreateRouteTable",
"State": "active"
}
],
"Tags": [],
"VpcId": "vpc-086c99e11cde64580",
"OwnerId": "101061110965"
},
"ClientToken": "4a292c9d-1b49-404d-80e0-52ed8fb63f4c"
}
Then, create tag or a descriptive name to your Public route table.
aws ec2 create-tags --resources <RouteTableId> --tags Key=Name,Value=<name>
For resources, copy and paste your RouteTableId
For Value, provide a name for your Public route table
C:\Users\Nsisong>aws ec2 create-tags --resources rtb-06f3188e96a915faa --tags Key=Name,Value=CLI-PUBLICROUTE
Now, create a route to allow internet access
To do this, use the command
aws ec2 create-route --route-table-id <RouteTableId> --destination-cidr-block 0.0.0.0/0 --gateway-id <InternetGatewayId>
For RouteTableId, copy and paste your rtb-Id
For InternetGatewayId, copy and paste your igwId
And ensure to configure the destination cidr-block to anywhere
C:\Users\Nsisong>aws ec2 create-route --route-table-id rtb-06f3188e96a915faa --destination-cidr-block 0.0.0.
0/0 --gateway-id igw-0e9b76329f85c97ca
{
"Return": true
}
_Now since you have created a route table, you have also given it an internet access and you have given it a name as Public route table _
Then, associate the route table with the public subnet.
To do this, use the command
aws ec2 associate-route-table --subnet-id <PublicSubnetId> --route-table-id <RouteTableId>
For PublicSubnetId, copy and paste your Public-subnetId there.
For RouteTableId, copy and paste your rtb-id there
C:\Users\Nsisong>aws ec2 associate-route-table --subnet-id subnet-090e0fa27cedb8e6a --route-table-id rtb-06f
3188e96a915faa
{
"AssociationId": "rtbassoc-0c6413a18d81b055c",
"AssociationState": {
"State": "associated"
}
}
Enable auto-assign public IP on the public subnet
To do this, use the command
aws ec2 modify-subnet-attribute --subnet-id <PublicSubnetId> --map-public-ip-on-launch
Where you have PublicSubnetId, copy and paste your Public-subnetId there.
C:\Users\Nsisong>aws ec2 modify-subnet-attribute --subnet-id subnet-090e0fa27cedb8e6a --map-public-ip-on-lau
nch
Create a route table for the private subnet
To do this, use this command
aws ec2 create-route-table --vpc-id <VpcId>
Where you have VpcId, copy and paste your vpc-id
C:\Users\Nsisong>aws ec2 create-route-table --vpc-id vpc-086c99e11cde64580
{
"RouteTable": {
"Associations": [],
"PropagatingVgws": [],
"RouteTableId": "rtb-09a1dc578d89c4d88",
"Routes": [
{
"DestinationCidrBlock": "10.0.0.0/16", "GatewayId": "local",
"Origin": "CreateRouteTable",
"State": "active"
}
],
"Tags": [],
"VpcId": "vpc-086c99e11cde64580",
"OwnerId": "101061110965"
},
"ClientToken": "ae6c4808-d1fd-4417-aee7-912067d74c22"
}
Then, create tag or a descriptive name to your Private route table.
aws ec2 create-tags --resources <RouteTableId> --tags Key=Name,Value=<name>
For resources, copy and paste your RouteTableId
For Value, provide a name for your Public route table
C:\Users\Nsisong>aws ec2 create-tags --resources rtb-09a1dc578d89c4d88 --tags Key=Name,Value=CLI-PRIVATEROUT
E
Create a route in the private route table to use the NAT gateway
To do this, use the command
aws ec2 create-route --route-table-id <PrivateRouteTableId> --destination-cidr-block 0.0.0.0/0 --nat-gateway-id <NatGatewayId>
Where you have PrivateRouteTableId, copy and paste your private-rtb-id
And where you have NatGatewayId, copy and paste your nat-gateway-id.
However, ensure you configure your destination to anywhere.
_Because your private instances might need access to internet for updates.
And that could be archived securely through the Nat gateway.
_
C:\Users\Nsisong>aws ec2 create-route --route-table-id rtb-09a1dc578d89c4d88 --destination-cidr-block 0.0.0.
0/0 --nat-gateway-id nat-070e891694114824b
{
"Return": true
}
Ok! now that you have created a route table, you have also given it a Nat gateway internet access and you have given it a name as Private route table
Then, associate the route table with the Private subnet
To do this, use the command
aws ec2 associate-route-table --subnet-id <PrivateSubnetId> --route-table-id <PrivateRouteTableId>
Where you have PrivateSubnetId, copy and paste your private-Subnet-id there
And where you have PrivateRouteTableId, copy and paste your private-rtb-id there.
C:\Users\Nsisong>aws ec2 associate-route-table --subnet-id subnet-0ab4cd05a41dc4882 --route-table-id rtb-09a
1dc578d89c4d88
{
"AssociationId": "rtbassoc-025956002fd6aef15",
"AssociationState": {
"State": "associated"
}
}
Step 6: create security groups
To do this, use the command
aws ec2 create-security-group --group-name <security-group-name> --description "<description>" --vpc-id <vpc-id>
Where you have security-group-name, provide a name for you security group.
Where you have description, give a description to your security group.
Then, where you have vpc-id, copy and paste your vpc-id there.
C:\Users\Nsisong>aws ec2 create-security-group --group
-name CLI-WEB-securityGroup --description "This is my
security group" --vpc-id vpc-086c99e11cde64580
{
"GroupId": "sg-03b513eb8de674a4e"
}
Then, create tag or a descriptive name to your security group.
aws ec2 create-tags --resources <GroupId> --tags Key=Name,Value=<name>
For resources, copy and paste your GroupId
For Value, provide a name for your Security group.
C:\Users\Nsisong>aws ec2 create-tags --resources sg-03b513eb8de674a4e --tags Key=Name,Value=CLI-security-gro
up
Now, configure the security rules
By default, outbound rules is always open.
However, add an inbound rules that allows both ssh and http access
To do this, use the command
aws ec2 authorize-security-group-ingress --group-id <security-group-id>
--protocol tcp --port 22 --cidr 0.0.0.0/0Where you have security-group-id, copy and paste your GroupId
--protocol tcp: Specifies the TCP protocol.
--port 22: Specifies port 22, which is used for SSH.
--cidr 0.0.0.0/0: Allows SSH access from any IP address.
C:\Users\Nsisong>aws ec2 authorize-security-group-ingr
ess --group-id sg-03b513eb8de674a4e --protocol tcp --p
ort 22 --cidr 0.0.0.0/0
{
"Return": true,
"SecurityGroupRules": [
{
"SecurityGroupRuleId": "sgr-0c91fcd4316408ba4",
"GroupId": "sg-03b513eb8de674a4e",
"GroupOwnerId": "101061110965",
"IsEgress": false,
"IpProtocol": "tcp",
"FromPort": 22,
"ToPort": 22,
"CidrIpv4": "0.0.0.0/0"
}
]
}
aws ec2 authorize-security-group-ingress --group-id <security-group-id>
--protocol tcp --port 80 --cidr 0.0.0.0/0
C:\Users\Nsisong>aws ec2 authorize-security-group-ingress --group-id sg-03b513eb8de674a4e --protocol tcp --port 80 --cidr 0.0.0.0/0
{
"Return": true,
"SecurityGroupRules": [
{
"SecurityGroupRuleId": "sgr-0fb478a9af9831a69",
"GroupId": "sg-03b513eb8de674a4e",
"GroupOwnerId": "101061110965",
"IsEgress": false,
"IpProtocol": "tcp",
"FromPort": 80,
"ToPort": 80,
"CidrIpv4": "0.0.0.0/0"
}
]
}
Step 7: Create key pair for SSH Login
To do this, use the command
aws ec2 create-key-pair --key-name <your_key_name> --query 'KeyMaterial' --output text > your_key_name
Replace your key name, with the name of your keypair.
C:\Users\Nsisong>aws ec2 create-key-pair --key-name MYCLIKEY123 --query "KeyMaterial" --output text > MYCLIKEY123
Step 8: Launch EC2 Instances
Launch an instance in the public subnet
To do this, use the command
aws ec2 run-instances --image-id <AMI-ID> --count 1 --instance-type <InstanceType> --key-name <KeyName> --subnet-id <PublicSubnetId> --security-group-ids <GroupId> --associate-public-ip-address
Where you have AMI-ID, copy and paste you image-id
--count 1: Specifies the number of instances
Where you have InstanceType, replace with t2.micro which free tier.
Where you have KeyName, replace with your key-pair.
Where you have GroupId, copy and paste your sg-id there
And where you have PublicSubnetId, copy and paste your publicSubnetid there.
--associate-public-ip-address: This command enables or gives this instance a Public IP address.
C:\Users\Nsisong>aws ec2 run-instances --image-id ami-0ebfd941bbafe70c6 --count 1 --instance-type t2.micro --key-name MYCLIKEY123 --security-group-ids sg-03b513eb8de674a4e --subnet-id subnet-090e0fa27cedb8e6a --associate-public-ip-address
{
"Groups": [],
"Instances": [
{
"AmiLaunchIndex": 0,
"ImageId": "ami-0ebfd941bbafe70c6",
"InstanceId": "i-0e60743780a84216e",
"InstanceType": "t2.micro",
"KeyName": "MYCLIKEY123",
"LaunchTime": "2024-09-17T08:31:11+00:00",
"Monitoring": {
"State": "disabled"
},
"Placement": {
"AvailabilityZone": "us-east-1f",
"GroupName": "",
"Tenancy": "default"
},
"PrivateDnsName": "ip-10-0-1-102.ec2.internal",
"PrivateIpAddress": "10.0.1.102",
"ProductCodes": [],
"PublicDnsName": "",
"State": {
"Code": 0,
"Name": "pending"
},
"StateTransitionReason": "",
"SubnetId": "subnet-090e0fa27cedb8e6a",
"VpcId": "vpc-086c99e11cde64580",
"Architecture": "x86_64",
"BlockDeviceMappings": [],
"ClientToken": "3dd000e7-5c7a-4a41-b1ed-26ec27d693f2",
"EbsOptimized": false,
"EnaSupport": true,
"Hypervisor": "xen",
"NetworkInterfaces": [
{
"Attachment": {
"AttachTime": "2024-09-17T08:31:11+00:00",
"AttachmentId": "eni-attach-07c3c205d29357b4c",
"DeleteOnTermination": true,
"DeviceIndex": 0,
"Status": "attaching",
"NetworkCardIndex": 0
},
"Description": "",
"Groups": [
{
"GroupName": "CLI-WEB-securityGroup",
"GroupId": "sg-03b513eb8de674a4e"
}
],
"Ipv6Addresses": [],
"MacAddress": "16:ff:c6:9b:03:b7",
"NetworkInterfaceId": "eni-0fd5681bfcdfa9866",
"OwnerId": "101061110965",
"PrivateIpAddress": "10.0.1.102",
"PrivateIpAddresses": [
{
"Primary": true,
"PrivateIpAddress": "10.0.1.102"
}
],
"SourceDestCheck": true,
"Status": "in-use",
"SubnetId": "subnet-090e0fa27cedb8e6a",
"VpcId": "vpc-086c99e11cde64580",
"InterfaceType": "interface"
}
],
"RootDeviceName": "/dev/xvda",
"RootDeviceType": "ebs",
"SecurityGroups": [
{
"GroupName": "CLI-WEB-securityGroup",
"GroupId": "sg-03b513eb8de674a4e"
}
],
"SourceDestCheck": true,
"StateReason": {
"Code": "pending",
"Message": "pending"
},
"VirtualizationType": "hvm",
"CpuOptions": {
"CoreCount": 1,
"ThreadsPerCore": 1
},
"CapacityReservationSpecification": {
"CapacityReservationPreference": "open"
},
"MetadataOptions": {
"State": "pending",
"HttpTokens": "required",
"HttpPutResponseHopLimit": 2,
"HttpEndpoint": "enabled",
"HttpProtocolIpv6": "disabled",
"InstanceMetadataTags": "disabled"
},
"EnclaveOptions": {
"Enabled": false
},
"BootMode": "uefi-preferred",
"PrivateDnsNameOptions": {
"HostnameType": "ip-name",
"EnableResourceNameDnsARecord": false,
"EnableResourceNameDnsAAAARecord": false
},
"MaintenanceOptions": {
"AutoRecovery": "default"
},
"CurrentInstanceBootMode": "legacy-bios"
}
],
"OwnerId": "101061110965",
"ReservationId": "r-0cbfc7bce9bf67f90"
}
- Then, create tag or a descriptive name to your Instance.
aws ec2 create-tags --resources <InstanceId> --tags Key=Name,Value=<name>
For resources, copy and paste your InstanceId there.
For Value, provide a name for your instance there.
C:\Users\Nsisong>aws ec2 create-tags --resources i-0e60743780a84216e --tags Key=Name,Value=CLI-Public-instance
Launch an instance in the private subnet
To do this, use the command
aws ec2 run-instances --image-id <AMI-ID> --count 1 --instance-type <InstanceType> --key-name <KeyName> --subnet-id <PrivateSubnetId>
Where you have AMI-ID, copy and paste you image-id.
--count 1: Specifies the number of instances
Where you have InstanceType, replace with t2.micro which free tier.
Where you have KeyName, replace with your key-pair.
And where you have PrivateSubnetId, copy and paste your PrivateSubnetId there.
C:\Users\Nsisong>aws ec2 run-instances --image-id ami-0ebfd941bbafe70c6 --count 1 --instance-type t2.micro --key-name MYCLIKEY123 --subnet-id subnet-0ab4cd05a41dc4882
{
"Groups": [],
"Instances": [
{
"AmiLaunchIndex": 0,
"ImageId": "ami-0ebfd941bbafe70c6",
"InstanceId": "i-056e1777784aab32a",
"InstanceType": "t2.micro",
"KeyName": "MYCLIKEY123",
"LaunchTime": "2024-09-17T11:45:13+00:00",
"Monitoring": {
"State": "disabled"
},
"Placement": {
"AvailabilityZone": "us-east-1f",
"GroupName": "",
"Tenancy": "default"
},
"PrivateDnsName": "ip-10-0-2-103.ec2.internal",
"PrivateIpAddress": "10.0.2.103",
"ProductCodes": [],
"PublicDnsName": "",
"State": {
"Code": 0,
"Name": "pending"
},
"StateTransitionReason": "",
"SubnetId": "subnet-0ab4cd05a41dc4882",
"VpcId": "vpc-086c99e11cde64580",
"Architecture": "x86_64",
"BlockDeviceMappings": [],
"ClientToken": "b9543fc9-e093-46a2-9d6c-b5391ac90eb5",
"EbsOptimized": false,
"EnaSupport": true,
"Hypervisor": "xen",
"NetworkInterfaces": [
{
"Attachment": {
"AttachTime": "2024-09-17T11:45:13+00:00",
"AttachmentId": "eni-attach-04bc3aededd1158ab",
"DeleteOnTermination": true,
"DeviceIndex": 0,
"Status": "attaching",
"NetworkCardIndex": 0
},
"Description": "",
"Groups": [
{
"GroupName": "default",
"GroupId": "sg-0f951d3f7faa4766f"
}
],
"Ipv6Addresses": [],
"MacAddress": "16:ff:ef:a1:19:87",
"NetworkInterfaceId": "eni-0550fdce65193c750",
"OwnerId": "101061110965",
"PrivateIpAddress": "10.0.2.103",
"PrivateIpAddresses": [
{
"Primary": true,
"PrivateIpAddress": "10.0.2.103"
}
],
"SourceDestCheck": true,
"Status": "in-use",
"SubnetId": "subnet-0ab4cd05a41dc4882",
"VpcId": "vpc-086c99e11cde64580",
"InterfaceType": "interface"
}
],
"RootDeviceName": "/dev/xvda",
"RootDeviceType": "ebs",
"SecurityGroups": [
{
"GroupName": "default",
"GroupId": "sg-0f951d3f7faa4766f"
}
],
"SourceDestCheck": true,
"StateReason": {
"Code": "pending",
"Message": "pending"
},
"VirtualizationType": "hvm",
"CpuOptions": {
"CoreCount": 1,
"ThreadsPerCore": 1
},
"CapacityReservationSpecification": {
"CapacityReservationPreference": "open"
},
"MetadataOptions": {
"State": "pending",
"HttpTokens": "required",
"HttpPutResponseHopLimit": 2,
"HttpEndpoint": "enabled",
"HttpProtocolIpv6": "disabled",
"InstanceMetadataTags": "disabled"
},
"EnclaveOptions": {
"Enabled": false
},
"BootMode": "uefi-preferred",
"PrivateDnsNameOptions": {
"HostnameType": "ip-name",
"EnableResourceNameDnsARecord": false,
"EnableResourceNameDnsAAAARecord": false
},
"MaintenanceOptions": {
"AutoRecovery": "default"
},
"CurrentInstanceBootMode": "legacy-bios"
}
],
"OwnerId": "101061110965",
"ReservationId": "r-072b7ba930ca46057"
}
Then, create tag or a descriptive name to your Instance.
To do this, use the command
aws ec2 create-tags --resources <InstanceId> --tags Key=Name,Value=<name>
For resources, copy and paste your InstanceId there.
For Value, provide a name for your instance there.
C:\Users\Nsisong>aws ec2 create-tags --resources i-056e1777784aab32a --tags Key=Name,Value=CLI-Private-instance
Step 9: SSH into the EC2 instances
C:\Users\Nsisong>ssh ec2-user@3.238.242.252 -i MYCLIKEY123
The authenticity of host '3.238.242.252 (3.238.242.252)' can't be established.
ED25519 key fingerprint is SHA256:KJqDKGF91jAWqRwY/9WdauIFuN1o0tGVy3qwpZZ3/ME.
This key is not known by any other names
Are you sure you want to continue connecting (yes/no/[fingerprint])? yes
Warning: Permanently added '3.238.242.252' (ED25519) to the list of known hosts.
, #_
~\_ ####_ Amazon Linux 2023
~~ \_#####\
~~ \###|
~~ \#/ ___ https://aws.amazon.com/linux/amazon-linux-2023
~~ V~' '->
~~~ /
~~._. _/
_/ _/
_/m/'
[ec2-user@ip-10-0-1-102 ~]$
[ec2-user@ip-10-0-1-102 ~]$
[ec2-user@ip-10-0-1-102 ~]$
[ec2-user@ip-10-0-1-102 ~]$ sudo yum install httpd
Last metadata expiration check: 0:17:56 ago on Tue Sep 17 08:32:05 2024.
Dependencies resolved.
===============================================================================================
Package Architecture Version Repository Size
===============================================================================================
Installing:
httpd x86_64 2.4.62-1.amzn2023 amazonlinux 48 k
Installing dependencies:
apr x86_64 1.7.2-2.amzn2023.0.2 amazonlinux 129 k
apr-util x86_64 1.6.3-1.amzn2023.0.1 amazonlinux 98 k
generic-logos-httpd noarch 18.0.0-12.amzn2023.0.3 amazonlinux 19 k
httpd-core x86_64 2.4.62-1.amzn2023 amazonlinux 1.4 M
httpd-filesystem noarch 2.4.62-1.amzn2023 amazonlinux 14 k
httpd-tools x86_64 2.4.62-1.amzn2023 amazonlinux 81 k
libbrotli x86_64 1.0.9-4.amzn2023.0.2 amazonlinux 315 k
mailcap noarch 2.1.49-3.amzn2023.0.3 amazonlinux 33 k
Installing weak dependencies:
apr-util-openssl x86_64 1.6.3-1.amzn2023.0.1 amazonlinux 17 k
mod_http2 x86_64 2.0.27-1.amzn2023.0.3 amazonlinux 166 k
mod_lua x86_64 2.4.62-1.amzn2023 amazonlinux 61 k
Transaction Summary
===============================================================================================
Install 12 Packages
Total download size: 2.3 M
Installed size: 6.9 M
Is this ok [y/N]: y
Downloading Packages:
(1/12): apr-util-openssl-1.6.3-1.amzn2023.0.1.x86_64.rpm 251 kB/s | 17 kB 00:00
(2/12): apr-util-1.6.3-1.amzn2023.0.1.x86_64.rpm 1.3 MB/s | 98 kB 00:00
(3/12): generic-logos-httpd-18.0.0-12.amzn2023.0.3.noarch.rpm 951 kB/s | 19 kB 00:00
(4/12): httpd-2.4.62-1.amzn2023.x86_64.rpm 2.3 MB/s | 48 kB 00:00
(5/12): apr-1.7.2-2.amzn2023.0.2.x86_64.rpm 1.2 MB/s | 129 kB 00:00
(6/12): httpd-filesystem-2.4.62-1.amzn2023.noarch.rpm 665 kB/s | 14 kB 00:00
(7/12): httpd-core-2.4.62-1.amzn2023.x86_64.rpm 24 MB/s | 1.4 MB 00:00
(8/12): httpd-tools-2.4.62-1.amzn2023.x86_64.rpm 1.7 MB/s | 81 kB 00:00
(9/12): libbrotli-1.0.9-4.amzn2023.0.2.x86_64.rpm 7.4 MB/s | 315 kB 00:00
(10/12): mailcap-2.1.49-3.amzn2023.0.3.noarch.rpm 1.5 MB/s | 33 kB 00:00
(11/12): mod_lua-2.4.62-1.amzn2023.x86_64.rpm 3.0 MB/s | 61 kB 00:00
(12/12): mod_http2-2.0.27-1.amzn2023.0.3.x86_64.rpm 4.7 MB/s | 166 kB 00:00
-----------------------------------------------------------------------------------------------
Total 9.5 MB/s | 2.3 MB 00:00
Running transaction check
Transaction check succeeded.
Running transaction test
Transaction test succeeded.
Running transaction
Preparing : 1/1
Installing : apr-1.7.2-2.amzn2023.0.2.x86_64 1/12
Installing : apr-util-openssl-1.6.3-1.amzn2023.0.1.x86_64 2/12
Installing : apr-util-1.6.3-1.amzn2023.0.1.x86_64 3/12
Installing : mailcap-2.1.49-3.amzn2023.0.3.noarch 4/12
Installing : httpd-tools-2.4.62-1.amzn2023.x86_64 5/12
Installing : libbrotli-1.0.9-4.amzn2023.0.2.x86_64 6/12
Running scriptlet: httpd-filesystem-2.4.62-1.amzn2023.noarch 7/12
Installing : httpd-filesystem-2.4.62-1.amzn2023.noarch 7/12
Installing : httpd-core-2.4.62-1.amzn2023.x86_64 8/12
Installing : mod_http2-2.0.27-1.amzn2023.0.3.x86_64 9/12
Installing : mod_lua-2.4.62-1.amzn2023.x86_64 10/12
Installing : generic-logos-httpd-18.0.0-12.amzn2023.0.3.noarch 11/12
Installing : httpd-2.4.62-1.amzn2023.x86_64 12/12
Running scriptlet: httpd-2.4.62-1.amzn2023.x86_64 12/12
Verifying : apr-1.7.2-2.amzn2023.0.2.x86_64 1/12
Verifying : apr-util-1.6.3-1.amzn2023.0.1.x86_64 2/12
Verifying : apr-util-openssl-1.6.3-1.amzn2023.0.1.x86_64 3/12
Verifying : generic-logos-httpd-18.0.0-12.amzn2023.0.3.noarch 4/12
Verifying : httpd-2.4.62-1.amzn2023.x86_64 5/12
Verifying : httpd-core-2.4.62-1.amzn2023.x86_64 6/12
Verifying : httpd-filesystem-2.4.62-1.amzn2023.noarch 7/12
Verifying : httpd-tools-2.4.62-1.amzn2023.x86_64 8/12
Verifying : libbrotli-1.0.9-4.amzn2023.0.2.x86_64 9/12
Verifying : mailcap-2.1.49-3.amzn2023.0.3.noarch 10/12
Verifying : mod_http2-2.0.27-1.amzn2023.0.3.x86_64 11/12
Verifying : mod_lua-2.4.62-1.amzn2023.x86_64 12/12
Installed:
apr-1.7.2-2.amzn2023.0.2.x86_64
apr-util-1.6.3-1.amzn2023.0.1.x86_64
apr-util-openssl-1.6.3-1.amzn2023.0.1.x86_64
generic-logos-httpd-18.0.0-12.amzn2023.0.3.noarch
httpd-2.4.62-1.amzn2023.x86_64
httpd-core-2.4.62-1.amzn2023.x86_64
httpd-filesystem-2.4.62-1.amzn2023.noarch
httpd-tools-2.4.62-1.amzn2023.x86_64
libbrotli-1.0.9-4.amzn2023.0.2.x86_64
mailcap-2.1.49-3.amzn2023.0.3.noarch
mod_http2-2.0.27-1.amzn2023.0.3.x86_64
mod_lua-2.4.62-1.amzn2023.x86_64
Complete!
[ec2-user@ip-10-0-1-102 ~]$ sudo service httpd start
Redirecting to /bin/systemctl start httpd.service
[ec2-user@ip-10-0-1-102 ~]$ cd /var/www/html/
[ec2-user@ip-10-0-1-102 html]$ echo "<h1> Hello there! this is my first web server that i created, using the CLI.</h1>" > index.html
-bash: index.html: Permission denied
[ec2-user@ip-10-0-1-102 html]$ sudo su
[root@ip-10-0-1-102 html]# echo "<h1>Hello there! this is my first web server that i created using the CLI.</h1>" > index.html
Conclusion
By using the AWS CLI, you have successfully completed the tasks of setting up a fully functional VPC with both public and private subnets, configured internet and NAT gateways, and launched EC2 instances in each. Now, this process showcases the power of managing cloud infrastructure on the terminal and it gives you more control and efficiency even without having to go and touch the AWS Console.
Mastering the CLI can unlock endless possibilities for automating and
scaling your infrastructure, especially as your cloud knowledge grows and I hope this guide helps you take a confident step toward that journey. Keep exploring and keep experimenting even as you keep building with AWS CLI, of course, the cloud is yours to command!
Top comments (2)
Nicely done !
Thank you Uduakabasi