The Simplest Possible EC2 Web Server Setup Using Terraform (On AWS)

Are you looking to create a basic AWS instance web server? Maybe you’re learning AWS, trying to get an understanding on Terraform or actually trying to get a pieceof your infrastructure setup. Whatever your reason for needing a simple AWS web server setup, that’s what we’ll be covering today.

Today we’ll walk through (in detail) how to create the simplest possible EC2 web server on AWS using Terraform. We’ll cover all of the fiddly AWS details like AMI’s and user data scripts.

By the end of this article you’ll know how to create a simple Apache based web server on AWS EC2 written in Terraform. 

Right, let’s get straight into it!

If you’re in a rush and you’re just looking for a snippet to copy, here it is…

But if you’re not in such a rush, and you actually want to understand the code that you’re copy/pasting then read on.

In part one, we’ll go through our configuration, and what we’ve written and why — there’s a surprising amount going on when you dig into it.

In part two, we’ll go through how to execute the snippet and what you should see in AWS when it executes.

Sound good? Let’s get to it…

Part 1: The Terraform Configuration

Before we start flying through the article—depending on what you know already—reading one (or all) of the following articles might help.

Let’s start with the Terraform configuration of our instance…

1.1. The Terraform Instance

Okay so the first thing we’ll look at is the Terraform’ed instance resource. You’ll notice in the above example I’ve removed a lot of code (which mainly was the user_data property). We’ll cover what the user_data property does soon, but for now let’s focus on the EC2 instance block.

What we’ve created here is an aws_instance resource block. This resource block is specific to AWS. You can only execute this resource when you’ve installed the AWS provider (so make sure you have that setup first).

You’ll also see that we’re passing ami-06ce3edf0cff21f07 as the ami property. The AMI property stands for Amazon Machine Image (AMI), which is the underlying base machine that our EC2 is created upon.

For our example I hardcoded the latest AMI, which is fine if you running the example as an experiment. But, hardcoding AMI’s is to be avoided if you want to eventually run this configuration in production. Instead you’ll want to dynamically grab your AMI using the aws_ami resource block.

Ans last up in our configuration is the instance_type, which is set to the cheapest instance that is available on AWS, the t2.micro. Feel free to change the instance size if you want or need greater performance.

That should hopefully cover enough to get you going with the AWS instance resource configuration block, let’s move onto the user_data script that we mentioned earlier…

1.2. The EC2 “User Data” Script

The “user data” script. What is this cryptic looking thing? Let’s take a look…

Firstly, our underlying EC2 image itself doesn’t have apache (our web server of choice) installed on it. So we’ll need to add that ourselves. But rather than do it manually, we want our instance to automatically start itself once it’s deployed, and that’s done by usage of the “user data” script. In our script we install Apache, create a basic web page and then start apache.

The sharp-eyed amongst you will have noticed we removed the <<-EOF and EOF characters that were present in the original snippet. These characters simply allow us to put multiline strings into terraform configurations, in our case, that’s our putting our bash script into user data.

Let’s start dissecting our script, starting from the top. At the top of our script is the line #!/bin/bash. This odd looking character collection is a shebang. This tells our interpreter that we want to execute our script using bash.

Next up we are “elevating our permissions” to the root user with sudo su (su stands for switch user) so we can perform our apache installation. Now, with the right permissions we can install httpd (using yum, the package manager which is installed on the AWS AMI).

Now we have apache installed, but no website files to serve, so let’s fix that. We create our website as a small HTML string, and outputting it to the /var/www directory—which is the default location for files on an apache web server.

Now we’ve got everything setup, the last thing we’ll need to do is start our web server. We start our server using the global binary systemctl which we installed with yum in the last step.

1.3. The Terraform Output Block

Below our resource configuration we have a Terraform output. Outputs are easy ways to expose values that can be consumed in other configurations, or in our case just make an easy way to see a simple output when we run our terraform apply command.

In the output block we are giving a name to our output (like you would name a variable). In our case our name is DNS and we’re pointing our variable to a returned values of our instance, in our case the public DNS entry.

Every resource in Terraform documents the values that they “output”—here’s the output values of an EC2 instance in Terraform. But in our case the output block is optional, so feel free to omit it if you don’t feel you need it.

Part 2: Creating Your Instance

Okay hopefully by now you should have a good handle on the what and why of our setup. Now let’s move onto the practicalities of executing it, and what you should see in AWS when you’ve executed your configuration.

Before we do jump into the details of the setup there are few things you’ll need to have installed and setup.

Once you’ve got those setup, you’ll be good to go.

2.1 Plan Terraform

Plan your terraform configuration by copying in the EC2 resource from above, and execute a terraform plan.

You might notice that Terraform creates a lot of values here that we explicitly define. That’s because the instance resource also creates a lot of other resources implicitly. Because we didn’t define things like subnets, security groups and mounted volumes AWS takes a best guess at what we want to set these values to, using things like default resources.

Terraform Plan Instance

Terraform Plan Instance

2.2 Apply Terraform

When you’ve checked that your terraform plan didn’t output anything unexpected, go ahead and execute a terraform apply to launch your instance. Note the URL at the bottom, which is thanks to our output block.

Terraform Apply Instance

Terraform Apply Instance

2.3 View Your Website!

Lastly, you can just grab that outputted URL and go to your browser to see if it has worked as expected. And there you have it, a super simple web server, launched on EC2 in AWS with Apache.

Basic Web Server Output

Basic Web Server Output

Destroy What You Made (Optional)

Before you go, I should also remind you that if you don’t want an unexpected AWS bill, you should also destroy your infrastructure. The small instances cost about $10 dollars per month, but that’s money you can put elsewhere!

To destroy your instance you can execute terraform destroy, which will tear down the stack you just created.

Your Simple EC2 Instance!

And that concludes our walk through of how to create a super simple EC2 instance on AWS with Apache. This setup can be used to create a basic website, or in my case you can use it for experimenting with different AWS features, such as exploring how load balancing works, or DNS failover.

I hope this article helped point you in the right direction with the different nuances of the setup, sometimes it can be quite overwhelming with the amount of prior knowledge that you need to do something as simple as launching an EC2. Stick with your learning though, it does eventually get clearer the more you experiment.

Speak soon Cloud Native friends!

What are you intending to build on your EC2?

Lou Bichard