Using the AWS CLI to launch an Amazon EC2 instance with an Apache web server

Aalok Trivedi
11 min readDec 16, 2022

--

Intro

In my last article, I demonstrated how to install an Apache web server on an AWS EC2 instance, mainly through the AWS Management Console. Now, I will demonstrate how to perform the same task through the AWS Command Line Interface (CLI). If you haven’t already, please skim over my last article, so you’ll have a greater understanding of the terminology and principles I’ll be discussing.

Scenario

We’ll use the same scenario as last time: You are a dev ops cloud engineer for Brainiac, a new tech startup. Instead of dealing with expensive and time-consuming on-premises server maintenance, your bosses want to start making the switch to AWS cloud services. For starters, they want to begin hosting the company website on an AWS server.

Instead of using the AWS Management Console, We’re going to do all of this programmatically, through the AWS Command Line Interface (CLI).

Steps we’ll take

  1. Install and configure the AWS CLI.
  2. Create our EC2 environment by creating a VPC, Key pair, and Security Group.
  3. Write a bash script that will update all packages and install an Apache web server on our EC2 instance.
  4. Launch the EC2 instance that will run our apache-install script.

Prerequisites:

  • An AWS account with an IAM user and an access key/secret access key.
  • Basic knowledge of the Linux OS and commands.
  • Basic knowledge of bash scripting.
  • Basic knowledge of an Amazon EC2 instance.
  • Access to a command line terminal or shell.

🟢 🟢 🟢 Let’s get started! 🟢 🟢 🟢

Step 1: Install & configure the AWS CLI

What is the AWS CLI?

The AWS Command Line Interface (AWS CLI) is a unified tool to manage your AWS services. With just one tool to download and configure, you can control multiple AWS services from the command line and automate them through scripts. You can read more about the AWS CLI, here.

Installing the AWS CLI

I will be installing the CLI for macOS via the package installer. Visit the official AWS CLI page for directions on how to install the package on the OS of your choice.

Just like any other software install, open the macOS pkg installer that was downloaded and go through the guided steps.

After the installation has been completed, let’s confirm the CLI has been installed properly by opening the terminal and running the command

$ which aws

Great! We’ve verified that the shell can find aws. Now let’s run a version check.

$ aws --version

Looking Good!

If you ever need more references or help troubleshooting, refer to the official AWS CLI documentation. It is very thorough and will walk you through getting started for any scenario.

Configuring the AWS CLI

Now that we’ve installed the CLI, we have to configure basic settings and credentials to properly access resources and interact with AWS.

What we need to configure:

  • AWS Access Key ID
  • AWS Secret Key
  • Default region
  • Default output format

Remember the access key pair we generated when we created our IAM account? Find that .csv file (I save all my key pairs in a folder so I can easily access them). You can open the file in a program like Excel to see the keys. If you don’t have an access key pair or lost it, you’ll have to create a new one through the IAM console.

Now run the command, ‘aws configure,’ and enter these settings:

$ aws configure

AWS Access Key ID [None]: [YOUR_ACCESS_KEY]
AWS Secret Access Key [None]: [YOUR_SECRET_ACCESS_KEY]
Default region name [None]: us-east-1
Default output format [None]: json

Great! We've taken the first steps in using the CLI to run our AWS tasks.

Step 2: Create the EC2 Environment

If you remember from the AWS Management Console, to create an EC2 instance, we need to configure or create each of the following:

  1. Amazon Machine Image (AMI): The operating system the instance will run on.
  2. Virtual Private Cloud (VPC) & Subnet: A private cloud network where the instance will live.
  3. EC2 key pair. The key pair that allows us to SSH into ur server.
  4. Security group: Inbound/outbound traffic and firewall rules for the network.

Note: For many of these configurations, we’ll need each their IDs handy. It’s a good idea to open up a notepad or text file to copy & paste the IDs for easy access. I will just use VS Code for this.

I will also start by navigating into the folder where I keep my keys to make life a little easier when I need to access them.

$ cd /Users/aaloktrivedi/AWS/Keys 

1. Get the AMI ID

We’ll be using an Amazon Linux 2 AMI. To get the ID, we’ll need to go to the EC2 console and navigate to the ‘AMI Catalog’ page, under ‘Images.’

Under the ‘Quick Start’ tab, we’ll see the first option is an Amazon Linux 2 AMI with the ID located underneath the title. Let’s copy that into our working text file for easy access.

2. Get the VPC ID & subnet

Our AWS account should already have a default VPC and subnet. We will be using this default VPC to launch our EC2 instance. We’ll need the VPC and subnet ID.

First, let’s list all the available VPCs.

$ aws ec2 describe-vpcs

As you can see, this command echos back JSON information about each VPC. In this case, we only have one. Copy the ‘VpcId’ and paste it to your working text file for easy access.

Now let’s get the subnet ID.

$ aws ec2 describe-subnets

Remember, this subnet is already attached to our VPC. Copy the ‘SubnetId’ to your file for easy access.

3. Create an EC2 Key pair

Now we need to create an EC2 key pair so we can SSH into the instance. This will download a .pem file to your current directory, so make sure we're in a directory where we want to store all our keys (I’m in my ‘Keys’ folder).

Give your key pair a unique ‘key-name.’ I named mine ‘brainiac-ec2-key-2.

We’ll also have to change the permissions for the file so only the owner can read it.

$ aws ec2 create-key-pair --key-name [your-key-name] --query 'KeyMaterial' --output text > [your-key-name].pem
$ chmod 400 [your-key-name].pem

Great! To verify it worked, let’s check our folder to see if the .pem file was properly created.

Woo! There it is!

4. Create a Security Group

A security group sets rules and firewalls to control inbound (ingress) and outbound (egress) traffic to-and-from our network and server. AWS does come with a default security group, but we’re going to create our own to allow SSH from our IP address and inbound HTTP traffic.

Give your security group a name (I named my ‘brainiac-server-sg’), a description, and the vpc-id this security group will be attached to.

$ aws ec2 create-security-group --group-name [your-sg-name] --description "your sg description" --vpc-id [your-vpc-id]

The CLI will then return the ‘Group-id.’ Copy this id and paste it to your working text file for easy access.

If we go back into the EC2 console and go to our Security Groups. We can verify that our group has indeed been created.

However, the group doesn't have any rules yet! So let’s create our SSH and HTTP rules for this security group.

For SSH, we need to allow traffic to ‘port 22,’ but only from our IP address. To find our IP address, we can run this curl command:

$ curl https://checkip.amazonaws.com

Copy the address, and then create an SSH rule (remember to add the /32 at the end of your IP address):

$ aws ec2 authorize-security-group-ingress --group-id [your-group-id] --protocol tcp --port 22 --cidr [your-ip-address/32]

For HTTP, we need to allow traffic to ‘port 80’ and from anywhere (0.0.0.0/0).

$ aws ec2 authorize-security-group-ingress --group-id [your-group-id] --protocol tcp --port 80 --cidr 0.0.0.0/0

Fantastic! Let’s verify the rules by listing the security groups.

$ aws ec2 describe-security-groups
Great! We can see the SHH and HTTP rules have been added.

Step 3: Create a bash script that installs and runs an Apache web server

In the last article, we created a bash script that installs and runs an Apache web server. I won’t go through this again in great detail, but if you want a little reviewer on the script, check out the previous article. Here is the script:

#!/bin/bash

#update all
sudo yum update -y

#install apache
sudo yum install -y httpd

#enable and start apache
sudo systemctl enable httpd
sudo systemctl start httpd

#navigate to the html folder that apache creates on install
cd /var/www/html

sudo mkdir Css
sudo mkdir Scripts

#create index.html file and change file permissions
touch index.html
sudo chmod 775 index.html

sudo echo '<!DOCTYPE html>

<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />

<title>A Basic HTML5 Template</title>

<link rel="preconnect" href="https://fonts.googleapis.com" />
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
<link
href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;700;800&display=swap"
rel="stylesheet"
/>

<link rel="stylesheet" href="css/styles.css?v=1.0" />
</head>

<body>
<div class="wrapper">
<div class="container">
<h1>Welcome! An Apache web server has been started successfully.</h1>
<p>Replace this with your own index.html file in /var/www/html.</p>
</div>
</div>
<!-- your content here... -->
</body>
</html>

<style>
body {
background-color: #34333d;
display: flex;
align-items: center;
justify-content: center;
font-family: Inter;
padding-top: 128px;
}

.container {
box-sizing: border-box;
width: 741px;
height: 449px;
display: flex;
flex-direction: column;
justify-content: center;
align-items: flex-start;
padding: 48px 48px 48px 48px;
box-shadow: 0px 1px 32px 11px rgba(38, 37, 44, 0.49);
background-color: #5d5b6b;
overflow: hidden;
align-content: flex-start;
flex-wrap: nowrap;
gap: 24;
border-radius: 24px;
}

.container h1 {
flex-shrink: 0;
width: 100%;
height: auto; /* 144px */
position: relative;
color: #ffffff;
line-height: 1.2;
font-size: 40px;
}
.container p {
position: relative;
color: #ffffff;
line-height: 1.2;
font-size: 18px;
}
</style>
' > index.html

Your HTML code doesn’t have to be nearly this fancy, but the designer in me couldn’t help it. A simple ‘<html><body><h1> Welcome! </h1></body></html>’ will do.

Save this file as a .sh file. I created a ‘Scripts’ folder, just to keep organized. We’ll need this file when we launch our EC2 instance.

Step 4: Launch the EC2 instance

Almost there! We’ve successfully configured the VPC, key pair, and security group, so now it’s time to launch our EC2 instance!

We’ve set everything up and have all the parameters to run the launch command, so let’s put everything together.

  1. ––image-id: The Amazon Machine Image ID
  2. ––instance-type: We’ll be using a t2.micro since it’s on the free tier.
  3. ––key-name: The EC2 key pair name
  4. ––security-group-ids: The security group ID
  5. ––subnet-ids: The subnet ID
  6. ––user-data: Where we’ll point to our apache-install script file

Get user data

When creating an instance from the Management Console, we placed our Apache bash script in the ‘User data’ field. In the CLI, we can use the
––user-data’ parameter and point to the script file when we run our EC2 launch command.

Launch time!

Alright! Now that we have all the pieces in order, we’re ready to finally launch our EC2 instance. Place your IDs in the appropriate spots and run the command.

$ aws ec2 run-instances --image-id ami-0b0dcb5067f052a63 --count 1 --instance-type t2.micro --key-name [your-keypair-name] --security-group-ids [your-sg-id] --subnet-id [your-subnet-id] --user-data file://../Scripts/apache-install.sh

Hooray! We’ve launched our first EC2 instance entirely from the AWS CLI! But before we pat ourselves on the back, let’s check if the Apache script executed correctly by going to the public IPv4 address.

Yes, we can go to the EC2 console to get the public IP, but that’s no fun!

There are several methods to get the public IPv4, but one way is to ‘query’ the JSON output of the instance.

$ aws ec2 describe-instances --query "Reservations [*]. Instances [*].{PublicIP:PublicIpAddress}" --output text

Copy the address and paste it into your browser.

Success!

Congrats! We’ve successfully created an Apache web server on an Amazon EC2 Instance solely from the AWS CLI. We’re well on our way to becoming full-fledged cloud engineers.

Note: Since this is a demo, we don’t want to keep this instance constantly running. To stop or terminate an instance through the CLI we can run these commands:

$ aws ec2 stop-instances --instance-ids [your-instance-id]
$ aws ec2 terminate-instances --instance-ids [your-instance-id]

😱 😱 BONUS 😱 😱

Turning our instance into its own AMI for fast deployment

Now… I know you’re probably wondering, “Hmm, that was still a lot of work. How is this more efficient?”

… And you’d be right. But in this bonus section, I’ll show you how to turn this web server instance into its own image! This allows us to easily launch an instance with the same parameters without doing all the legwork again.

Steps we’ll take

  1. Create an AMI from the instance we just created.
  2. Launch a NEW EC2 instance with the new AMI.

Let’s go!

Step 1: Create a new AMI

We’ll need the instance ID, so let’s run the ‘describe’ command and copy the ‘InstanceId.’

$ aws ec2 describe-instances

Now we can create a new AMI image based on this instance.

$ aws ec2 create-image --instance-id [instance-id] --name "ami-name" --description "am1 description"

We can quickly verify that our new image has been created by navigating to the AMIs page.

Boom! Image created.

Step 2: Launch a new EC2 Instance

Now it’s time to launch a new instance with the new image. Copy the ‘ImageId’ and run the ‘run-instances’ command (we’ll use the same key name, security group, and subnet as before).

$ aws ec2 run-instances --image-id [your-image-id] --count 1 --instance-type t2.micro --key-name [your-keypair-name] --security-group-ids [your-sg-id] --subnet-id [your-subnet-id]

If we go to the console, we’ll see the new instance. Let’s go to its public IPv4 address and confirm the web server ran correctly.

Woo! Now every time we need a web server, we can just use this custom image! That’s where the magic is. Yes, there was a lot of legwork in the beginning, but now we can leverage that groundwork for more efficiency.

Thank you!

Thank you for following me on my cloud computing journey. I hope this article was helpful and informative. Please give me a follow as I continue my journey, and I will share more articles like this!

--

--