Eyes, JAPAN Blog > Configuring Jenkins on OS X Mountain Lion

Configuring Jenkins on OS X Mountain Lion

denvazh

この記事は1年以上前に書かれたもので、内容が古い可能性がありますのでご注意ください。

Why?

In normal working software development environment, where certain tools used to make developers live easier (IDE, version control, doxygen and etc. ) there is a solution, that really helps controlling the how process. This is called continuous integration. Central part of such solution is a system for automated software testing and building. In this blog post I will explain how to setup Jenkins build system on OS X Mountain Lion environment.

Requirements

  • preinstalled Xcode with command-line tools
  • ALL actions below must be done either as a root user or sudo, so please make sure you have necessary admin permissions on the system you about to install software to.

1. Install homebrew

It is pretty straight-forward, thus I would recommend to follow offical installation documents provided here

Make sure to check if paths are in the following order

echo $PATH
	/usr/local/bin:/usr/bin:/bin:/usr/local/sbin:/usr/sbin:/sbin:/usr/X11/bin

If its not the case, then change the file /etc/paths to be like

	/usr/local/bin
	/usr/bin
	/bin
	/usr/local/sbin
	/usr/sbin
	/sbin

Important: creating text file in /etc/paths.d won’t have any effect, because paths from /etc/paths loaded first, and only then paths from files in /etc/paths.d.

2. Install jenkins
Installing jenkins with homebrew

	brew install jenkins

Creating jenkins user.

#!/bin/bash

# Modified by Denis Vazhenin <[email protected]>
#
# Based on original script for jenkins post install on OS X
# https://github.com/yokoe/jenkins/blob/master/osx/scripts/postinstall-launchd-jenkins

# checking if platform is OS X
if [ `uname -s` != 'Darwin' ]; then
	printf "Error: this script can be used only in OS X\n"
	exit 1
fi

JENKINS_USR='jenkins'
JENKINS_HOMEDIR="/Users/Shared/Jenkins"
JENKINS_HOME="/Users/Shared/Jenkins/Home"

mkdir -p $JENKINS_HOMEDIR
mkdir -p $JENKINS_HOME

# check if user already exists
stat=`dscl . -list /Users/${JENKINS_USR} 2&>1`

if [ $stat -eq 0 ]; then
	# user already exists
	printf "User %s already exists \n" $JENKINS_USR

	# forcing shell not to be /usr/bin/false	
	dscl . -change /Users/${JENKINS_USR} UserShell /usr/bin/false /bin/bash	
else
	# user not exists	
	printf "Creating %s user\n" $JENKINS_USR

	# find not occupied system uid (<500)
	uid=$(dscl . -list /Users uid | sort -nrk 2 | awk '$2 < 500 {print $2 + 1; exit 0}')
	
	if [ $uid -eq 500 ]; then
		printf "Error: Unable to create %s user, all uid < 500 already occupied"
		exit 1
	fi
	
	# group should be the same as uid, looking for gid
	gid=$uid
	
	while dscl . -search /Groups gid $gid | grep -q $gid; do
		gid=$(($gid + 1))

		__stat=$(dscl . -search /Users uid $gid | grep $gid)
		if [ x"${__stat}" == x ]; then
			# "$gid is free"
			uid=$gid
		fi
	done

	printf "Using %s:%s for %s user\n" $uid $gid $JENKINS_USR

	# create user ( use dscl cmd )

	dscl . -create /Groups/${JENKINS_USR} PrimaryGroupID $gid
	dscl . -create /Users/${JENKINS_USR} UserShell /bin/bash
	dscl . -create /Users/${JENKINS_USR} Password '*'
	dscl . -create /Users/${JENKINS_USR} UniqueID $uid
	dscl . -create /Users/${JENKINS_USR} PrimaryGroupID $gid
	dscl . -create /Users/${JENKINS_USR} NFSHomeDirectory "$JENKINS_HOMEDIR"

	dscl . -append /Groups/${JENKINS_USR} GroupMembership ${JENKINS_USR}
fi

# fix directory permissions
find "$JENKINS_HOMEDIR" \( -not -user ${JENKINS_USR} -or -not -group ${JENKINS_USR} \) -print0 | xargs -0 chown ${JENKINS_USR}:${JENKINS_USR}

# create directory for logs and fix permissions
mkdir -p /var/log/${JENKINS_USR}

chown ${JENKINS_USR}:${JENKINS_USR} /var/log/${JENKINS_USR}

printf "Done.\n"

Setting-up jenkins service default parameters

defaults write /Library/Preferences/org.jenkins-ci war "/usr/local/opt/jenkins/libexec/jenkins.war"
defaults write /Library/Preferences/org.jenkins-ci heapSize 512m
defaults write /Library/Preferences/org.jenkins-ci httpListenAddress 127.0.0.1
defaults write /Library/Preferences/org.jenkins-ci httpPort 8080
defaults write /Library/Preferences/org.jenkins-ci permGen 256m
defaults write /Library/Preferences/org.jenkins-ci JENKINS_HOME "/Users/Shared/Jenkins/Home"

Setting-up jenkins service wrapper. Put the following script to /Library/Application Support/Jenkins/jenkins-runner.sh

#!/bin/bash
#
# Startup script used by Jenkins launchd job.
# Mac OS X launchd process calls this script to customize
# the java process command line used to run Jenkins.
# 
# Customizable parameters are found in
# /Library/Preferences/org.jenkins-ci.plist
#
# You can manipulate it using the "defaults" utility.
# See "man defaults" for details.

defaults="defaults read /Library/Preferences/org.jenkins-ci"

war=`$defaults war` || war="/Applications/Jenkins/jenkins.war"

javaArgs=""
heapSize=`$defaults heapSize` && javaArgs="$javaArgs -Xmx${heapSize}"
permGen=`$defaults permGen` && javaArgs="$javaArgs -XX:MaxPermSize=${permGen}"

home=`$defaults JENKINS_HOME` && export JENKINS_HOME="$home"

add_to_args() {
    val=`$defaults $1` && args="$args --${1}=${val}"
}

args=""
add_to_args prefix
add_to_args httpPort
add_to_args httpListenAddress
add_to_args httpsPort
add_to_args httpsListenAddress
add_to_args ajp13Port
add_to_args ajp13ListenAddress

echo "JENKINS_HOME=$JENKINS_HOME"
echo "Jenkins command line for execution:"
echo /usr/bin/java $javaArgs -jar "$war" $args
exec /usr/bin/java $javaArgs -jar "$war" $args

Installing and enabling jenkins service.

Put the following script and name it as /Library/LaunchAgents/org.jenkins-ci.plist

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
    <key>StandardOutPath</key>
    <string>/var/log/jenkins/jenkins.log</string>
    <key>StandardErrorPath</key>
    <string>/var/log/jenkins/jenkins.log</string>
	<key>EnvironmentVariables</key>
	<dict>
		<key>JENKINS_HOME</key>
		<string>/Users/Shared/Jenkins/Home</string>
	</dict>
	<key>GroupName</key>
	<string>daemon</string>
	<key>KeepAlive</key>
	<true/>
	<key>Label</key>
	<string>org.jenkins-ci</string>
	<key>ProgramArguments</key>
	<array>
                <string>/bin/bash</string>
		<string>/Library/Application Support/Jenkins/jenkins-runner.sh</string>
	</array>
	<key>RunAtLoad</key>
	<true/>
	<key>UserName</key>
	<string>jenkins</string>
        <key>SessionCreate</key>
	<true />
</dict>
</plist>

Fix ownership to root and permissions to 644.

PLIST='/Library/LaunchAgents/org.jenkins-ci.plist'; chown root:wheel $PLIST && chmod 644 $PLIST

Start jenkins service

launchctl load -w /Library/LaunchAgents/org.jenkins-ci.plist

3. Install nginx
Installing nginx with homebrew

	brew install nginx

Configure nginx to run as a system daemon

	cp /usr/local/opt/nginx/homebrew.mxcl.nginx.plist /Library/LaunchAgents/
	chown root:wheel /Library/LaunchAgents/homebrew.mxcl.nginx.plist && chmod 644 /Library/LaunchAgents/homebrew.mxcl.nginx.plist

Configure jenkins to run behind nginx reverse proxy

Edit file /usr/local/etc/nginx/nginx.conf to be like this, but MAKE SURE TO CHANGE server_name to match YOUR settings.

worker_processes  1;

events {
    worker_connections  1024;
}

http {
    include       mime.types;
    default_type  application/octet-stream;
    sendfile        on;
    keepalive_timeout  65;

server {
  listen 80;
  server_name some_jenkins_server.com;

  location / {
    proxy_pass              http://localhost:8080;
    proxy_set_header        Host $host;
    proxy_set_header        X-Real-IP $remote_addr;
    proxy_set_header        X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_connect_timeout   150;
    proxy_send_timeout      100;
    proxy_read_timeout      100;
    proxy_buffers           4 32k;
    client_max_body_size    8m;
    client_body_buffer_size 128k;

    error_page   500 502 503 504  /50x.html;
        location = /50x.html {
            root   html;
    }
  }
}

Check configuration and start nginx

	/usr/local/bin/nginx -t
nginx: the configuration file /usr/local/etc/nginx/nginx.conf syntax is ok
nginx: configuration file /usr/local/etc/nginx/nginx.conf test is successful

Starting nginx

launchctl load -w /Library/LaunchAgents/homebrew.mxcl.nginx.plist

After few seconds if you go to some_jenkins_server.com (or the one you’ve set up yourself), you should see jenkins menu.

Conclusion

From that point it is possible to setup jenkins in the way it is desired for any software development team. Security, build settings, automatic deployment to external services and etc. Whole world of continuos integration is open for you.
One more thing: why I thought it would be better to have a setup like this? Answer is very simple: jenkins is very well maintained and regularly updated, thus (from my point of view) it is good to use existing tools, namely homebrew, to install and update it.

Comments are closed.