DEV Community

Nonso Echendu
Nonso Echendu

Posted on

Deploying Jenkins on AWS, Installing and Configuring Artifactory and SonarQube on Seperate EC2 Instances

Overview

We would be deploying Jenkins on AWS, integrate it with Artifactory and SonarQube.

We're using SonarQube to generate reports on coding standards, unit tests, code coverage, code complexity, bugs, and security recommendations. And JFrogs's Artifactory for artifacts strorage

A. AWS Console Deployment: Jenkins, Sonarqube and Artifactory

1. Create a VPC

We'll be using a VPC to host and manage securely our instances that will be running Jenkins, Sonarqube and Artifactory.

  • Go to VPC
  • Create VPC
  • Select VPC and more
  • Input a name for your VPC (e.g. TestVPC)
  • IPv4 CIDR: 10.0.0.0/16
  • No IPv6
  • Number of public subnets: 1
  • Number of private subnets: 1
  • Click "Customize Subnets CIDR blocks" "
  • Under Public subnet: 10.0.1.0/24
  • Under Private subnet: 10.0.2.0/24
  • Click "Create VPC"

It should look something like this:

Image description

Selecting VPC and more automatically creates a subnet, Internet gateway and route tables

2. Create NAT Gateway

  • VPC Dashboard → NAT Gateways → Create
  • Select the subnet created while creating the VPC (you should see it with a similar name as your VPC)
  • Connectivity type: public
  • Allocate new EIP
  • Create NAT Gateway

3. Edit Route Table

  • Select route table associated with private subnet
  • Edit routes
  • Add route: > - Destination: 0.0.0.0/0 > - Target: Select your NAT Gateway > - Save changes

It should look something like this:

Image description


Now we move to creating EC2 Instances...

EC2 Instances Setup

1. Jenkins Instance (Public Subnet)

  • EC2 Dashboard → Launch Instance
  • Name: test-jenkins
  • AMI: Ubuntu 22.04 LTS
  • Instance type: t2.micro
  • Key pair: Create/select existing
  • Click "Edit" (under network setting)
  • VPC: TestVPC
  • Subnet: Public subnet created earlier
  • Auto-assign public IP: Enable
  • Click "Create security group"
  • Name: jenkins-sg
  • Inbound rules:
  • SSH (22): Your IP
  • Custom TCP (8080): Your IP or Anywhere (0.0.0.0/0)

It should look something like this:

Image description

2. Artifactory Instance (Private Subnet)

  • EC2 Dashboard → Launch Instance
  • Name: Artifactory
  • AMI: Ubuntu 22.04 LTS
  • Instance type: t2.medium
  • Key pair: Same as that used for Jenkins instance
  • Click "Edit" (under network setting)
  • VPC: TestVPC
  • Subnet: Private subnet created earlier
  • Auto-assign public IP: Disable
  • Click "Create security group"
  • Name: artifactory-sg
  • Inbound rules:
  • SSH (22): jenkins-SG
  • Custom TCP (8081-8082): jenkins-SG

It should look something like this:

Image description

3. Sonarqube Instance (Private Subnet)

  • EC2 Dashboard → Launch Instance
  • Name: Sonarqube
  • AMI: Ubuntu 22.04 LTS
  • Instance type: t2.medium
  • Key pair: Same as that used for Jenkins instance
  • Click "Edit" (under network setting)
  • VPC: TestVPC
  • Subnet: Private subnet created earlier
  • Auto-assign public IP: Disable
  • Click "Create security group"
  • Name: sonarqube-sg
  • Inbound rules:
  • SSH (22): bastion-SG
  • Custom TCP (9000): jenkins-SG

It should look something like this:

Image description


Next, we'll be creating another Instance for Bastion Host.

A bastion host is a server used to manage access to an internal or private network from an external network.

In our case, we'll be using it to ssh into the private subnet for managing Artifactory and Sonarqube.

4. Bastion Host (Public Subnet)

  • EC2 Dashboard → Launch Instance
  • Name: Bastion
  • AMI: Ubuntu 22.04 LTS
  • Instance type: t2.micro
  • Network: Public subnet
  • Security Group:
  • Allow SSH from your IP
  • Allow outbound to Artifactory SG

It should look something like this:

Image description


B. Instalation of Jenkins, Artifactory and Sonarqube

Now we're done setting up and configuring our instances. Next, we'll be installing our tools: Jenkins, Artifactory and Sonarqube

1. Jenkins Installation

To install Jenkins, we'll be using docker. Specifically, we'll be spinning up a jenkins container using a docker-compose.yaml file.

  • SSH to jenkins using
ssh -i <identity-file> ubuntu@<jenkins-public-ip>

Install docker

sudo apt-get update
sudo apt-get install docker.io -y
  • Add docker to usergroup with this command:
sudo usermod -aG docker $USER
  • Logout and login again

  • Test that docker is installed properly:

docker run hello-world

something like this should show:

Image description

  • Next, we install docker compose
DOCKER_CONFIG=${DOCKER_CONFIG:-$HOME/.docker}
mkdir -p $DOCKER_CONFIG/cli-plugins
curl -SL https://github.com/docker/compose/releases/download/v2.32.0/docker-compose-linux-x86_64 -o $DOCKER_CONFIG/cli-plugins/docker-compose
chmod +x $DOCKER_CONFIG/cli-plugins/docker-compose
  • Confirm docker compose is installed
docker compose version

It should bring an output like this:

Image description


  • Create a file with the name docker-compose.yaml.

  • Paste this into the file:

services:
  jenkins:
    image: jenkins/jenkins:lts
    container_name: jenkins
    privileged: true
    user: root 
    ports:
      - "8080:8080"
      - "50000:50000"
    volumes:
      - jenkins_home:/var/jenkins_home
      - /var/run/docker.sock:/var/run/docker.sock
    command: |
      sh -c "
        apt-get update && \
        apt-get install -y sudo && \
        chown -R 1000:1000 /var/jenkins_home && \
        apt-get -y install docker.io && \
        groupadd -f docker && \
        usermod -aG docker jenkins && \
        echo 'jenkins ALL=(ALL) NOPASSWD: ALL' >> /etc/sudoers && \
        chown jenkins:jenkins /var/run/docker.sock && \
        chmod 666 /var/run/docker.sock && \
        su jenkins -c /usr/local/bin/jenkins.sh"
volumes:
  jenkins_home:
  • Run
docker compose up -d

This installs docker and spins up a jenkins container as well. In addition, it installs sudo which is needed to run some commands in our jenkins pipeline.

  • Access Jenkins UI by opening in your browser: http://<jenkins-public-ip>:8080

  • Follow the prompt and Install selected plugins

2. Sonarqube Installation

Like we did for jenkins, we'll also be installing Sonarqube using docker

  • SSH to sonarqube from Bastion
# SSH first to bastion
ssh -i <identity-file> ubuntu@<bastionpublic-ip>
# SSH to Sonarqube
ssh -i <identity-file> ubuntu@<sonarqube-private-ip>
  • Install docker

Go to previous install docker step

  • Create a file with the name docker-compose.yaml.

  • Paste this into the file:

services:
  sonarqube:
    image: sonarqube:lts
    container_name: sonarqube
    ports:
      - "9000:9000"
    volumes:
      - sonarqube_data:/opt/sonarqube/data
      - sonarqube_extensions:/opt/sonarqube/extensions
      - sonarqube_logs:/opt/sonarqube/logs
    restart: always
volumes:
  sonarqube_data:
  sonarqube_extensions:
  sonarqube_logs:
  • Run
docker compose up -d
  • Run docker ps to ensure Sonarqube is running

  • Access Sonarqube UI by opening in your browser:

Because we setup sonarqube in a private subnet, it doesn't have any public ip. And so we'll be accessing the UI using SSH tunnelling or SSH port forwarding from the Bastion host.

  • From your local machine, run this: (We are forwarding traffic from our local machone's port 9000 to Sonarqube's port 9000 in the private subnet, through Bastion.)
# From your local machine, run
ssh -L 9000:<sonarqube-private-ip>:9000 ubuntu@<bastion-public-ip>

On your local machine browser enter http://localhost:8082.

It should open something like this:

Image description

P.s. Because my local machine's port 9000 is already being used, that is why i'm using port 9023.

Default login:

  • username: admin
  • password: admin

3. Artifactory Installation

Like we did for both Jenkins and Sonarqube, we'll be installing Artifactory using docker

  • SSH to Artifactory from Bastion
# From your local machine, SSH first to bastion
ssh -i <identity-file> ubuntu@<bastionpublic-ip>
# SSH to Artifactory
ssh -i <identity-file> ubuntu@<artifactory-private-ip>
  • Install docker

Go to previous install docker step

  • Create a file with the name docker-compose.yaml.

  • Paste this into the file:

services:
  artifactory-service:
    image: docker.bintray.io/jfrog/artifactory-oss:7.49.6
    container_name: artifactory
    restart: always
    networks:
      - ci_net
    ports:
      - 8081:8081
      - 8082:8082
    volumes:
      - artifactory:/var/opt/jfrog/artifactory
volumes:
  artifactory:
networks:
  ci_net:
  • Run
docker compose up -d
  • Run docker ps to ensure Artifactory is running

  • Access Artifactory UI by opening in your browser:

Just like for Sonarqube, we'll be accessing the Artifactory UI using SSH port forwarding from the Bastion host.

  • Run this:
# From your local machine
ssh -L 8082:<artifactory-private-ip>:8082 ubuntu@<bastion-public-ip>
# 8082 is Artifactory's UI port

On your local machine browser enter http://localhost:8082.

It should open something like this:

Image description

Default login:

  • username: admin
  • password: password

Setting up Jenkins

Now we're going to install some plugins needed to configure Artifactory and Sonarqube in our Jenkins pipeline

First we'll be installing he Artifactory plugin

  • Go to Manage Jenkins > Plugins > Available Plugins, and search for artifactory

  • Select and tick the first one, then click install:

Image description

  • Search also for sonarqube. Select and tick the first one, then click install:

Image description

Next, let's configure Artifactory and Sonarqube on our jenkins server

Configure Sonarqube

  • Click Manage jenkins > System Configurations

  • Scroll to Sonarqube servers

  • Click Add Sonarqube

  • Name: Sonarqube (It has to tally with what you set as value for your env variable in your pipeline)

  • Server URL: http://:9000

  • Server authntication token. Let's create one

In your sonarqube ui, go to My account (top right)> Security> Generate token.

  • Type: User token

  • Expiration: no expiration

  • Click Generate

  • Make sure to copy the generated token

  • Add Server authentication token
  • Kind: Secret text

  • Scope: Global

  • Secret: the generated token you copied

  • ID: sonarqube-token (or whichever name of choice)

  • Click Add

  • Select sonarqube token

  • Click Save

It should look like this:

Image description

Configure Artifactory

  • Click Manage jenkins > System Configurations

  • Scroll to JFrog

  • Click Add JFrog Platform Instance

  • Instance ID: artifactory1 (It has to tally with same value of your env variable in your pipeline)

  • JFrog Platform URL: http://:8082

  • Default Deployer Creentials.

  • Username: admin

  • Password: (new password you set when JFrog prompted you to change default password)

  • Click Test Connection

It should show something like this:

Image description

  • Click Save

Configure Maven

  • Click Add maven

  • Name: enter one of your choice

  • Tick Install automatically

  • Version: Select a recent stable one (3.9.9 in this case)

  • Click Save

It should look like this:

Image description

Create Repository in Artifactory

We need to create a local repository in Artifactory where we would upload artifacts to. Here's a step-by-step on how to do it:

  • Click Add Repositories (top right) > Local Repository

Image description

  • Select Maven as package type

Image description

  • Repository key: test001 (same name to be used in Upload artifactory stage when uploading artifact)

  • Click Create Local Repository


And we're all setup!


Now we can go ahead to create a pipeline script, sourcing from a Java application created with springboot.

If you would want to see a sample Jenkins pipeline, i've actually written an article on the steps i took to create the pipeline script. Check here


Final Results:

And so we've created and ran a successful build:

Image description

When we check our Sonarqube, we see a newly created project from our build. We can also see reports, which we can expand on and read indepthly:

Image description

And in the Artifactory ui dashboard, we can see the newly created artifact under test001:

Image description

Conclusion

By integrating Artifactory and SonarQube into Jenkins, it helps streamline your Continuous Integration (CI) and Continuous Delivery (CD) pipeline, improves the quality of your code, and increases productivity.

Key Benefits

- Continuous Delivery: By linking Jenkins, Artifactory, and your deployment pipelines, you can automate the entire process from building to testing, and finally deploying the artifacts. Artifactory stores these artifacts until they are deployed to different environments.

- Integration with docker: Jenkins can build Docker images and push them to Artifactory. Artifactory supports Docker image repositories, so you can manage and store Docker images as part of your CI/CD pipeline.

- Early Detection of Code Issues: By running static analysis in the pipeline, SonarQube can quickly detect problems in the code base before they become bigger issues. This allows developers to fix problems early, saving time and reducing the cost of fixing issues later in the cycle.


Happy Building and Collaborating!


Top comments (0)