The Runner shows online, but production jobs still cannot be switched safely.
Fastest fix: migrate old launch-agent nodes to CircleCI Machine Runner 3 through an isolated pilot, parallel validation, and staged production cutover—not a full in-place replacement.
This guide is for platform engineers maintaining CircleCI macOS self-hosted nodes, IT leaders protecting code signing and private-network access, and technical directors deciding between existing Macs, isolated build nodes, and elastic remote Mac capacity.
Last updated August 21, 2026. The migration guidance and configuration claims below were checked against the official macOS migration guide, installation guide, configuration reference, policy documentation, and CircleCI Runner changelog.
00Start with the failure domains, not the installation command
CircleCI lists Machine Runner 3 as the replacement path for the older launch agent. That does not make a configuration file, service process, or build environment automatically equivalent. A node can report as connected while using the wrong resource class, accepting an unintended project, leaving signing material behind, or failing to recover after a restart. The Runner overview and migration documentation should be treated as the migration baseline, not as a substitute for acceptance testing.
The migration decision should therefore separate the following failure domains:
| Failure domain | What can appear healthy | What must be proven |
|---|---|---|
| Service lifecycle | Machine Runner 3 starts once | The old launch agent is stopped, removed, and cannot reclaim tasks |
| Configuration behavior | The file loads without a syntax error | Paths, permissions, cleanup, prefixes, mode, and task behavior match policy |
| Task routing | The Runner appears in the expected resource class | Allowed projects reach the pilot and unapproved projects are rejected |
| Credential handling | A signed build succeeds | Signing keys, profiles, checkout credentials, and temporary keychains do not persist |
| Recovery | The node is reachable before a test | Restart, process exit, network interruption, and timeout behavior are documented |
A useful acceptance record names the migration owner, rollback owner, pilot host, dependent pipelines, maintenance window, approved projects, private-network dependencies, signing responsibility, and fallback node. If any owner is missing, the migration is not ready for production cutover.
Is the old service really gone?
Old service remnants are a common source of ambiguous failures. The old launch agent may continue to start after a reboot, or it may use a different installation directory and configuration path from the new Runner. That can create a split-brain node: one process reports the expected identity while another process competes for work.
Use the official migration procedure to inspect and record:
- The old launch-agent service file and its loaded state.
- The old installation directory and configuration location.
- Running processes associated with the old service.
- The new Machine Runner 3 installation path.
- The exact binary source, package signature, notarization status, version, and installation log.
- The service account, file owner, group, and permissions for the configuration and working directories.
Do not install the new service first and “clean up later.” Stop the old service according to the official instructions, confirm that it is no longer loaded, and preserve the inspection output in the change record. Then install Machine Runner 3 using the current official macOS installation instructions.
Warning: If the pilot fails, the recovery choice must be explicit: restore the old service under its documented procedure, or route work to a standby node. Do not improvise two startup mechanisms on the production Mac during an incident.
01Check configuration semantics before moving any workload
A configuration file that parses successfully proves only that the file can be read. It does not prove that the new service uses the same working directory, execution identity, cleanup behavior, task-agent cache, or command handling. Compare the existing file with the current Machine Runner 3 configuration reference field by field.
| Configuration area | Migration question | Acceptance evidence |
|---|---|---|
| Working directory | Does the path exist for the new service account? | Directory owner, mode, free-space policy, and test-job output |
| Cleanup behavior | Is cleanup enabled and effective after a task? | Before-and-after file inventory from isolated test jobs |
| Runner mode | Does the selected mode match the pipeline’s execution model? | Resource-class mapping and successful baseline task |
| Command handling | Are prefixes and shell assumptions preserved? | Log output, exit code, and command trace from a safe test |
| Maximum task duration | Does the configured limit match the workload policy? | Timeout test and documented recovery action |
| Task-agent cache | Can cached data cross trust boundaries? | Cache inventory, ownership, and cross-project read test |
| Environment variables | Are paths and secrets injected by the same mechanism? | Sanitized environment review and log inspection |
Pay particular attention to path substitutions and environment variables that were implicit under the old launch agent. A service started with a different user or working directory can still reach the Runner control plane while failing at checkout, dependency installation, signing, or artifact upload.
The baseline job should contain no production credentials. It should prove checkout, tool discovery, a representative build command, log collection, exit-code propagation, and artifact return. If the pipeline requires private network access, the pilot must test that access without copying production signing secrets into the trial environment.
Can the existing config.yaml be reused?
The safe answer is conditional: reuse the configuration only after comparing every supported field against the current Machine Runner 3 reference and validating its runtime behavior. The official migration material may describe compatibility, but compatibility is not proof that old paths, permissions, environment assumptions, or task-agent behavior remain suitable.
Create a reviewed copy of the existing configuration. Mark every field as one of the following:
- Retained unchanged and validated.
- Retained with a documented value change.
- Removed because it is obsolete or unsupported.
- Replaced by a service, policy, or operating-system setting.
- Not applicable to the pilot and deferred with an owner.
Never place the Runner authentication token in a repository, shared script, build output, or diagnostic bundle. Store it through the approved secret-management path, restrict file access to the service account, and assign a named owner for rotation. The self-hosted Runner configuration policy documentation should guide organization-level restrictions, especially where multiple project trust levels share an infrastructure estate.
02Validate routing and permissions before signing anything
A migration becomes a security incident when an untrusted project can reach a Mac that holds release credentials. Resource class, namespace, project configuration, and authentication tokens must be tested as one routing system.
The pilot should demonstrate all of the following:
- An approved release pipeline reaches the intended Machine Runner 3 node.
- An approved non-release test pipeline reaches only the resource class assigned to it.
- An unapproved project is rejected or routed elsewhere.
- The Runner token is absent from repository content and build logs.
- The resource-class mapping is documented in the change record.
- Private network access is available only where the project requires it.
- The person responsible for token rotation is identified.
This is where organization-level policy matters more than a local shell test. A local configuration can appear correct while a project-level setting sends work to the wrong node. Use an allowlist model for macOS resource classes, then review the policy whenever a project is added, removed, or moved between trust domains.
| Project type | Recommended node policy | Evidence to collect |
|---|---|---|
| Release and signing pipeline | Dedicated resource class and service account | Successful signed baseline, access policy, credential inventory |
| Internal application testing | Separate resource class where feasible | Routing result and workspace-cleanup result |
| Untrusted or experimental code | No access to production signing nodes | Rejection or alternate-route evidence |
| Maintenance and diagnostics | Restricted operator access | Audit record and temporary access expiry |
How should a self-hosted Mac Runner be checked for residue?
Use separate test projects with non-production markers and deliberately different identifiers. Run one job that creates files, environment markers, checkout material, temporary Keychain data, provisioning profiles, and build artifacts. After the job finishes, run the next isolated job and attempt to detect those markers through the filesystem, environment, caches, logs, and available keychain interfaces.
The second job must not be able to read the first job’s source, environment values, SSH checkout key, signing profile, certificate, temporary keychain, or output artifact. Check both the normal completion path and failure paths, because cleanup often breaks when a task is interrupted or times out.
Review these locations and mechanisms:
- Working directory and nested build directories.
- Dependency and task-agent caches.
- SSH checkout keys and known-host material.
- Temporary Keychain files and unlocked keychains.
- Provisioning Profiles and signing certificates.
- Derived data, archives, logs, and exported packages.
- Shell history, diagnostic output, and process arguments.
A successful signed build is not sufficient evidence of isolation. For production signing, the safer default is a dedicated service account and dedicated resource class. General test workloads should not enter the same trust domain merely because the Mac has spare capacity.
03Run recovery tests before approving the node
Recovery testing should answer whether the node returns to a safe state, not merely whether a process can be started manually. Execute the tests against the pilot while the original production path remains available.
| Test condition | Expected result | Rollback or escalation trigger |
|---|---|---|
| Normal remote restart | Service starts through the approved mechanism and resumes intended routing | Manual startup is required or routing changes unexpectedly |
| Runner process exit | Process recovery follows the documented service behavior | Duplicate processes appear or tasks remain ambiguous |
| Short network interruption | In-flight behavior and later task acceptance are recorded | A job is duplicated, lost, or falsely reported successful |
| Task timeout | Timeout is visible and workspace cleanup still runs | Credentials or source remain accessible |
| Host maintenance | Node returns with the same identity and policy | A new identity receives production work unexpectedly |
The migration owner should record queue state, task outcome, failure reason, logs, and manual recovery actions for each test. Do not publish performance figures from a generic assumption. Capacity evidence must come from the team’s real baseline pipeline on the intended host.
For iOS CI/CD, the baseline should represent the actual dependency installation, Xcode selection, compilation, test, signing, archive, and artifact-upload path used by the team. The test should also verify that a restart cannot cause duplicate publication or a second signing action. If the pipeline has external release side effects, use a non-publishing destination for the pilot.
When should a node be accepted, limited, or rejected?
Use this decision list instead of relying on a single green build:
- Choose full production cutover if the old service is removed, configuration behavior is validated, routing is restricted, residue checks pass, recovery is repeatable, and rollback can be executed without editing production files under pressure.
- Choose limited rollout if the baseline works but capacity, restart evidence, or cleanup evidence is incomplete. Keep release signing on the existing protected path until the missing evidence is closed.
- Return to remediation if the new and old services compete, the token appears in logs, an unapproved project reaches the node, credentials survive cleanup, or a recovery test causes duplicate work.
- Use a standby or isolated remote Mac if the current host is the only production build path and the migration cannot be tested without removing its fallback.
- Delay migration if the team cannot identify a rollback owner, cannot preserve private-network controls, or cannot reproduce the signing environment in the pilot.
04Build the rollout around evidence and capacity
After the pilot passes, migrate production nodes in small batches. Keep at least one known-good execution path until the new path has completed the team’s representative release workload and the change record contains the required evidence. The exact batch size should depend on the number of independent build paths and the organization’s release SLA, not on a universal rule.
Capacity planning also belongs in the acceptance decision. A fixed Mac may be sufficient when the queue is predictable and release demand is stable. An additional isolated node is more appropriate when signing workloads must be separated from ordinary tests. Elastic remote Mac capacity can be useful when demand is seasonal, a pilot must not disturb production, or the team needs a temporary Machine Runner 3 environment before committing to more hardware.
NUKCLOUD can provide a remote Mac as an isolated test target through available remote Mac options. The right use is not to conceal an unresolved migration problem. It is to give the team a separate host where service replacement, resource-class routing, credential cleanup, and reboot recovery can be tested before altering the only production Mac.
For teams comparing fixed hardware with remote capacity, assess the complete operating burden:
- Hardware purchase and depreciation.
- Spare equipment and replacement handling.
- macOS and toolchain maintenance ownership.
- Data-center or office power and network dependencies.
- Physical access during a failed reboot.
- Security review for signing material.
- Queue growth during releases.
- Temporary capacity for pilots and incident recovery.
A purchase can be sensible for long-lived, predictable, high-utilization workloads that require physical interfaces or tightly controlled local hardware. A rental is less suitable when the team needs custom peripherals, uninterrupted local access, or a stable host for a sustained heavy workload without changing infrastructure. It is more attractive when the immediate decision is to create a disposable, isolated acceptance environment or add capacity without buying another Mac.
05Record the final acceptance decision
The final record should contain the old-service inspection, installation source, configuration diff, service identity, resource-class policy, token ownership, cleanup evidence, signing test result, restart logs, network interruption result, timeout result, queue observations, and rollback procedure.
The decision should be written as one of three outcomes:
- Passed: approved for the defined production scope.
- Limited rollout: approved only for named projects or workloads while evidence gaps remain.
- Rejected for remediation: not permitted to receive production work until the stated failures are corrected.
A Runner that merely appears online has not passed this checklist. Machine Runner 3 is ready only when the team can explain who may use the Mac, what remains after a task, how the node recovers, and how production work is restored if the migration fails.
For a team currently relying on a single physical Mac, direct replacement leaves several weaknesses: it creates a narrow rollback path, ties pilot work to production availability, and makes capacity expansion dependent on another hardware purchase. Renting an isolated Mac from NUKCLOUD can provide a cleaner trial boundary for the migration; after the evidence is complete, the team can decide whether the node should remain temporary, become a standby target, or supplement fixed production capacity through the NUKCLOUD remote Mac service.