# Create Jenkins AMI using Packer and Ansible Playbook.

In this article, you will learn how to create a Jenkins AMI using Hashicorp Packer and Ansible Playbook.

## What is Packer?

Packer is an open-source tool for creating identical machine images for multiple platforms from a single source configuration. Packer is lightweight, runs on every major operating system, and is highly performant, creating machine images for multiple platforms in parallel.

## What is Ansible?

Ansible is an open-source automation tool designed for IT infrastructure provisioning, configuration management, and application deployment. It allows you to automate repetitive tasks, orchestrate complex workflows, and manage infrastructure as code.

At its core, Ansible uses a simple and human-readable language called YAML (Yet Another Markup Language) to define automation tasks and configuration files. These files, called "playbooks," describe the desired state of a system and the steps needed to achieve that state.

## Prerequisites:

* AWS Account
    
* Packer
    

Ansible

Notes:

* I will be using the default VPC in my AWS Account. If you're using a custom VPC configure it accordingly to ensure your network is correct.
    
* Red Hat Enterprise Linux (RHEL) will be used as the source AMI for Packer.
    
* The code for the project can be found on my [Github](https://github.com/TafariBeckford/Jenkins-Ansible.git).
    

## AWS

### Create Security Group

Create the **Jenkins** Security Group with the following inbound rules:

* **Type**: HTTP  
    **Port range**: 8080  
    **Source**: My IP
    
* **Type**: SSH  
    **Port range**: 22  
    **Source**: My IP
    

## Ansible

### Create playbook in a folder named "ansible"  

This playbook sets up the Jenkins repository, installs OpenJDK 11 JRE, and installs Jenkins on the specified hosts using the yum package manager

1. `jenkins-playbook.yaml`
    

```yaml
---
- name: Install Jenkins
  hosts: all
  become: true

  tasks:
    - name: Add Jenkins repository
      yum_repository:
        name: jenkins
        description: Jenkins Repository
        baseurl: https://pkg.jenkins.io/redhat-stable
        gpgcheck: yes
        gpgkey: https://pkg.jenkins.io/redhat-stable/jenkins.io-2023.key
        enabled: yes

    - name: Download Jenkins repository key
      get_url:
        url: https://pkg.jenkins.io/redhat-stable/jenkins.io-2023.key
        dest: /etc/pki/rpm-gpg/jenkins.io-2023.key
      

    - name: Install OpenJDK 11 JRE
      ansible.builtin.yum:
        name: 
         - fontconfig 
         - java-11-openjdk-devel
        state: present
        update_cache: yes

    - name: Install Jenkins
      ansible.builtin.yum:
        name: jenkins
        state: latest
        update_cache: yes
```

## Bash Script

Create a `scripts` directory with the following `jenkins-start.sh` script:

```bash
#!/bin/bash
sudo systemctl enable jenkins
sudo systemctl start jenkins
```

## Packer

### Create packer files in a `packer` directory

1. `variables.pkr.hcl`
    

```ini
variable "ami_name" {
  default = "Jenkins-AMI"
}

variable "source_ami" {
  default = "ami-026ebd4cfe2c043b2"
}

variable "instance_type" {
  default = "t3.medium"
}

variable "region" {
  default = "us-east-1"
}

variable "ssh_username" {
  default = "ec2-user"
}

variable "security_group_id" {
  default = "sg-0022ddab3a95e94fc"
}
```

1. `jenkins.pkr.hcl`
    

```ini
source "amazon-ebs" "jenkins" {
  ami_name          = var.ami_name
  instance_type     = var.instance_type
  region            = var.region
  source_ami        = var.source_ami
  ssh_username      = var.ssh_username
  security_group_id = var.security_group_id

  tags = {
    "Name" = "Jenkins-Ansible"
  }
}

build {

  sources = ["source.amazon-ebs.jenkins"]

  provisioner "ansible" {

    playbook_file = "../playbook/jenkins-playbook.yaml"

  }

  provisioner "file" {
    source = "../scripts/jenkins-start.sh"

    destination = "/tmp/jenkins-start.sh"

  }

  provisioner "shell" {

    inline = [
      "sudo chmod +x /tmp/jenkins-start.sh",
      "sudo mv /tmp/jenkins-start.sh   /var/lib/cloud/scripts/per-instance/",
    ]

  }

  post-processor "manifest" {}

}
```

The file provisioner uploads files to machines built by Packer. The recommended usage of the file provisioner is to use it to upload files, and then use the shell provisioner to move them to the proper place, set permissions, etc.

The script is then made executable followed by placing them in the directories under `/var/lib/cloud/scripts/per-instance`. Scripts within this directory are run when a new instance is first booted.

1. Validate Packer files using the command `packer validate .` with validates both files simultaneously.
    
2. Create AMI using the command `packer build .`
    

The image below shows the ongoing build process:

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1685634553480/18462ef0-75a4-4ffe-b62c-a2e3172dfdc7.png align="center")

## Completion

Upon completion of the build process, your AMI will be stored in your AWS account along with a snapshot.

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1685634726705/10e63dbb-9c05-419b-afec-a7173a0eeb48.png align="center")

Congrats you have created a Jenkins AMI !!!!!!!!

%[https://media.giphy.com/media/v1.Y2lkPTc5MGI3NjExYmY3ZWFhY2Q3MTRlNTExOTUzYTVhOGEwMjk3MWRiNzU2MDc5ODFkNyZlcD12MV9pbnRlcm5hbF9naWZzX2dpZklkJmN0PWc/OqFvTdkCiDtAoDdq6p/giphy.gif]
