Home / Jenkins macOS Build Agent
Jenkins macOS Build Agent
A Jenkins macOS build agent lets your existing Jenkins controller run Xcode builds and Apple-platform tests. Hatmac provides the dedicated Mac mini or Mac Studio in the cloud; your controller stays where it is.
Two ways to connect a Mac to Jenkins
| SSH agent | Inbound agent | |
|---|---|---|
| Who connects | Controller opens SSH to the Mac | Mac connects to the controller |
| Plugin or tool | SSH Build Agents plugin | agent.jar, over WebSocket or the TCP agent port |
| Network need | Controller can reach the Mac's SSH port | Mac can reach the controller URL |
| Restarts | Controller relaunches the agent | You keep the process running with launchd |
| Good when | Controller has a stable outbound path | Controller is behind a firewall or NAT |
Both use the same Mac setup: a dedicated ci user, Java, Xcode and a work directory such as /Users/ci/jenkins. If you are still comparing CI systems, see the macOS CI/CD runner overview.
Mac mini M4
16GB · 256GB SSD
Everyday iOS builds, CI runners and remote macOS.
from $119/mo
- Monthly$149/mo
- 6 months$139/mo
- 12 months$119/mo
Mac mini M6
16GB · 256GB SSD
Newer chip for faster compiles and test runs.
from $129/mo
- Monthly$169/mo
- 6 months$159/mo
- 12 months$129/mo
Mac mini M6
Most popular24GB · 512GB SSD
More memory and storage for larger projects and caches.
from $179/mo
- Monthly$209/mo
- 6 months$199/mo
- 12 months$179/mo
Mac mini M5 Pro
24GB · 512GB SSD
Pro-class CPU and GPU for heavy builds and small models.
from $229/mo
- 6 months$249/mo
- 12 months$229/mo
Prices in USD per month for each machine's starting configuration. More memory, storage or several machines? Ask us.
Prepare the Mac
- Order a Mac. After payment we set it up and email you; SSH details appear under My Macs.
- Create a standard user for Jenkins and log in as it.
- Install Xcode, accept the licence and run first launch. Our Xcode build server page covers multiple Xcode versions.
- Install a Java runtime that your controller supports. Java 21 is a safe choice for current Jenkins releases; check jenkins.io if your controller is older.
brew install --cask temurin@21
java -version
Option 1: SSH Build Agents plugin
- Add the controller's public key to
~/.ssh/authorized_keysfor theciuser on the Mac. - In Jenkins, install the SSH Build Agents plugin, then go to Manage Jenkins → Nodes → New Node.
- Set the remote root directory to
/Users/ci/jenkinsand labels such asmacos xcode m6. - Choose Launch agents via SSH, enter the host and port from My Macs, pick an SSH key credential and a host key verification strategy (known hosts or manually trusted).
- Save. The controller copies
remoting.jarto the Mac and starts it.
One common catch: non-interactive SSH sessions do not read your shell profile, so Homebrew tools may be missing from PATH. Add /opt/homebrew/bin under the node's environment variables, or set JavaPath in the launch method's advanced options.
Option 2: Inbound agent with agent.jar
Create the node with the launch method Launch agent by connecting it to the controller. The node page shows a secret and the exact command. On the Mac, run it as the ci user:
mkdir -p ~/jenkins && cd ~/jenkins
curl -sO https://jenkins.example.com/jnlpJars/agent.jar
echo "SECRET_FROM_NODE_PAGE" > ~/jenkins/secret-file && chmod 600 ~/jenkins/secret-file
java -jar agent.jar -url https://jenkins.example.com/ \
-name mac-m6 -secret @$HOME/jenkins/secret-file \
-webSocket -workDir "$HOME/jenkins"
-webSocket uses the normal HTTPS port, so you do not need to expose the TCP agent port. To keep the agent running after logout and reboots, wrap the command in a launchd agent in ~/Library/LaunchAgents. Details are in the Jenkins nodes documentation.
Labels and the pipeline
Use labels to describe what the agent can do, then select it with a label expression. Unlock the signing keychain inside withCredentials and lock it again in post:
pipeline {
agent { label 'macos && xcode' }
stages {
stage('Archive') {
steps {
withCredentials([string(credentialsId: 'ci-keychain-password',
variable: 'KEYCHAIN_PASSWORD')]) {
sh '''
security unlock-keychain -p "$KEYCHAIN_PASSWORD" ~/Library/Keychains/ci.keychain-db
xcodebuild archive -scheme MyApp -destination 'generic/platform=iOS' \
-archivePath build/MyApp.xcarchive
'''
}
}
}
}
post {
always { sh 'security lock-keychain ~/Library/Keychains/ci.keychain-db || true' }
}
}
Keep the shell block in single quotes so Groovy does not interpolate the password into the build log. The keychain itself is set up once, as shown on the iOS build server page.
Sizing and executors
- Set the node to 1 executor on a 16GB Mac mini. Xcode and simulators use a lot of memory.
- The Mac mini M6 with 24GB / 512GB can usually handle two executors for lighter jobs, or one heavy UI-test job.
- For more parallel jobs, add more Macs with the same labels and let Jenkins spread the load. See Mac build farm, or tell us what you need for a multi-machine quote.
FAQ
Which is better for a Jenkins macOS build agent, SSH or inbound?
SSH is simpler to manage because the controller restarts the agent for you. Use an inbound agent when the controller cannot reach the Mac, for example when it sits behind NAT.
Does the Jenkins controller have to run on a Mac?
No. The controller can run on Linux, in a container or anywhere else. Only the jobs that need Xcode must run on the macOS agent.
Why does codesign hang or fail on the agent?
Usually the keychain is locked or the key partition list has not been set. Unlock the keychain in the job and run security set-key-partition-list once when you import the certificate.
Can I keep the agent month to month?
Yes. The Mac mini M4 and M6 are available month to month. See pricing.