Build setup guide

Connect your node to the pipeline

Your team has a dedicated physical Mac. First verify access, then pin your toolchain and register a runner. Use this checklist for your first 30 minutes. Dependency downloads and full builds will take longer, depending on your project.

No node yet? Apple Silicon M4 / M4 Pro, dedicated physical machine, not a virtual machine. From $20.1/day.

Getting started · Recommended first steps

Verify you can reconnect to the node

Before registering automation jobs, keep one working graphical connection and verify SSH. Don’t disable password login until you’ve confirmed another way to connect.

  1. 01

    Get your connection details

    Sign in to the console, open the relevant instance, and check the node ID, address, username and connection instructions. View credentials only in your account; don’t paste them into tickets, pipeline configuration or repositories.

  2. 02

    Open the desktop and change the password

    Open the browser-based remote desktop from the instance details and confirm you’re viewing this instance’s macOS environment. Change the system user’s password after your first login, save it in your team’s password manager, and assign owners for renewals and credential rotation.

  3. 03

    Configure Remote Login

    In macOS System Settings, check Remote Login under Sharing and allow only the users who need access. Connect using the address and port shown in the console. If the port isn’t the default, specify it in the ssh command.

  4. 04

    Verify key-based login

    Generate a dedicated SSH key on your workstation and add only the public key to the node’s authorized_keys. Keep your current session open, then use a separate terminal to confirm key-based login works before changing other authentication settings.

Check permissions on the node

mkdir -p ~/.ssh
chmod 700 ~/.ssh
chmod 600 ~/.ssh/authorized_keys
whoami
sw_vers
uname -m

Check that the username matches the instance credentials, the macOS version meets your project requirements, and the architecture on Apple Silicon is arm64. On your first SSH connection, verify the host identity when prompted about its fingerprint. Don’t disable host key checking just to connect.

After connecting · Run these commands first

Get the command line working before CI

This is an example of the output format, not a record from your node. The sample project is named TeamApp. Replace the workspace, scheme and signing configuration with those in your repository.

glide-m4 — ssh
$ ssh "$NODE_USER@$NODE_ADDRESS"
Authenticated using "publickey".
$ uname -m
arm64

$ xcodebuild -workspace TeamApp.xcworkspace \
  -scheme TeamApp -configuration Release \
  -destination 'generic/platform=iOS' \
  -archivePath build/TeamApp.xcarchive archive
** ARCHIVE SUCCEEDED **

$ bundle exec fastlane gym --scheme TeamApp
Successfully exported and compressed dSYM file
Successfully exported and compressed ipa file
Successfully generated ipa file:
build/TeamApp.ipa

A successful SSH connection doesn’t mean the environment is ready

Once SSH works, check Ruby, Bundler and your project dependencies. Prefer the versions pinned in your repository; a global upgrade command could change the build environment for the whole team.

Ready when: the same user can access the repository and install its dependencies.

Check archiving and exporting separately

If archiving succeeds but IPA export fails, first check the export method, signing certificate and provisioning profile. Keep the first error and its context; don’t capture only the final failure message.

Ready when: the target path contains a build artifact for downstream jobs.

Automation setup · Connect your team repository

Use clear labels to send jobs to this Mac

The node is a dedicated physical machine, but parallel builds still depend on memory, disk space and job isolation. Verify the full workflow with one build first, then increase concurrency.

GitHub Actions self-hosted runner

Add a self-hosted runner in your repository or organization’s Actions settings, then select macOS and ARM64. Follow the download, verification and registration commands provided there. Don’t use old installers from untrusted sources.

Register the runner under a dedicated system user and add labels such as vmfly,ios-build . Set the workflow’s runs-on to the matching labels so jobs don’t keep running in a shared environment.

runs-on: [self-hosted, macOS, ARM64, vmfly, ios-build]

Ready when: the runner appears online in the management page and accepts a manually triggered job.

GitLab Runner

Use a Runner version compatible with your GitLab environment, and get an authentication token by following the project or group runner setup flow. On macOS, use the shell executor and label the node macos-arm64 and your use-case labels.

Specify the same tags in pipeline jobs. Make sure the Runner working directory belongs to the user running it. That same user should be able to access certificates, dependency caches and build artifacts, so a successful interactive run doesn’t mask a failing automated job.

ios_archive:
  tags:
    - macos-arm64
    - ios-build
  script:
    - bundle exec fastlane gym

Ready when: a test job can report the system architecture and access the toolchain your project needs.

Include restart recovery in your checks

From the GitHub runner registration directory, run its service script: ./svc.sh install and ./svc.sh start. For GitLab Runner, use the commands for your installation method: gitlab-runner install and gitlab-runner start. Don’t set up two auto-start mechanisms for the same runner.

On macOS, a service running as a user LaunchAgent typically depends on that user’s login session. Check the service’s generated configuration and runtime identity; a machine starting up doesn’t mean the build user is logged in. When no release job is running, test that the runner comes back online after a restart and can access its paths and Keychain and export artifacts.

Keep signing assets within controlled access

Provide build certificates and provisioning profiles through a security method approved by your team. A certificate must include its corresponding private key to sign builds. Store unlock passwords and automation tokens in protected CI variables, and restrict which branches and jobs can use them.

If your team uses fastlane match, follow your existing storage and access policies. When CI reads existing signing assets, prefer read-only mode. Before troubleshooting the archive command, check that the bundle identifier, team, export method and provisioning profile validity period all match.

Unattended jobs must be able to access the designated Keychain. Don’t put long-lived plaintext passwords in scripts or print all environment variables in logs. Remove private keys, tokens, passwords and signing assets before sharing logs.

Toolchain checks · Reproducible versions

Pin the Xcode path and manage caches separately

Check the node’s current environment before deciding whether to install the version your project needs. Don’t assume the Xcode selected in the desktop session is the one used by the runner process.

Check the current selection; replace the path with the actual installation directory before switching

xcodebuild -version
xcode-select -p
xcrun simctl list runtimes

sudo xcode-select --switch /Applications/Xcode.app/Contents/Developer
xcodebuild -checkFirstLaunchStatus

Multiple Xcode versions

Give each Xcode app a recognizable filename. If projects on a shared node need different versions, set DEVELOPER_DIRin each job instead of changing the system-wide selection before every build.

Ready when: the runner’s actual job log shows xcodebuild -versionand the version matches your project requirements.

Simulator runtimes

Install the runtimes your project needs in Xcode Settings. Then use xcrun simctl list to check which devices are available. Specify a destination for UI tests so jobs don’t wait for a runtime or device that isn’t installed.

Ready when: you can start the target simulator on its own and run a minimal set of UI tests.

DerivedData & build artifacts

Give each project its own DerivedData path, keep only the caches you need and set an artifact retention policy. Stop related builds before cleaning. Check the directory contents and disk usage first; don’t recursively delete a shared working directory.

Ready when: dependencies, caches and IPAs each have a dedicated directory, with enough disk space for the next archive.

Install Xcode’s first-launch components before connecting it to automation. If commands work in an interactive terminal but CI can’t find them, compare the runtime user, PATH, working directory and shell initialization rather than reinstalling all dependencies.

Graphical access · Keep a backup way to connect

Choose a connection method for the task

Use the browser desktop for initial setup, a client connection for longer graphical sessions, and SSH with a runner for unattended builds. Don’t rely on any of the three graphical options as the only place to keep code and artifacts.

These are suggested starting settings, not guarantees of network latency or display performance.
Connection method Best for Starting setup What to check if it lags
Browser remote desktop First login, system settings and a quick look at a build in progress Open from the instance details in the console; start with one display at a moderate resolution Local network, browser zoom and whether multiple desktop sessions are open
VNC client Longer graphical sessions and adjusting encoding or image quality Configure as instructed for your instance; start with automatic encoding or balanced image quality Lower image quality or color depth gradually; avoid changing several settings at once
macOS Screen Sharing Desktop debugging and assistance from a local Mac Use a supported connection method for your instance; start with one 1920 × 1080 display High resolution, motion and cross-network connections; lower the resolution first and compare

Track desktop lag and build speed separately

A choppy desktop doesn’t mean compilation is slower. Check job output and resource usage over SSH to see whether the build is still progressing. Likewise, a responsive desktop doesn’t prove that signing, dependency downloads or access to a remote repository are working.

If you have connection issues, note how you connected, when they occurred and the time zone, your local network type, and whether SSH still works. When changing Remote Login or Screen Sharing settings, keep an existing working session open so you don’t lose every way to connect.

Manage your subscription · Check the order first

Keep billing changes in sync with your build schedule

Manage your account, instance and billing in the console. Check the order ID and instance ID before renewing or changing your configuration, and don’t schedule a release after your confirmed rental period ends.

Renewals & expiration

Check your subscription, expiration date and outstanding invoices in the console. After paying, confirm the subscription status. Before expiration, move your code, certificate backups and build artifacts to a team-controlled location; don’t rely on an expiring node for long-term backups.

When a node expires without renewal, service stops and the entire disk is erased. Move any data you need in advance.

Plan changes & storage

Glide M4 includes Apple Silicon M4, 16 GB memory and a 256 GB SSD. Cruise M4 Pro includes Apple Silicon M4 Pro, 64 GB memory and a 2 TB SSD. Contact support through a ticket before changing plans; this isn’t an instant memory upgrade on your existing machine.

Check the +1 TB SSD, +2 TB SSD and Thunderbolt 5 expansion options in the order configuration. For changes to a rented node, submit a support ticket first.

Payment & processing checks

We accept only USDT-TRC20 and Visa / Mastercard / Amex (via Stripe). All prices are charged in USD. Available payment gateways depend on the response from the payment interface. Physical machine allocation starts only after payment is confirmed.

If your payment status hasn’t updated, send the order ID and proof of payment; for USDT, include the transaction hash. Don’t pay again or send your full card number.

Give the support team the details they need to investigate

If you have an account, submit and track a support ticket in the console. Include the node ID, time and time zone of the error, steps to reproduce it, and redacted log excerpts. For presales questions or if you can’t sign in, visit the contact page to reach support@vmfly.com.

Describe the expected and actual results, and note whether SSH, desktop access and the runner are still working. Don’t include passwords, private keys or full payment card details.