Michael Blum

Developer from Chicago

Deploying Jenkins to AWS


Configure EC2

I opted for an t2.small Ubuntu 14.04 EC2 instance. This gives us two gigs of RAM and a single core for about .02 cents an hour. This should serve our purposes for a personal CI server.

Elastic IP Address

I elected to not assign a public IP address / Amazon DNS as this will change everytime the server reboots. Instead I allocated an Elastic IP address (under Network & Security). This allows Rotue 53 to properly route to the EC2 instance even after a reboot or completely different instance.

Securing a Linux box

Codelitt’s excellent article on securing a Linux server proves useful here: My First Ten Minutes on a Server

Jenkins User

For the purposes of this deployment I created a jenkins user but you can create whatever user you’d like, so long as it as SSH and SUDOer powers.

Security Groups

One point where I differed from the above guide was that rather than having ufw handle the firewall, I opted for AWS security groups instead. This way I can monitor my open ports directly from EC2, rather than logging into individual machines. We also need to give Github access so Webhooks work:

Github Whitelist IPs

Github Security Group

github security group for ports 22, 443, and 9418

Jenkins Security Group

AWS security group for ports 22, 443, and 8080

VPN and Security Groups

You’ll note the IP address for the source is not 0.0.0.0/0 (which allows anyone to access those ports). I created a personal VPN to give me a secure and static IP address (sorry, not the actual VPN server address 😉). This is important since my ISP only hands out dynamic IP addresses and I don’t want the whole world gunning for my server.

DigitalOcean wrote a great guide on getting one setup: How to setup a VPN server

An interesting side note about VPN, the IP address of the VPN server itself is the one AWS sees.

Now that we’ve deployed and secured our webserver, lets install Jenkins.

Installing Jenkins

1. Install Oracle Java 8

sudo add-apt-repository ppa:webupd8team/java
sudo apt-get update && sudo apt-get install oracle-java8-installer
java -version

java version "1.8.0_91"
Java(TM) SE Runtime Environment (build 1.8.0_91-b14)
Java HotSpot(TM) 64-Bit Server VM (build 25.91-b14, mixed mode)

2. Install Jenkins

I recommend using a 2.x build of Jenkins to get Pipelines support but the LTS (1.651.3 LTS as of this writing) should work as well.

Installing Jenkins on Ubuntu: instructions

Copied here for prosperity:

wget -q -O - http://pkg.jenkins.io/debian/jenkins.io.key | sudo apt-key add -

# add to /etc/apt/sources.list
deb http://pkg.jenkins.io/debian binary/

# update and install
sudo apt-get update
sudo apt-get install jenkins

If everything went according to plan you’ll find Jenkins on port :8080 of your EC2 instance. Make sure 8080 is open in your security group.

I found the wizard at :8080 NOT :8080/jenkins as would be the case if we installed the WAR on a tomcat.

Follow the initial setup instructions in the 2.x setup wizard.

Plugins I selected:

  • Pipeline
  • GitHub Organization Folder Plugin
  • Git plugin
  • GitHub plugin
  • Credentials
  • Credentials binding

as well as the default Dashboard and email plugins.

Configure Nginx

You’ll have noticed by now that the packaged Jenkins needs that 8080 port. Lets fix that with a reverse proxy.

sudo apt-get update
sudo apt-get install nginx

Make sure to add port 80 to your security group and you should see the Nginx landing page by browsing to your EC2 instance:

nginx landing page

Let’s configure Nginx to route to Jenkins on port 80:

cd /etc/nginx/sites-available
sudo vi jenkins

server {
   listen 80;

   server_name elastic.ip.address jenkins.server.tld

   access_log /var/log/nginx/jenkins.server.tld/access.log;
   error_log  /var/log/nginx/jenkins.server.tld/error.log info;

   location / {
      proxy_pass  http://localhost:8080;
   }
}

#create the logs folder
sudo mkdir -p /var/log/nginx/jenkins.{{ hostname }}/
# remove default and add the jenkins site
sudo rm /etc/nginx/sites-enabled/default
# enable an nginx site with a syslink
sudo ln -s /etc/nginx/sites-available/jenkins /etc/nginx/sites-enabled/
# restart nginx
sudo service nginx restart

Configure Github plugin

Create an RSA keypair for jenkins:

ssh-keygen -t rsa

Note: don’t specify a password as it apparantly breaks Jenkins’ daemon - Jenkins and private repos

If you added a password, you can remove it with ssh-keygen -p

Assign your id_rsa.pub to your Github account

Browse to https://github.com/settings/ssh and copy your password-less id_rsa.pub as a new SSH key. This will allow two-way communication between Github and Jenkins.

You can verify the SSH connection with:

ssh -T git@github.com

jenkins@jenkins:~/.ssh$ ssh -T git@github.com
Hi github user! You've successfully authenticated, but GitHub does not provide shell access.

Note: no password should be prompted for

Not sure why this is the case since Jenkins’ credentials page specifes an SSH user and password combo. Make sure the password field is blank:

jenkins credentials keypair

Create a pipeline

Add the HTTPS url to the Jenkins build to listen for commits:

add HTTPS Github repo to build

Once you’ve configured SSH credentials for both Jenkins and Github we can verify git checkout works by creating a simple Pipeline:

node {
    stage 'Checkout'
    git credentialsId: 'jenkins.mblum.me', url: 'git@github.com:mikeblum/mblum.me.git'
}

It’s import to note here we use the SSH repo adddress, not the HTTPS version so our SSH keys we’ve configured allow for password-less deployments.

The credentialsId matches the ID speciifed in the Jenkins Global Credentials.

Kick off a test build with Build Now.

Deploying this blog

In our previous post: Deploying to S3 we configured Gitlab to deploy our site to Amazon S3. We’ll want to replicate the same behavior using Jenkins pipelines and Docker in the next post: Docker Pipelines.