Self-Hosted macOS CI on Apple Silicon
About
โข Getting Started
โข Ideas for the Future
โข Join Us
Caution
There seems to be an issue with swift-nio based SSH on macOS 15.X hosts. Please don't update your host OS if you rely on Cilicon for production CI. This issue only affects the host OS. Images may still be updated to 15.X.
We're excited to announce a new major update to Cilicon! Here's a summary of what's new:
- While Cilicon 1.0 relied on a user-defined Login Item script in the VM, its new version now includes an SSH client and directly executes commands on the VM.
- Cilicon has partially adopted the tart image format and can automatically convert 1.0 images to it.
- The integrated OCI client can download pre-built CI images that have been created with/for tart. We recommend their macos-sonoma-xcode images.
- The config file schema has changed slightly. In most cases renaming the
vmBundlePath
property tosource
should suffice. - When Cilicon detects a 1.0 image it will offer you to automatically convert it to the new format for you.
- When converting an image from the 1.0 format, you must enable SSH and set the respective credentials in the config (or use the default
admin:admin
).
Cilicon is a macOS App that leverages Apple's Virtualization Framework to create, provision and run ephemeral CI VMs with near-native performance. It currently supports Github Actions, Buildkite Agent, GitLab Runner and arbitrary scripts. Depending on your setup, should be able to get up and running with your self-hosted CI in minutes ๐
Cilicon operates in a very simple cycle described below:
The Cilicon Cycle |
Running a sample job via GitHub Actions (2x playback) |
To get started, download the latest release here.
Cilicon uses the tart
container format and comes with an integrated OCI client to fetch images from the internet.
It's recommended to use publicly hosted images, however if you need to create or customize your own image, you may use tart.
- When choosing an OCI hosted image, make sure to prepend the
oci://
scheme to the url. Cilicon will otherwise assume a local filesystem path. - Don't use the
latest
tag when choosing an image version. Instead pick the specific version of Xcode you would like to have installed (e.g.14.3
). - Images downloaded via OCI will reside in the
~/.tart
folder which should be cleared of unused images periodically. - Images with newer versions of macOS may be published with the same version of Xcode installed. In case you want to upgrade, you may need to manually delete the outdated image and start Cilicon again.
Cilicon expects a cilicon.yml
file to be present in the Host OS's home directory.
For more information on all available settings see Config.swift.
To use the GitHub Actions provisioner you will need to create and install a new GitHub App with Self-hosted runners
Read & Write
permissions on the organization level and download the private key file to be referenced in the configuration file.
source: oci://ghcr.io/cirruslabs/macos-sonoma-xcode:15.3
provisioner:
type: github
config:
appId: <APP_ID>
organization: <ORGANIZATION_SLUG>
privateKeyPath: ~/github.pem
To use the GitLab Runner provisioner you will need to create a runner with an authentication token.
Minimal example:
source: oci://ghcr.io/cirruslabs/macos-sonoma-xcode:15.3
provisioner:
type: gitlab
config:
gitlabURL: <GITLAB_INSTANCE_URL>
runnerToken: <RUNNER_TOKEN>
Full configuration:
source: oci://ghcr.io/cirruslabs/macos-sonoma-xcode:15.3
provisioner:
type: gitlab
config:
gitlabURL: <GITLAB_INSTANCE_URL>
runnerToken: <RUNNER_TOKEN>
executor: <EXECUTOR> # defaults to 'shell'
maxNumberOfBuilds: <MAX_BUILDS> # defaults to '1'
downloadLatest: <DOWNLOAD_LATEST> # defaults to 'true'
downloadURL: <DOWNLOAD_URL> # defaults to GitLab official S3 bucket
configToml: > # Advanced config as custom config.toml file to be appended to the basic config and copied to the runner.
<CONFIG_TOML>
To use the Buildkite Agent provisioner, simply set your agent token in the provisioner config.
source: oci://ghcr.io/cirruslabs/macos-sonoma-xcode:15.3
provisioner:
type: buildkite
config:
agentToken: <AGENT_TOKEN>
If you want to run a script (e.g. to start a runner that's not natively supported), you may use the script
provisioner.
source: oci://ghcr.io/cirruslabs/macos-sonoma-xcode:15.3
provisioner:
type: script
config:
run: |
echo "Hello World"
sleep 10
It is recommended to use Cilicon on a macOS device fully dedicated to the task, ideally one that is freshly restored.
If you don't want to host your machine locally, OakHost provides great value dedicated Macs and are kindly offering 10% off the first two months for new customers with the code CILICON10
(Disclaimer: We do not receive any form of compensation from sharing this code).
- Transfer
Cilicon.app
,cilicon.yml
as well as any other files referenced by your config (e.g. Local image, GitHub private key etc.) to your Host OS. - Add
Cilicon.app
as a launch item - Set up Automatic Login
- Disable automatic software updates
- Disable any concept of screen lock, battery saving etc.
We use GitHub Actions for our iOS builds at Trade Republic but would love to see Cilicon being used for other CI services as well.
Implementing support for more services should be easy by building on top of the Provisioner
protocol.
Xcode builds often don't use all of the compute resources available. Therefore running 2 VMs im parallel (more are not possible due to a limitation of the Virtualization framework) would be a welcome addition.
A logging or monitoring concept would greatly improve identifying and troubleshooting any potential issues and provide the ability to notify the team in real time.
At Trade Republic, we are on a mission to democratize wealth. We set up millions of Europeans for wealth with fast, easy, and free access to capital markets. With over one million customers we are one of the largest savings platforms in Europe, with users holding over โฌ6 billion on our platform. Join us to build the FinTech of the future.
Disclaimer: Trade Republic is not affiliated with Cirrus Labs or their tart product