Installing Jenkins on OS X Yosemite
Jenkins is a continuous integration (CI) server written in Java. It’s a pretty common solution for self-hosted CI servers.
A lot of the documentation for installing on OS X is a little old (OS X has changed a lot when it comes to say, Java, in the last few years) and it seemed a good plan to write up something a bit newer.
I host a Jenkins instance on a hosted Mac mini with Macminicolo. In addition to Yosemite, it’s also got the OS X Server package installed, Open Directory (which is Apple’s name for LDAP) configured and a few other tools. It’s typically used for boxes builds.
I’m assuming you’ll be installing Jenkins via Homebrew as the Jenkins installer does some odd things around how the user is handled. I’m also assuming you’re connected via VNC/Screen Sharing, as often it requires a GUI.
1. Install Java
You likely don’t have Java installed yet, so open a terminal and enter java
to request the install. Follow the instructions.
2. Create a user for Jenkins
It’s best to run Jenkins as it’s own user (it can then be limited in the permissions it has), and you’ll want to create a standard (full) user for it.
You can do this through System Preferences, the Server Manager or the command line.
For a local user:
# create an applications group
dseditgroup -o create -n . -u username -p -r ‘Applications’ applications
# get the id for that group
sudo dscl . -read /Groups/applications
# find a unique identifier to give the user
sudo dscl . -list /Users UniqueID
# create the jenkins user
sudo dscl . -create /Users/jenkins
sudo dscl . -create /Users/jenkins PrimaryGroupID 505
sudo dscl . -create /Users/jenkins UniqueID 1026
sudo dscl . -create /Users/jenkins UserShell /bin/bash
sudo dscl . -create /Users/jenkins RealName "Jenkins"
sudo dscl . -create /Users/jenkins NFSHomeDirectory /Users/jenkins
sudo dscl . -passwd /Users/jenkins
# create and set the owner of the home directory
sudo mkdir /Users/jenkins
sudo chown -R jenkins /Users/jenkins
(Replace username
with the username of an admin user).
For an Open Directory user (replace the IP with the location of the relevant OD tree):
# create an applications group
dseditgroup -o create -n /LDAPv3/127.0.0.1 -u diradmin -p -r ‘Applications’ applications
# get the id for that group
sudo dscl -u diradmin -p /LDAPv3/127.0.0.1 -read /Groups/applications
# find a unique identifier to give the user
sudo dscl -u diradmin -p /LDAPv3/127.0.0.1 -list /Users UniqueID
# create the jenkins user
sudo dscl -u diradmin -p /LDAPv3/127.0.0.1 -create /Users/jenkins
sudo dscl -u diradmin -p /LDAPv3/127.0.0.1 -create /Users/jenkins PrimaryGroupID 505
sudo dscl -u diradmin -p /LDAPv3/127.0.0.1 -create /Users/jenkins UniqueID 1026
sudo dscl -u diradmin -p /LDAPv3/127.0.0.1 -create /Users/jenkins UserShell
/bin/bash
sudo dscl -u diradmin -p /LDAPv3/127.0.0.1 -create /Users/jenkins RealName "Jenkins"
sudo dscl -u diradmin -p /LDAPv3/127.0.0.1 -create /Users/jenkins NFSHomeDirectory /Users/jenkins
sudo dscl -u diradmin -p /LDAPv3/127.0.0.1 -passwd /Users/jenkins
# create and set the owner of the home directory
sudo mkdir /Users/jenkins sudo chown -R jenkins /Users/jenkins
You’ll now able to login as the Jenkins user by doing something like: sudo -u
jenkins -i
(this will login as Jenkins with a full user session).
3. Install Jenkins
Run brew install jenkins
as the user you’d normally use brew
with.
4. Configure the Launch Item
OS X handles services using launchd
and has a few different types for where
they should be placed:
Type | Context |
---|---|
LaunchDaemon | System |
LaunchAgent | User |
More detail can be found in the Daemons and Services Programming Guide.
In our case, we want to run Jenkins as a LaunchDaemon
as our newly created
jenkins
user, so create a plist
file as
/Library/LaunchDaemons/homebrew.mxcl.jenkins.plist
with:
<?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>Label</key>
<string>homebrew.mxcl.jenkins</string>
<key>ProgramArguments</key>
<array>
<string>/usr/bin/java</string>
<string>-Dmail.smtp.starttls.enable=true</string>
<string>-jar</string>
<string>/usr/local/opt/jenkins/libexec/jenkins.war</string>
<string>--httpListenAddress=127.0.0.1</string>
<string>--httpPort=8080</string>
</array>
<key>RunAtLoad</key>
<true/>
<key>UserName</key>
<string>jenkins</string>
</dict>
</plist>
And then load it: sudo launchctl load
/Library/LaunchDaemons/homebrew.mxcl.jenkins.plist
.
(I’m sticking with the convention for naming as recommended by Hombrew.)
5. Test it out
Now you’ll be able to go to http://127.0.0.1:8080
(locally) and see Jenkins.
You’ll want to verify that it’s launched with the correct user, which can be
found under “System Info”.
The Launch Daemon specifies that it’ll only listen on 127.0.0.1
, so it’s not
possible to access it outside the local machine.
(I’d recommend keeping Jenkins inside an internal network, as it’s executing code on the local machine. Maybe by restricting it like below…)
6. (Optional) Reverse Proxying Apache & Restricting by Networks
It’s likely that you’ll want to access Jenkins at a specific domain and not have to use a separate port. This can be accomplished in lots of ways, but here I’m going to explain Apache as that’s what OS X Server uses by default. If you’re not using OS X Server, either install Apache or another Web Server such as nginx. The steps below configure this using SSL (using this guide), you can cut out much of this if you’d prefer not to.
First, enable “Websites” in Server. It doesn’t need any special configuration for what we’ll be doing.
Next, create a new site from within Server. This will ensure it’s all working in the manner it expects. Here, I’ve restricted it to internal only IPs:

The configuration for “Websites” is held in:
/Library/Server/Web/Config/apache2
. There’s a README
which might be helpful
to read.
Next, reconfigure the configuration file for the new site (which is an Apache virtualhost):
# /Library/Server/Web/Config/apache2/sites/0000_10.0.0.1_443_jenkins.example.com.conf
<VirtualHost 10.0.0.1:443>
ServerName jenkins.example.com
ServerAdmin admin@example.com
DocumentRoot "/Library/Server/Web/Data/Sites/jenkins.example.com"
DirectoryIndex index.html index.php /wiki/ /xcode/ default.html
CustomLog /var/log/apache2/access_log combinedvhost
ErrorLog /var/log/apache2/error_log
<IfModule mod_ssl.c>
SSLEngine On
SSLCipherSuite "ALL:!aNULL:!ADH:!eNULL:!LOW:!EXP:RC4+RSA:+HIGH:+MEDIUM"
SSLProtocol -ALL +TLSv1
SSLProxyEngine On
SSLCertificateFile "/etc/certificates/certificate_name.cert.pem"
SSLCertificateKeyFile "/etc/certificates/certificate_name.key.pem"
SSLCertificateChainFile "/etc/certificates/certificate_name.chain.pem"
SSLProxyProtocol -ALL +TLSv1
SSLProxyCheckPeerCN off
SSLProxyCheckPeerName off
</IfModule>
<Directory "/Library/Server/Web/Data/Sites/jenkins.example.com">
Options All -Indexes -ExecCGI -Includes +MultiViews
AllowOverride None
<IfModule mod_dav.c>
DAV Off
</IfModule>
<IfDefine !WEBSERVICE_ON>
Require all denied
ErrorDocument 403 /customerror/websitesoff403.html
</IfDefine>
</Directory>
<proxy>
Order Deny,Allow
Deny from all
Allow from 127.0.0.1
Allow from 10.0.0.1/8
Allow from 199.19.86.77
</proxy>
ProxyPass / http://127.0.0.1:8080/ nocanon
ProxyPassReverse / http://127.0.0.1:8080/
ProxyRequests Off
AllowEncodedSlashes NoDecode
RequestHeader set X-Forwarded-Proto "https"
RequestHeader set X-Forwarded-Port "443"
</VirtualHost>
Much of this is the default configuration, with the bottom two additions being the important bit:
<proxy>
Order Deny,Allow
Deny from all
Allow from 127.0.0.1
Allow from 10.0.0.1/8
</proxy>
ProxyPass / http://127.0.0.1:8080/ nocanon
ProxyPassReverse / http://127.0.0.1:8080/
ProxyRequests Off
AllowEncodedSlashes NoDecode
RequestHeader set X-Forwarded-Proto "https"
RequestHeader set X-Forwarded-Port "443"
…which configures it as a reverse proxy.
Next, restart Apache:
sudo /Applications/Server.app/Contents/ServerRoot/usr/sbin/serveradmin stop web
sudo /Applications/Server.app/Contents/ServerRoot/usr/sbin/serveradmin start web
7. (Optional) Configure Users with LDAP
The final step I took was to configure Jenkins’ user support against OS X Server’s Open Directory. This is just LDAP with a different name, and it’s easy to get working.
Under “Manage Jenkins” → “Configure Global Security”, configure the server to the correct name and then fill in the root DN like so:
dc=server,dc=example,dc=com
…where server
, example
, com
make up the hostname of the configured LDAP
tree (server.example.com
). This screenshot might help:

Jenkins will be able to configure the rest itself.
8. (Optional) Manage the Jenkins Process with brew services
The default way to manage processes on OS X is using launchctl
, but the
syntax isn’t the easiest to use. For example, restarting Jenkins (something
you’ll want to do each time it’s upgrade):
sudo launchctl unload /Library/LaunchDaemons/homebrew.mxcl.jenkins.plist
sudo launchctl load /Library/LaunchDaemons/homebrew.mxcl.jenkins.plist
The alternative is to use brew services, which can make this much easier:
# first, install it:
brew tap homebrew/services
# then you can view the services:
sudo brew services list
# restarting:
sudo brew services restart jenkins
Closing Steps
Before configuring your first set of builds, you’ll likely want to install a set of plugins. I use: