Lessons

Setting up a Jenkins server on a Digital Ocean Droplet

In this lesson, we setup a Jenkins CI/CD pipeline on a Digital Ocean droplet. It will trigger on push events to the master branch of a Git repository and build the project. These pipelines are excellent for validating your code changes are properly tested, and changes are instantly deployed after they're verified. When you are trying to build a resilient system you have to ask yourself, how long is recovery if your servers go down? What's the playbook for recovery? Using a tool like Jenkins allows this to potentially be a single click.

Simple use case: Your hosting an API on a Digital Ocean droplet. The version your hosting is 1.0.1. You make a few code changes, team member reviews it, and the code is merged. You can set it up so this code is unit tested, then compiled with Jenkins. Automatically with Jenkins, it deploys a new droplet using Digital Ocean's API or Terraform. This droplet is provisioned and the code is loaded onto it. Once the health check passes, Jenkins begin running integration tests. All integration tests pass, it updates your DNS to point to the new droplet via your domain providers API (Ex. GoDaddy). Once the domain has the new version in the health check. Jenkins runs your end to end tests. At this point assuming everything passed, it takes down the previous version of the droplet and you just got version 1.0.2 to production with confidence. If anything went wrong, Jenkins could fail back to your previous droplet.

Start by signing up for a Digital Ocean account.

Droplet Setup

Open the Digital Ocean console. In the top right corner, you should see Create > Droplets.

Screenshot of Github Workflow Running

Choose an image: 18.04 x64

Choose a plan: Standard

Select your pricing plan.

I'm not going to enable backups. Select your nearest datacenter. Add your ssh keys to sign into the droplet. If you haven't setup ssh keys, you'll be emailed a password.

I'm naming my server myjenkinsserver.

Screenshot of Github Workflow Running

Screenshot of Github Workflow Running

Install Jenkins on Droplet

Retrieve the IP address from Digital Ocean. You will need to SSH into the box:

1 ssh root@<your_ip>

Screenshot of Github Workflow Running

Start by updating the server.

1 2 sudo apt-get update -y && sudo apt-get upgrade -y sudo apt update -y

Install Open JDK.

1 sudo apt install openjdk-8-jdk -y

Install the Jenkins page.

1 2 3 4 5 6 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 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 jenkins -y systemctl status jenkins

Screenshot of Github Workflow Running

Open the IP with the port. For me, it would be 159.203.46.47:8080 in this case.

Screenshot of Github Workflow Running

Before signing off the server, we are going to retrieve the root password. Run:

1 sudo cat /var/lib/jenkins/secrets/initialAdminPassword

It will return:

1 38ad*******************17b***c5

But with no stars. You can just plug this into the web console.

Jenkins Setup

I'm going to select install suggested Packages.

Screenshot of Github Workflow Running

Screenshot of Github Workflow Running

We are prompt with create new user. This is a very good idea. However, we will do it after Jenkins is setup. The only reason, you can do this once via this method and I want to share how to do it multiple times.

Screenshot of Github Workflow Running

I'm going to hit Continue as Admin.

Screenshot of Github Workflow Running

I'm not going to use a domain. I'm just going to use the IP.

Screenshot of Github Workflow Running

Installing Additional Packages

I'm going to demo with a Java/Springboot project and I'm going to use Maven. Since I'm still ssh'ed into the server, I'm going to add these packages.

1 2 3 4 apt install maven -y JAVA_HOME="/usr/lib/jvm/open-jdk" echo $JAVA_HOME PATH=$PATH:$HOME/bin:$JAVA_HOME/bin
1 mvn --version
1 2 3 4 5 6 Apache Maven 3.3.9 (bb52d8502b132ec0a5a3f4c09453c07478323dc5; 2015-11-10T16:41:47+00:00) Maven home: /opt/maven Java version: 1.8.0_212, vendor: Oracle Corporation Java home: /usr/lib/jvm/java-8-openjdk-amd64/jre Default locale: en, platform encoding: UTF-8 OS name: "linux", version: "4.15.0-50-generic", arch: "amd64", family: "unix"

Jenkins Job Setup && Integrating with Github

The last big step is integrating with Github and creating our first Jenkins job. Every time I push to Github, I want the build to auto kick off.

Let's start by grabbing a SSH key. On the box:

1 ssh-keygen

Screenshot of Github Workflow Running

spacer:[height:10]

1 ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDKmFzCarJR9ZAboW2zSTQOf7GLW1sUyBrSV9lVazMDqa+AHKLa6OzNfM0QiYuNb+jlOfeKH0hYknWq03+Xi9kPJXjX505jHCLgHlDdcI/OLzvc5LZoJN1KebdXzeqaEPD4SbJsnTSQ6eE0q3zB0A2A5w01qx5ujaNYyb3T0EcvQ5Onrh92wxsQbBwRiEHqOGnypAaRqM14WyB7EPWZRQcCpdgQj1PAtSmOPsfGpKmliaQ78zaYPa7hAaDEpGtf7iuvaXtbQ8UgkXxvJuNWQ2WQg1xNNa5Rf1aSZ+PXlckyiQVux5BKgFefkf1SmKF8XZOKxg85RcF2ndqmn84/jGHR root@myjenkinsserver

Copy this down for later use.

You'll need to have a project setup with a repository on Github.

Screenshot of Github Workflow Running

Clone the project to local.

1 2 git clone your_git_url> cd your_project_name

I'm now going to create a new project using Intellij.

Screenshot of Github Workflow Running

Screenshot of Github Workflow Running

Screenshot of Github Workflow Running

Screenshot of Github Workflow Running

Screenshot of Github Workflow Running

Screenshot of Github Workflow Running

Screenshot of Github Workflow Running

Screenshot of Github Workflow Running

Screenshot of Github Workflow Running

In your terminal run:

1 mvn clean package

You should see:

1 2 3 4 5 6 [INFO] ------------------------------------------------------------------------ [INFO] BUILD SUCCESS [INFO] ------------------------------------------------------------------------ [INFO] Total time: 4.239 s [INFO] Finished at: 2019-06-13T06:49:42-04:00 [INFO] ------------------------------------------------------------------------

Since the project works, commit it to the remote master branch. We need a starting point. I recommend creating a .gitignore at the root of the project with:

1 2 3 4 5 6 7 8 9 10 11 12 13 14 .idea/ target/ *.class *.log *.ctxt .mtj.tmp/ *.jar *.war *.nar *.ear *.zip *.tar.gz *.rar hs_err_pid*

And commit:

1 2 3 git add --all git commit -m "Starting point" git push

Once you can confirm the code on Github, we will add the Jenkins ssh key.

Screenshot of Github Workflow Running

Screenshot of Github Workflow Running

Screenshot of Github Workflow Running

Screenshot of Github Workflow Running

Screenshot of Github Workflow Running

We have now setup a secure connection between our Droplet and our Github repository. Next, we will setup the hooks for sending a POST request on push. Under settings you will find Hooks. The domain will be your IP for Jenkins instead.

Screenshot of Github Workflow Running

Screenshot of Github Workflow Running

I want to trigger my builds on pushes and new pull requests opened.

Screenshot of Github Workflow Running

Screenshot of Github Workflow Running

Screenshot of Github Workflow Running

Now we are triggering builds on events. We have not tested this but this is how we would set this up. The last integration with Github is getting access from the UI of Jenkins. For this we will need a personal access token. Its like a specific password for your account. Beaware people will be able to access your account, so if this is a share project I would suggest creating a new Github user just for Jenkins. Under settings, go to Developer Settings.

Screenshot of Github Workflow Running

Screenshot of Github Workflow Running

Select Generate New Token.

Screenshot of Github Workflow Running

Screenshot of Github Workflow Running

Screenshot of Github Workflow Running

We have all the prerequisites to begin setting up our Jenkins job. Log into your Jenkins UI. You should see creat job on the home page or on the left. We are going to setup a new pipeline.

Screenshot of Github Workflow Running

Screenshot of Github Workflow Running

Screenshot of Github Workflow Running

Screenshot of Github Workflow Running

Screenshot of Github Workflow Running

Screenshot of Github Workflow Running

As you can see above, we are getting denied with our access. This is where the personal access token comes in. You need to hit Add on the right. Select username and password. The username is the username of the personal access token and the password is the personal access token. If you have the correct access, the warning should go away.

Screenshot of Github Workflow Running

Screenshot of Github Workflow Running

Add a Jenkinsfile to the root of the project.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 pipeline { agent any stages { stage('Checkout') { steps { echo 'Checkout...' checkout scm stash 'sources' } } stage('Build') { steps { echo 'Build...' unstash 'sources' sh 'mvn clean package -DskipTests' stash 'sources' } } } }

Commit it up and your pipeline should run:

1 git add --all && git commit -m "Added Jenkinsfile" && git push

It will trigger a new build.

Screenshot of Github Workflow Running

Screenshot of Github Workflow Running

Jenkins User

The last step is showing how to add users. From the home page, head to Manage Jenkins.

Screenshot of Github Workflow Running

Screenshot of Github Workflow Running

Screenshot of Github Workflow Running

Screenshot of Github Workflow Running

Conclusion

And that is it! You are all setup with a repository on Jenkins for running a CI/CD pipeline on each push or pull request.