Introduction to Terraform
Use Case
Your team would like to start using Jenkins as their CI/CD tool to create pipelines for DevOps projects. They need you to create the Jenkins server using Terraform so that it can be used in other environments and so that changes to the environment are better tracked. In this use case, we will have all our code in a single main.tf file (known as a monolith) with hardcoded data.
Definitions
What is Terraform? Terraform is an infrastructure as code tool that lets users define both resources in human-readable configuration files that users can version, reuse, and share. The main benefits of this functionality is: consistency, repeatability, time-savings, and increase efficiency.
What is Jenkins? “Jenkins is a self-contained, open source automation server which can be used to automate all sorts of tasks related to building, testing, and delivering or deploying software.”
Prerequisites
- AWS Free Tier Account
- Basic AWS Knowledge (EC2, Security Groups, S3 etc.)
- Basic Terraform knowledge
- AWS Cloud9 Environment (or another Integrated development environment)
Prep Work
As a beginner to Terraform, I found it easier to figure out what I needed to do by running through the use case in a platform I was already familiar with…AWS Console. By running through this in the AWS Console first, it helped me figure out what I need to build out in the main.tf file for Terraform.
- Deploy 1 EC2 Instance in the Default VPC. Bootstrap the EC2 instance with a script that will install and start Jenkins. Ensure to set up the instance with the following criteria:
- I am using the Ubuntu AMI. If you use Linux, you’ll need to revise the commands indicated below.
- Create a new security group. We will want to revise the inbound rules later.
- Under Advanced Details > User Data, input the below code
#!/bin/bash
#Download Java 8. Jenkins requires Java 8 or later.
sudo apt install -y default-jre
#Download Jenkins GPG key
sudo wget -q -O - https://pkg.jenkins.io/debian/jenkins.io.key | sudo apt-key add -
#Add Jenkins repository to APT sources list
sudo sh -c 'echo deb http://pkg.jenkins.io/debian-stable binary/ > /etc/apt/sources.list.d/jenkins.list'
#Update package list
sudo apt update -y
#Install Jenkins
sudo apt install -y jenkins
#Start Jenkins service
sudo systemctl start jenkins
# Enable Jenkins service to start on boot
sudo systemctl enable jenkins 2. Update the new Security Group so that it allows traffic on port 22 from “your IP” and allows traffic from port 8080.
3. Create a S3 bucket for the Jenkins Artifacts that is not open to the public.
Building the EC2 Instance
After walking through how to do this in the AWS Console, we can better understand what we need to actually input into our resource block. We will need to refer to the Terraform registry to help us determine the coding that we will need to use for creating the desired EC2 instance. The link I referenced is listed below. We will want to navigate to our IDE to begin our configuration build.
# Create an EC2 instance
resource "aws_instance" "jenkins_instance" {
ami = "ami-0c7217cdde317cfec" # Specify the desired AMI ID
instance_type = "t2.micro" # Specify the desired instance type
key_name = "[INSERT KEY PAIR NAME]" # Specify the key pair name for SSH access
vpc_security_group_ids = [aws_security_group.jenkins_sg.id]
tags = {
Name = "Jenkins"
}
user_data = <<-EOF
#!/bin/bash
sudo apt update -y
sudo apt install -y default-jre
wget -q -O - https://pkg.jenkins.io/debian/jenkins.io.key | sudo apt-key add -
sudo sh -c 'echo deb http://pkg.jenkins.io/debian-stable binary/ > /etc/apt/sources.list.d/jenkins.list'
sudo apt update -y
sudo apt install -y jenkins
sudo systemctl enable jenkins
sudo systemctl start jenkins
EOF
}You can also create a separate file to house your user data aka script to install Jenkins.
Creating and Updating the Security Group
We will need to refer to the Terraform registry to help us determine the coding that we will need to use for creating the desired security group. The link I referenced is listed below.
# Create a security group for Jenkins
resource "aws_security_group" "jenkins_sg" {
name = "jenkins_sg"
description = "Jenkins Security group"
# Allow SSH access for administration (replace with your IP address)
ingress {
from_port = 22
to_port = 22
protocol = "tcp"
cidr_blocks = ["50.4.49.47/32"] # Replace with your IP address
}
# Allow HTTP access to Jenkins web interface on port 8080
ingress {
from_port = 8080
to_port = 8080
protocol = "tcp"
cidr_blocks = ["0.0.0.0/0"] # Allow access from any IP
}
# Allow HTTPS access to Jenkins web interface on ports 443 and 433
ingress {
from_port = 443
to_port = 443
protocol = "tcp"
cidr_blocks = ["0.0.0.0/0"] # Allow access from any IP
}
# Allow all outbound traffic from the Jenkins instance
egress {
from_port = 0
to_port = 0
protocol = "-1" # Allow all protocols
cidr_blocks = ["0.0.0.0/0"]
}
}Creating the S3 Bucket
We will need to refer to the Terraform registry to help us determine the coding that we will need to use for creating the desired S3 bucket. The link I referenced is listed below.
# Create an S3 bucket for Jenkins artifacts
resource "aws_s3_bucket" "jenkins_bucket" {
bucket = "INPUT UNIQUE BUCKET NAME"
acl = "private"
}Note: When I ran the “terraform validate”, the system advised that this block was deprecated, which means outdated. It suggested using “ aws_s3_bucket_acl resource” instead. I had to lean on some Google articles to get me through this roadblock. Eventually, I was able to find what I needed to resolve the errors being presented.
Get Madison Hersom’s stories in your inbox
Join Medium for free to get updates from this writer.
Another thing to note, ensure your bucket name is very specific, otherwise you’ll run into issues getting it created. It has to be unique.
# Create an S3 bucket for Jenkins artifacts
resource "aws_s3_bucket" "jenkins_bucket" {
bucket = "jenkins-bucket-mh-141414"
}
# Add ownership controls for the Jenkins S3 bucket
resource "aws_s3_bucket_ownership_controls" "jenkins_ownership_controls" {
bucket = aws_s3_bucket.jenkins_bucket.id
rule {
object_ownership = "BucketOwnerPreferred"
}
}
resource "aws_s3_bucket_acl" "jenkins-acl" {
bucket = aws_s3_bucket.jenkins_bucket.id
acl = "private" # Set ACL to private to restrict public access
depends_on = [aws_s3_bucket_ownership_controls.jenkins_ownership_controls]
}Building the main.tf file in Cloud9
In the Cloud9 environment, we will need to put all of these code blocks together in a main.tf file. Navigate to “File” and select “New File”. We will want to save the file and name it “main.tf”. The .tf indicator will ensure that the system recognizes it as a Terraform file.
We will need to start the file with the below code block. This block will tell Terraform that we are using AWS and not another cloud platform. It also will tell the system which region to create the resources in.
terraform {
required_providers {
aws = {
source = "hashicorp/aws"
version = "~> 4.0"
}
}
}Now copy and paste all of the resource block information for the EC2, security groups, and bucket into the main.tf file.
Now I want to run a few commands to initialize and “spell check” what I’ve created thus far. These commands will check the syntax and validity of what is built.
# Initialize Terraform working directory, downloading any necessary plugins
terraform init
#Format your Terraform configuration files
terraform fmt
#Check the syntax and validity of your Terraform configuration
terraform validateWhen you run the “terraform validate” command, ensure you’re reading the output and make any revisions as instructed. Repeat this process until you get a success message.
Applying the main.tf File
Next, we will want to execute commands that will build the resources. When you run “terraform plan”, the output will show you what will be built. This will not actually build out the resources. We need to run the “terraform apply” command to actually build out the resources. If you do not use the “auto-approve” version, you will need to manually input “yes” before the build will complete.
# Generate and show an execution plan without making any changes
terraform plan
# Apply the changes described in the Terraform execution plan
terraform apply
# Apply with auto-approval
terraform apply --auto-approveIt will take a few moments for the resources to be built. As the system is processing, you can navigate to the AWS Console and watch as your resources are getting built out.
Testing
You can check the service status, by connecting to your instance and running the below command. The output will confirm if Jenkins is active.
# Check Jenkins service status
sudo systemctl status jenkinsVerify that you can reach your Jenkins install via port 8080 in your browser. To complete this, copy the Jenkins instance public IP address and paste into the browser. You will want to follow this formatting: “IP_ADDRESS:8080”.
You should be presented this screen:
Cleanup
You can tear down everything you built in the main.tf file with one simple command. This will shut everything down for us that was set up with the main.tf file.
# Destroy the infrastructure defined in the Terraform configuration
terraform destroyConclusion
In this article, we walked through how to utilize the Terraform registry to build out a main.tf file to build resources such as: EC2 instance, security group, and S3 buckets.
Helpful Resources
- https://www.jenkins.io/doc/book/installing/linux/
- https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/instance
- https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/security_group
- https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/s3_bucket
- https://github.com/mhersom/terraform-luit/blob/main/Week21_main.tf





