Jenkins on Fedora Server 21

     

Preamble

Yeah, at the time of writing it’s in alpha yet, but it’s already in a quite good shape. My plan is to migrate our current services from Ubuntu Server to Fedora Server. This is one of the first attempts, so you may even call this a feasibility study. So far, it seems Fedora will do the job well. So without further ado, let’s get into it.

Fedora

I recommend performing a Minimal Install with the Standard and Headless Management add-ons to minimize the attack surface and all that stuff. If running virtualized, you probably want to select the Guest Agents add-on as well.

If you’re wondering why you need those add-ons, check out the other post, Jenkins Service Unavailable for details.

I used the 64 bit version but it should work just fine with the 32 bit one, too. Once the installation’s finished, proceed to the next section.

Prerequisites

Packages

There’s an official Fedora package for Jenkins but it installs a lot of unnecessary dependencies, it doesn’t have an LTS version and naturally it lags behind the official Jenkins RPMs, so in this guide we’ll use the official Jenkins repo and install an LTS release. For this, you gotta exclude the official Fedora package for Jenkins. To achieve that, first you gotta find out which repo contains the Jenkins package:

yum info jenkins

Find something like this:

Repo : updates-testing/21/x86_64

So now you gotta go to /etc/yum.repos.d and open the fedora-updates-testing.repo file. Now find the [updates-testing] section and put the following line at the end of it:

exclude=jenkins

Now check with yum again. It may show Jenkins again, except in a different repo, like this:

Repo : fedora/21/x86_64

So now open the fedora.repo file, and put the same exclude line in the [fedora] section. Repeat this until you get the following output:

Error: No matching Packages to list

Now you’re ready to install Jenkins, but first you also gotta install the Java runtime, because the official Jenkins RPM seems to not have that set up as a dependency, probably because it leaves it up to you to use whatever you want.

Which is fortunate, because Fedora 21 introduced the headless version of the JRE, which means we don’t have to install any GUI-related bloat on the headless server. So install the headless JRE:

yum install java-1.8.0-openjdk-headless

Firewall

You need to open port 80 (the standard HTTP port) to be able to reach your future Jenkins instance. To do this, go to /etc/firewalld/zones and open the appropriate zone file. By default, this is public.xml. Add the following line:

<service name="http"/>

Now reload the firewall configuration:

firewall-cmd --reload

Then verify that it indeed includes http:

firewall-cmd --list-services

If it does, proceed.

Jenkins

Installation

To install Jenkins, you gotta add their repo to your repo list:

sudo wget -O /etc/yum.repos.d/jenkins.repo http://pkg.jenkins-ci.org/redhat-stable/jenkins.repo
sudo rpm --import http://pkg.jenkins-ci.org/redhat-stable/jenkins-ci.org.key

At this point, a jenkins.repo file will appear under /etc/yum.repos.d. Now query the available Jenkins packages which will automatically fetch data from the newly added repo:

yum info jenkins

A new Jenkins package should appear in the jenkins repo:

Repo : jenkins

Now install it:

yum install jenkins

After the install, you can start Jenkins:

systemctl start jenkins.service

By default, it listens on port 8080 so you’d be able to reach it there, except Fedora’s firewall won’t let you yet (we’ll get back to that soon). But if you want, you can already test it via the terminal:

wget localhost:8080

If you get an

ERROR 503: Service Unavailable.

response, just try again a bit later, Jenkins takes some time to start. Once it’s started, you shoud receive an index.html file with the Jenkins start page. So once it works on localhost, the next step is to make it accessible from the network on port 80.

Direct access

On Unix, if a process wants to open a port under 1024 it must have root privileges. It’s probably not a good idea to run Jenkins as root, but if you wanna go this route it’s certainly doable.

Go to /etc/sysconfig and open the jenkins file. Find the following line:

JENKINS_USER="jenkins"

Change it from jenkins to root. Then also find:

JENKINS_PORT="8080"

and change it to 80. Save the file, then restart the Jenkins service:

systemctl restart jenkins.service

At this point, you should be able to reach your Jenkins instance from the network.

Access via reverse proxy

A slightly more sophisticated approach is to let Jenkins run on port 8080 and make it accessible via a reverse proxy that does nothing else but forwards the traffic back and forth between port 80 and 8080.

The reverse proxy I use in this scenario is nginx. Install it:

yum install nginx

Now go to /etc/nginx, backup the old config and create a new one:

mv nginx.conf nginx.conf.orig
touch nginx.conf

Now paste this into the new nginx.conf:

user  nginx;
worker_processes  1;

error_log  /var/log/nginx/error.log;

pid        /run/nginx.pid;

events {
    worker_connections  1024;
}

http {
    include       /etc/nginx/mime.types;
    include       /etc/nginx/sites-enabled/*;
    default_type  application/octet-stream;

    log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
                      '$status $body_bytes_sent "$http_referer" '
                      '"$http_user_agent" "$http_x_forwarded_for"';

    access_log  /var/log/nginx/access.log  main;
    sendfile        on;
    keepalive_timeout  65;
    index   index.html index.htm;
}

Also create the sites-available and sites-enabled directories:

mkdir sites-available
mkdir sites-enabled

Now go to sites-available and create the jenkins file. Make it look like this:

upstream app_server {
    server 127.0.0.1:8080 fail_timeout=0;
}

server {
    listen 80;
    listen [::]:80 default ipv6only=on;
    server_name ci.yourcompany.com;

    location / {
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header Host $http_host;
        proxy_redirect off;

        if (!-f $request_filename) {
            proxy_pass http://app_server;
            break;
        }
    }
}

Now switch to the sites-enabled directory, and create a symlink for the jenkins file:

ln -s ../sites-available/jenkins

Alright, nginx’s configured up, time to restart:

systemctl restart nginx.service

Now you try to re-open the Jenkins web page, and all is good, right? Wrong. It doesn’t work yet because SELinux is blocking it. So now it’s time to tell SELinux to let this traffic go. For that, you need to generate a policy file, but for that you need to install the appropriate utilities first:

yum install policycoreutils-python

Now generate the policy file:

grep nginx /var/log/audit/audit.log | grep denied | audit2allow -M nginx

This generates 2 files, nginx.pp and nginx.te. Install the policy, which will take a few seconds to complete:

semodule -i nginx.pp

And that’s it, your Jenkins instance should be up and running via nginx.