This article explains how to set up a JNLP macOS slave, which is useful e.g. when slaves are in private network and Jenkins master cannot initialize connection via SSH. Also, method described in this article allows to use graphical applications such as Xcode.

foo is used as a sample user which runs Jenkins jobs in this article.

Preparation

Install the same version of Java as on your master, e.g. from AdoptOpenJDK or Azul.

Also, you should have a slave already created on Jenkins with Launch method set to Launch agent by connecting it to the master and Remote root directory set to e.g. /Users/foo/jenkins.

Obtaining a Jenkins slave secret

If the slave is not yet connected to Jenkins, you can obtain a secret on it’s page on Jenkins (https://jenkins.domain.com/computer/your-node-name/). Then put this randomly generated string e.g. to the /Users/foo/Documents/jenkins/jenkins-secret file.

Then create a /Users/foo/jnlp_slave directory and download agent.jar there from the slave’s page above. This directory will also store log files.

Create a LaunchAgent

Create a LaunchAgent /Library/LaunchAgents/com.jenkins.ci.one.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>Label</key>
    <string>com.jenkins.ci.one</string>
    <key>UserName</key>
    <string>foo</string>
    <key>SessionCreate</key>
    <true/>
    <key>EnvironmentVariables</key>
    <dict>
        <key>JAVA_HOME</key>
        <string>/usr/local/bin/jdk/Contents/Home</string>
    </dict>
    <key>ProgramArguments</key>
    <array>
        <string>/Users/foo/jnlp_slave/jnlp.sh</string>
    </array>
    <key>KeepAlive</key>
    <true/>
    <key>StandardOutPath</key>
    <string>/Users/foo/jnlp_slave/stdout.log</string>
    <key>StandardErrorPath</key>
    <string>/Users/foo/jnlp_slave/error.log</string>
</dict>
</plist>

LaunchAgent allows to run GUI applications and LaunchDaemon is not really supported now. You might get an error like Failed to find newest available Simulator runtime from Xcode when using LaunchDaemon.

Remember to check if JAVA_HOME is set correctly.

Initializing a JNLP connection

Create a jnlp.sh script in the /Users/foo/jnlp_slave directory which will initialize a connection (and configure additional stuff depending on your needs).

#!/bin/bash

java -jar "/Users/foo/jnlp_slave/agent.jar" -jnlpUrl https://jenkins.domain.com/computer/foo/slave-agent.jnlp -secret @/Users/foo/Documents/jenkins/jenkins-secret -workDir "/Users/foo/jenkins"

Set the foo user to auto-login in macOS Settings and reboot.