HOW TO AUTOMATE JENKINS INSTALLATION ON AWS EC2 USING TERRAFORM
In today’s dynamic software development environment, building and scaling a Jenkins server for continuous integration is critical. However, manually configuring such infrastructure can be time-consuming, error-prone, and inconsistent.
Terraform comes into play. Terraform, an Infrastructure as Code (IaC) tool, allows us to automate the deployment of a Jenkins server on Amazon Web Services (AWS) infrastructure. This approach provides numerous benefits, including rapid deployment, scalability, and repeatability, while eliminating the complexity and inconsistency of resource deployment. This article will walk you through the steps to build a Jenkins server on AWS using Terraform, enabling efficient and consistent CI/CD processes.
Below is a step-by-step guide to automating the provisioning of an EC2 instance and installing a Jenkins server on an EC2 instance using Terraform.
PREREQUISITES
- Terraform
- AWS accounts
- AWS CLI installed and configured.
TASK
- Deploy an EC2 instance in the default VPC.
- Create a security group and assign it to the instance. This allows traffic on port 22 from the IP address and traffic from port 8080.
- Bootstrap the EC2 Instance with the Bash script (user data script that installs and run Jenkins).
- Create an S3 bucket for Jenkins artifacts that are not publicly accessible.
Step 1: Deploying an EC2 Instance on a Default VPC
On your working directory, create a file with a .tf extension. On the terraform script (main.tf), we define the provider block, specify the provider’s name (in our case, AWS) and the region where you want to configure the infrastructure and create the EC2 instance
# main.tf
# you can use any region and ami of your choice.
terraform {
required_providers {
aws = {
source = "hashicorp/aws"
version = "~> 4.31.0"
}
}
}
provider "aws" {
region = "us-east-1"
}
resource "aws_instance" "jenkins_server"{
ami = "ami-08a52ddb321b32a8c"
instance_type = "t2.micro"
associate_public_ip_address = true
key_name = "jenkins-ssh-key"
tags= {
Name = "Jenkins Installation Tutorial"
}
}
## ssh connectivity
resource "aws_key_pair" "jenkins_key" {
key_name = "jenkins-ssh-key"
public_key = file("~/.ssh/id_rsa.pub")
}
Step 2: Creating and Assigning a Security Group
On the main.tf file, define the security group, and assign it to the EC2 instance. This security group will allow incoming traffic on port 22 (SSH) from your IP address and traffic on port 8080 (Jenkins).
# main.tf
terraform {
required_providers {
aws = {
source = "hashicorp/aws"
version = "~> 4.31.0"
}
}
}
provider "aws" {
region = "us-east-1"
}
resource "aws_instance" "jenkins_server"{
ami = "ami-08a52ddb321b32a8c"
instance_type = "t2.micro"
vpc_security_group_ids = [aws_security_group.jenkins_sg.id]
associate_public_ip_address = true
key_name = "jenkins-ssh-key"
user_data = file("./Install_jenkins.sh")
tags= {
Name = "Jenkins Installation Tutorial"
}
}
## ssh connectivity
resource "aws_key_pair" "jenkins_key" {
key_name = "jenkins-ssh-key"
public_key = file("~/.ssh/id_rsa.pub")
}
# Creating a security group named jenkins_sg
resource "aws_security_group" "jenkins_sg" {
# Name, Description and the VPC of the Security Group
name = "jenkins_sg"
description = "Security group for jenkins server"
# Since Jenkins runs on port 8080, we are allowing all traffic from the internet
# to be able to access the EC2 instance on port 8080
ingress {
description = "Allow all traffic through port 8080"
from_port = 8080
to_port = 8080
protocol = "tcp"
cidr_blocks = ["0.0.0.0/0"]
}
# Since we only want to be able to SSH into the Jenkins EC2 instance, we are only
# allowing traffic from our IP on port 22
ingress {
description = "Allow SSH from my computer"
from_port = 22
to_port = 22
protocol = "tcp"
cidr_blocks = ["0.0.0.0/0"]
}
# We want the Jenkins EC2 instance to being able to talk to the internet
egress {
description = "Allow all outbound traffic"
from_port = 0
to_port = 0
protocol = "-1"
cidr_blocks = ["0.0.0.0/0"]
}
}
Step 3: Bootstrap the EC2 Instance with a script that installs the Jenkins server.
Now, let’s bootstrap the EC2 instance by installing and starting Jenkins. You can use a user data script to achieve the installation process. This script will update the instance, install Java, add the Jenkins repository, install Jenkins, and start the Jenkins service.
We create another file in the working directory with a .sh extension (Install_script.sh) and define the path to the file on the terraform script.
#!/bin/bash
# Install_script.sh
# Bash script to bootstrap jenkins installation
sudo yum update -y
sudo wget -O /etc/yum.repos.d/jenkins.repo https://pkg.jenkins.io/redhat-stable/jenkins.repo
sudo rpm --import https://pkg.jenkins.io/redhat-stable/jenkins.io-2023.key
sudo yum upgrade
sudo dnf install java-17-amazon-corretto -y
sudo yum install jenkins -y
sudo systemctl enable jenkins
sudo systemctl start jenkins
sudo systemctl status jenkins
# main.tf
}
resource "aws_instance" "jenkins_server"{
ami = "ami-08a52ddb321b32a8c"
instance_type = "t2.micro"
vpc_security_group_ids = [aws_security_group.jenkins_sg.id]
associate_public_ip_address = true
key_name = "jenkins-ssh-key"
# jenkins installation
user_data = file("./Install_jenkins.sh")
tags= {
Name = "Jenkins Installation Tutorial"
}
}
Step 4: Create an S3 Bucket for Jenkins Artifacts
For Jenkins to store artifacts, create an S3 bucket. Make sure it’s not public.
# main.tf
terraform {
required_providers {
aws = {
source = "hashicorp/aws"
version = "~> 4.31.0"
}
}
}
provider "aws" {
region = "us-east-1"
}
resource "aws_instance" "jenkins_server"{
ami = "ami-08a52ddb321b32a8c"
instance_type = "t2.micro"
vpc_security_group_ids = [aws_security_group.jenkins_sg.id]
associate_public_ip_address = true
key_name = "jenkins-ssh-key"
user_data = file("./Install_jenkins.sh")
tags= {
Name = "Jenkins Installation Tutorial"
}
}
## ssh connectivity
resource "aws_key_pair" "jenkins_key" {
key_name = "jenkins-ssh-key"
public_key = file("~/.ssh/id_rsa.pub")
}
resource "aws_s3_bucket" "jenkins_s3"{
bucket = "jenkinstutorial-1-s3-bucket"
}
# Creating a security group named jenkins_sg
resource "aws_security_group" "jenkins_sg" {
# Name, Description and the VPC of the Security Group
name = "jenkins_sg"
description = "Security group for jenkins server"
# Since Jenkins runs on port 8080, we are allowing all traffic from the internet
# to be able to access the EC2 instance on port 8080
ingress {
description = "Allow all traffic through port 8080"
from_port = 8080
to_port = 8080
protocol = "tcp"
cidr_blocks = ["0.0.0.0/0"]
}
# Since we only want to be able to SSH into the Jenkins EC2 instance, we are only
# allowing traffic from our IP on port 22
ingress {
description = "Allow SSH from my computer"
from_port = 22
to_port = 22
protocol = "tcp"
cidr_blocks = ["0.0.0.0/0"]
}
# We want the Jenkins EC2 instance to being able to talk to the internet
egress {
description = "Allow all outbound traffic"
from_port = 0
to_port = 0
protocol = "-1"
cidr_blocks = ["0.0.0.0/0"]
}
}
output "jenkins_url" {
description = "Jenkins url"
value = "${aws_instance.jenkins_server.public_ip}:8080"
}
Run the terraform command to create the instance.
terraform init
terraform plan
terraform validate
terraform apply -auto-approve
Once Jenkins is up and running, configure AWS global credentials and install AWS s3 publisher plugins. The Jenkins URL is obtained from the terraform outputs in the terminal console.
Connect to the instance using EC2 instance connect or through SSH to get Jenkin’s initial password from the server by running the command below:
sudo cat /var/lib/jenkins/secrets/initialAdminPassword
GitHub repository.
CONCLUSION
Great work! In this tutorial, you’ve gained the knowledge and hands-on experience to effectively utilize Terraform as an infrastructure as a code tool to provision a Jenkins server on an EC2 instance within a default VPC on the AWS platform.