pool.yml, see Harness’s Set up a macOS VM build infrastructure with Orka.
How it works
- The Harness Delegate and VM runner run in your network. Harness documents how to install the Delegate and its system requirements.
- The runner keeps a warm pool of ready VMs, or deploys them on demand, up to a limit you set. It calls the Orka API with a service account token and deploys each VM from a VM config or directly from an image.
- At boot, a launchd daemon in the image reads a startup script that the runner passes through VM metadata. The script starts the Harness agent, lite-engine, which runs the build.
- The runner reaches lite-engine at the node’s IP address on TCP port 9079 or 9080, which Orka forwards to the VM.
- When the build finishes, the runner deletes the VM.
Prerequisites
- An Orka cluster with Apple silicon nodes, on Orka 3.x or 4.0. The integration deploys VMs from OCI images.
- A host for the Harness Delegate and runner that can reach the Orka API and your Orka nodes. See Network access.
- An Orka administrator to create the service account.
Set up Orka for Harness
1
Create a service account and token
Create a service account for Harness, then generate a token for it. Use a service account token, not a user token: user tokens expire after about an hour.The token lasts one year by default. Give it to the runner as the
ORKA_TOKEN environment variable, as Harness describes in Start the runner. For token lifetimes and rotation, see Manage service accounts.On Orka 3.x, use orka3 in place of orka.2
Choose a namespace
The runner deploys VMs into the namespace set in On Orka 3.x, use
pool.yml. Orka namespace names must start with orka-, so a namespace such as harness-ci can’t exist on an Orka cluster, and the runner fails because the namespace isn’t found.To use the default namespace, set namespace: orka-default in pool.yml. To keep Harness builds on their own nodes, create a namespace, move nodes into it, and give the service account access:orka3 rolebinding add-subject --namespace orka-harness-ci --serviceaccount orka-default:harness for the last command. For more on namespaces, see Namespace management.3
Prepare a VM image
Start from an Orka image, for example
ghcr.io/macstadium/orka-images/tahoe:latest, and add the tools your builds need, such as Xcode. Then add the Harness bootstrap daemon, as described in Harness’s Prepare your Orka base image.The image needs:- Orka VM Tools, which serve the VM metadata the daemon reads. MacStadium’s Orka images include them. If you build your own base image, install them.
- Homebrew, at
/opt/homebrew. The runner’s startup script installs lite-engine under/opt/homebrew/bin.
orka vm push, and wait for the push to finish (orka vm get-push-status <JOB_NAME>) before you use the image. To make VMs start faster, cache it on the nodes Harness uses with orka imagecache add.4
Create a VM config (optional)
The runner can deploy from an image directly, or from a VM config. To use a VM config, create one:Use
--tag to keep Harness builds on specific nodes, and --tag-required to keep them off other nodes. If you deploy from an image instead, the runner’s pool.yml has matching tag and tag_required settings. For all options, see VM deployment and configuration.5
Plan the port mapping
On each deploy, the runner asks Orka to forward TCP port 9079 on the node to lite-engine on port 9079 in the VM. If 9079 is already taken on the node, it retries with node port 9080. A node runs at most 2 VMs, so the two ports cover it. Don’t map 9079 or 9080 to anything else on nodes that Harness uses.If both ports are taken on the chosen node, the deploy fails with
Requested reserved port range not available on the chosen node(s).Network access
The runner must reach the Orka API and TCP ports 9079 and 9080 on every node it deploys to. Orka maps ports and NATs traffic to the VM, but it doesn’t provide public ingress to VMs.- Hosted by MacStadium
- Self-managed (on-premises)
- Run the Delegate and runner where they can reach your Orka network (recommended). Connect your network to MacStadium with a site-to-site VPN, or run the runner in a cloud you’ve connected. Nothing is exposed to the internet.
- Public IP addresses. For a small environment, you can map public IP addresses to the Orka API and the nodes on your firewall, and allow only Harness’s addresses. See Allow specific IPs to access MacStadium via the internet. This doesn’t scale well as you add nodes.
- A tunnel you run. Tools such as Tailscale, Cloudflare Tunnel, or ngrok can give the runner a path to the VMs without a VPN client. You set up and support these yourself.
Troubleshooting
- The runner can’t find the namespace. The namespace in
pool.ymldoesn’t exist. Orka namespace names start withorka-. See Choose a namespace. - Different images or VM configurations for different builds. Define one pool per image or VM config in
pool.yml, then choose the pool by name in each Build stage. Each stage uses one pool. - A deploy fails with
Requested reserved port range not available on the chosen node(s).Ports 9079 and 9080 are both taken on the node, usually because it’s already running 2 VMs. See Plan the port mapping. - Choosing a Delegate per pipeline or stage. If you run more than one Delegate and runner, for example one per Orka cluster, and want to pick one for each pipeline or stage, Harness’s delegate selectors for VM build infrastructure are behind a feature flag. Ask Harness Support to enable
CI_ENABLE_VM_DELEGATE_SELECTORon your account. With a single Delegate and runner, you don’t need it.

