Contents
Introduction
Hey there! Welcome to the world of automation where we make tedious tasks disappear with the magic of scripts and infrastructure as code. Today, I’m going to share with you a practical solution for automating the setup of a Jenkins server and a slave node on AWS using Terraform and Bash scripts.
Forget about manual configurations and hours of tinkering. With the scripts I’ve crafted, you’ll breeze through the process of provisioning an AWS EC2 instance and configuring Jenkins, all in a few simple steps.
No lengthy theoretical discussions hereโjust pure, hands-on automation goodness. So, let’s dive straight into the action and see how Terraform and Bash can revolutionize your CI/CD pipeline setup.
The Bash Scripts
We have three bash scripts that will be used in this setup:
- Script to setup up Jenkins
- Script to install Docker
- Script to setup Jenkins slave server
docker-setup.sh
#!/bin/bash
#
# Automate Installation of Docker
# Author: Gabriel Ibenye
# Update the apt package index and install packages to allow apt to use a repository over HTTPS
sudo apt-get update
sudo apt-get install -y apt-transport-https ca-certificates curl software-properties-common
# Add Dockerโs official GPG key
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add -
# Set up the stable repository for your architecture (amd64)
sudo add-apt-repository "deb [arch=amd64] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable"
# Update the apt package index again and install the latest version of Docker Engine and containerd
sudo apt-get update
sudo apt-get install -y docker-ce docker-ce-cli containerd.io
# Verify that Docker Engine is installed correctly
sudo docker --version
# Add your user to the docker group to run Docker commands without sudo
sudo usermod -aG docker ${USER}
echo "User added to the docker group. Logging out and back in to apply changes..."
echo "Docker setup completed."
jenkins-slave-setup.sh
#!/bin/bash
#
# Automate Jenkins Slave Node Setup
# Author: Gabriel Ibenye
#
#######################################
# Print a message in a given color.
# Arguments:
# Color. eg: green, red
#######################################
function print_color() {
NC='\033[0m' # No Color
case $1 in
"green") COLOR='\033[0;32m' ;;
"red") COLOR='\033[0;31m' ;;
"*") COLOR='\033[0m' ;;
esac
echo -e "${COLOR} $2 ${NC}"
}
echo "---------------- JENKINS SLAVE NODE SETUP ------------------"
print_color "green" "Update apt repository. "
sudo apt update
print_color "green" "Installing Java(openjdk-17-jre)"
sudo apt install openjdk-17-jre -y
echo "---------------- SETUP COMPLETE ------------------"
jenkins-setup.sh
#!/bin/bash
#
# Automate Installation of Jenkins
# Author: Gabriel Ibenye
#######################################
# Print a message in a given color.
# Arguments:
# Color. eg: green, red
#######################################
function print_color() {
NC='\033[0m' # No Color
case $1 in
"green") COLOR='\033[0;32m' ;;
"red") COLOR='\033[0;31m' ;;
"*") COLOR='\033[0m' ;;
esac
echo -e "${COLOR} $2 ${NC}"
}
#######################################
# Check the status of a given service. If not active exit script
# Arguments:
# Service Name. eg: firewalld, mariadb
#######################################
function check_service_status() {
service_is_active=$(sudo systemctl is-active $1)
if [ $service_is_active = "active" ]; then
echo "$1 is active and running"
else
echo "$1 is not active/running"
exit 1
fi
}
#######################################
# Check if a given service is enabled to run on boot. If not enabled exit script
# Arguments:
# Service Name. eg: jenkins, mariadb
#######################################
function check_service_enable() {
service_is_enabled=$(sudo systemctl is-enabled $1)
if [ $service_is_enabled = "enabled" ]; then
echo "$1 is enabled"
else
echo "$1 is not enabled"
exit 1
fi
}
#######################################
# Check the status of a firewalld rule. If not configured exit.
# Arguments:
# Port Number. eg: 3306, 80
#######################################
function is_firewalld_rule_configured() {
firewalld_ports=$(sudo firewall-cmd --list-all --zone=public | grep ports)
if [[ $firewalld_ports == *$1* ]]; then
echo "FirewallD has port $1 configured"
else
echo "FirewallD port $1 is not configured"
exit 1
fi
}
echo "---------------- Adding Debian package repository of Jenkins to apt repository ------------------"
print_color "green" "Download jenkins debian package repository. "
sudo wget -O /usr/share/keyrings/jenkins-keyring.asc \
https://pkg.jenkins.io/debian-stable/jenkins.io-2023.key
print_color "green" "Adding jenkins debian package to apt repository. "
echo deb [signed-by=/usr/share/keyrings/jenkins-keyring.asc] \
https://pkg.jenkins.io/debian-stable binary/ | sudo tee \
/etc/apt/sources.list.d/jenkins.list >/dev/null
print_color "green" "Update apt repository. "
sudo apt update
print_color "green" "Installing fontconfig"
sudo apt install fontconfig -y
print_color "green" "Installing Java(openjdk-17-jre)"
sudo apt install openjdk-17-jre -y
print_color "green" "Installing Jenkins"
sudo apt install jenkins -y
print_color "green" "Enable jenkins service to run on boot"
sudo systemctl enable jenkins
print_color "green" "Starting jenkins service"
sudo systemctl start jenkins
# check Jenkins is enable
check_service_enable jenkins
# check Jenkins is running
check_service_status jenkins
print_color "green" "Opening jenkins default port (8080)"
sudo ufw allow 8080
print_color "green" "Opening OpenSSH port"
sudo ufw allow OpenSSH
print_color "green" "Enable Firewall"
yes | sudo ufw enable
echo "---------------- SETUP COMPLETE ------------------"
Terraform IaC Scripts
With the IaC tool terraform, we will be provisioning 2 basic ec2 instances with a security group.
Prerequisite: you should have your ssh private and public keys setup locally. To create these you can run the
ssh-keygen
command. Default location of the keys is~/.ssh/
or in windows osc:/users/<user>/.ssh/
.
main.tf
resource "aws_instance" "primary" {
ami = "ami-0e83be366243f524a"
instance_type = "t2.micro"
#running script
user_data = file("path/to/bash/jenkins-setup.sh")
tags = {
"Name" = "Jenkins Server"
}
key_name = aws_key_pair.web.id
vpc_security_group_ids = [aws_security_group.primary.id]
}
resource "aws_instance" "slave" {
ami = "ami-0e83be366243f524a"
instance_type = "t2.micro"
#running script
user_data = "${file("path/to/bash/jenkins-slave-setup.sh")}${file("path/to/bash/docker-setup.sh")}"
tags = {
"Name" = "Jenkins Slave"
}
key_name = aws_key_pair.web.id
vpc_security_group_ids = [aws_security_group.primary.id]
}
#Enabling ssh access
resource "aws_key_pair" "web" {
public_key = file("~/.ssh/id_rsa.pub")
}
resource "aws_security_group" "primary" {
name = "jenkins_sg"
description = "Allow Jenkins Server Traffic"
# SSH Port
ingress {
from_port = 22
to_port = 22
protocol = "tcp"
cidr_blocks = ["0.0.0.0/0"]
}
ingress {
from_port = 80
to_port = 80
protocol = "tcp"
cidr_blocks = ["0.0.0.0/0"]
}
# Jenkins port
ingress {
from_port = 8080
to_port = 8080
protocol = "tcp"
cidr_blocks = ["0.0.0.0/0"]
}
# Allow all outbound connection over the internet
egress {
protocol = "-1"
from_port = 0
to_port = 0
cidr_blocks = ["0.0.0.0/0"]
}
}
/**
* Creating node on jenkins
* First create a credential to login with username and private key
* Create the private key and public key on the jenkins slave (ssh-keygen)
* Use the private key on the jenkins credential you were creating earlier
* Copy and paste the public key into the authorized_keys file (~/.ssh/authorized_keys) of the slave server
* In the jenkins credentials select Non verifying Verification Strategy
*/
output.tf
output "jenkins_server_ip" {
value = aws_instance.primary.public_ip
}
output "jenkins_slave_ip" {
value = aws_instance.slave.public_ip
}
Conclusion
In a nutshell, automating Jenkins setup on AWS with Terraform and Bash is a game-changer. Say goodbye to manual headaches and hello to streamlined processes. With just a few commands, you’re up and running, saving time and hassle. Keep exploring and tweaking to fit your needs.
Happy automating!
[fluentform id="8"]