Setting up a Jenkins Server on a Digital Ocean Droplet

Keith Weaver
9 min readAug 8, 2019

This story was originally posted a few months back on my personal website. Find out why my website is where I post first now.

In this post, 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 too 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.

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.

Install Jenkins on Droplet

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

ssh root@<your_ip>

Start by updating the server.

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

Install Open JDK.

sudo apt install openjdk-8-jdk -y

Install the Jenkins page.

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

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

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

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

It will return:

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.

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.

I’m going to hit Continue as Admin.

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

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.

apt install maven -y
JAVA_HOME="/usr/lib/jvm/open-jdk"
echo $JAVA_HOME
PATH=$PATH:$HOME/bin:$JAVA_HOME/bin
mvn --versionApache 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:

ssh-keygen
cat ~/.ssh/id_rsa.pubssh-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.

Clone the project to local.

git clone <your_git_url>
cd <your_project_name>

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

In your terminal run:

mvn clean package

You should see:

[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:

.idea/
target/
# Compiled class file
*.class
# Log file
*.log
# BlueJ files
*.ctxt
# Mobile Tools for Java (J2ME)
.mtj.tmp/
# Package Files #
*.jar
*.war
*.nar
*.ear
*.zip
*.tar.gz
*.rar
# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml
hs_err_pid*

And commit:

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.

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.

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

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. Beware 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.

Select Generate New Token.

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

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.

Add a Jenkinsfile to the root of the project.

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:

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

It will trigger a new build.

Jenkins User

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

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.

--

--