Connect first, then migrate

Connect to your Cloud Mac in minutes

Run commands over SSH and use the macOS desktop over VNC. Get a dedicated physical machine, not a virtual one. Migrate your source, toolchain, and CI in stages—without carrying local environment problems over with them.

If you have your delivery details and SSH public key, follow the steps below to connect. Allow extra time to set up the toolchain; that isn't part of the connection steps.

Connect over SSH first; everything else uses this connection

Prepare your local terminal, SSH public key, and host details from the console. Replace HOSTwithPORTandUSER the delivered host address, SSH port, and username, respectively. Don't copy the examples as-is.

01 · Prepare locally

Add your public key; never upload your private key

You can use an existing dedicated key. Otherwise, generate an Ed25519 key pair on your computer, set a passphrase, then add the contents of the .pub file to the SSH public key settings for your instance in the console.

ssh-keygen -t ed25519 \
  -f ~/.ssh/osxbuild_ed25519

cat ~/.ssh/osxbuild_ed25519.pub

Keep your private key on your computer. Never paste it into a support ticket, email, or code repository. After uploading, follow the console prompts to confirm the public key is applied to the target instance.

02 · Verify delivery details

Connect directly using the delivered port

Get the connection details from the instance page in the console. The first time you're asked to verify a host fingerprint, compare it with the delivery details. If you can't verify it, submit a support ticket—don't disable host verification to skip the prompt.

ssh -i ~/.ssh/osxbuild_ed25519 \
  -p PORT USER@HOST

sw_vers
uname -m
xcodebuild -version

Check the OS, architecture, and Xcode version first. If the last command reports that the toolchain isn't ready, finish installing it and selecting the active version before connecting build jobs.

03 · Set up a shortcut

Give the machine a local alias

Add the following to your local ~/.ssh/config. The example alias is bake. Reuse it for the sync, tunnel, and troubleshooting commands below, so you don't have to enter the host and port each time.

Host bake
  HostName HOST
  Port SSH_PORT
  User SSH_USER
  IdentityFile ~/.ssh/osxbuild_ed25519
  IdentitiesOnly yes
  ServerAliveInterval 30
  ServerAliveCountMax 3

Save the file, then run ssh bake. Keepalive settings help detect a stale connection; they don't reconnect the network or resume terminal jobs.

Use VNC for the desktop, through an SSH tunnel

Open the desktop when you need to configure Xcode, check Keychain, or use the simulator. First confirm the VNC connection details provided in the console. Don't assume the default port is the right one for your machine.

Choose a client you know

On macOS, use Screen Sharing. On Windows or Linux, use a VNC client such as TigerVNC. If you need to install a client, get it from its official distribution channel and confirm it supports the authentication method used by the service.

Reduce bandwidth before adjusting image quality

Start with 1440 × 900 or 1600 × 1000 for the desktop resolution; you don't need to fill a high-resolution display. If available, try 24-bit color first, then 16-bit if your network is constrained. Options depend on what the client and server support.

Terminal builds and the remote desktop are two separate ways to work. If desktop interactions feel sluggish, keep building over SSH and retrieve the logs and IPA without relying on screen refreshes for the whole pipeline.

Forward only the desktop port to your local machine

Run the command below locally and leave the terminal open. ReplaceVNC_PORT with the server port provided to you. The example's 15900 is a local port; you can use any unused port instead.

ssh -N \
  -L 127.0.0.1:15900:127.0.0.1:VNC_PORT \
  -o ExitOnForwardFailure=yes \
  bake

Then enter 127.0.0.1in the VNC client's address field and 15900in its port field. If the client has a single address field, use the format specified in its documentation.

VNC still uses the desktop credentials provided to you; your SSH key does not replace the desktop password. When you're done, quit the client, then press Ctrl + C to close the tunnel.

Can't connect to the desktop? Check each part of the connection path
Symptom Check first Next step
Can't open the local port Whether SSH is connected and whether the local port is already in use Try another local port and keep any error message shown in the tunnel terminal
Tunnel is up, but the desktop connection is refused The delivered VNC port and whether the service is listening Check the instance details; don't expose the desktop port to the public internet
Connection fails after authentication starts Desktop username and password, and client compatibility with the authentication method Check the credentials you received; don't use your SSH private key as a VNC password
Logged in, but the screen updates slowly Resolution, color depth, local network, and distance to the server location Reduce the amount of screen data sent and continue any headless builds over SSH

Migrate in three stages, not by copying the entire disk

Move your data first, align the toolchain next, then connect CI. Verify each step. Get one clean archive working before restoring caches and automation.

Stage 1 · Data

Sync source; rebuild temporary artifacts

Clone the project with Git, or use rsync to sync your local working directory and any resources outside the repository. For the first sync, exclude DerivedData and old build directories. Don't mix signing private keys into a routine file sync.

rsync -az --progress \
  --exclude='DerivedData/' \
  --exclude='build/' \
  --exclude='*.p12' \
  --exclude='*.mobileprovision' \
  ./ bake:~/project/

Verify: Confirm the destination directory, commit, and required resources match. The example doesn't include a delete option, so it won't accidentally remove remote files on the first sync. A successful sync isn't a backup.

Stage 2 · Toolchain

Align versions, then restore dependencies

Install or select Xcode as needed for your project, then configure Homebrew. Restore CocoaPods from the lockfile and re-resolve SPM dependencies. Caches must match the toolchain and dependency versions; don't reuse directories from unknown sources.

xcode-select -p
xcodebuild -version
brew --version

bundle install
bundle exec pod install

Verify: Versions match your local baseline and dependencies resolve. Run the last two commands only for CocoaPods projects. Import signing certificates into Keychain separately through a controlled channel, and check their validity and provisioning profile match.

Stage 3 · CI

Register a runner; add distribution last

Register a dedicated runner in GitHub Actions or GitLab Runner. First check the versions, then run your project's Fastlane lane. Verify archiving and export before adding an upload step.

xcodebuild -list \
  -workspace App.xcworkspace

bundle exec fastlane ios build

Verify: Logs identify the commit, Scheme, and artifact path. Replace the example workspace and lane names with those used by your project. Authorize release credentials separately; don't distribute them with the source code.

Connect CI and make sure jobs run on this machine

A self-hosted runner uses the physical machine you've rented. Use labels for routing and credentials for authorization; don't mix them up. Get one job working before evaluating concurrency and disk usage.

GitHub Actions: target the build machine with a dedicated label

Follow the instructions in your repository or organization settings to register a self-hosted runner and add the custom label osxbuild. The workflow below checks the toolchain and creates an archive. It doesn't inject signing assets, export an IPA, or distribute the build.

name: iOS archive
on:
  workflow_dispatch:

permissions:
  contents: read

concurrency:
  group: ios-${{ github.ref }}
  cancel-in-progress: false

jobs:
  archive:
    runs-on: [self-hosted, macOS, ARM64, osxbuild]
    steps:
      - uses: actions/checkout@v4
      - name: Check Xcode
        run: xcodebuild -version
      - name: Archive
        run: |
          xcodebuild \
            -workspace App.xcworkspace \
            -scheme App \
            -configuration Release \
            -archivePath "$RUNNER_TEMP/App.xcarchive" \
            archive

Replace the workspace and Scheme, and make sure the Scheme is shared. Only trusted repositories and workflows should use a runner that holds signing assets. Different branches get different concurrency groups, but you still need to prevent jobs from conflicting over shared build directories.

Jenkins: launch a dedicated agent over SSH

In Jenkins, add a permanent node, set a dedicated build directory as the remote root, and use the label osxbuild-mac. Choose to launch the agent over SSH, enter the delivered host and port, and manage the private key in the Jenkins credentials store.

pipeline {
  agent { label 'osxbuild-mac' }

  stages {
    stage('Checkout') {
      steps {
        checkout scm
      }
    }
    stage('Toolchain') {
      steps {
        sh 'xcodebuild -version'
      }
    }
    stage('Build') {
      steps {
        sh 'bundle exec fastlane ios build'
      }
    }
  }
}

Check that the agent's required Java version is available, the SSH credentials work, and the host fingerprint has been verified. Non-interactive environments launched over SSH may not load your local shell configuration, so configure the paths for Homebrew, Ruby, and Fastlane explicitly.

Connect GitLab Runner in the same order: register the runner, limit it to trusted projects, set project tags, then verify the environment with a version-check job. Test the requirements for any tests that need a graphical session separately first.

Start with one executor. Before increasing concurrency, check peak memory use, simulator count, and DerivedData paths. Don't let multiple jobs write to the same archive directory.

Six locations: choose based on who will use the machine

If you use the desktop often, compare the connection from your team to each location. For CI-heavy workloads, consider the paths for source code, dependencies, and artifact uploads. Distance is only a starting point; your carrier, routing, and local network also affect performance.

Singapore

SG · UTC+8

For teams working across Southeast Asian time zones. If you use Xcode remotely throughout the day, compare the connection from your location to this one first.

Choose Singapore

Tokyo

JP · UTC+9

For teams working across East Asian time zones. Run interactive development by day and archiving overnight on the same machine to simplify handoffs.

Choose Tokyo

Seoul

KR · UTC+9

For teams working across Northeast Asian time zones. If you use the remote desktop frequently, test screen refresh and input response before settling on a team connection point.

Choose Seoul

Hong Kong

HK · UTC+8

For teams working across South China and Southeast Asian time zones. Check dependency downloads and artifact uploads as well as desktop responsiveness; don't judge performance by a single successful connection.

Choose Hong Kong

US East

US-E · UTC−5 / −4

For teams working across eastern North America and western Europe. Set an explicit time zone for nightly builds and account for local time changes due to daylight saving time.

Choose US East

US West

US-W · UTC−8 / −7

For teams working across western North America. Align build windows with local workdays; for cross-time-zone handoffs, include clear timestamps in logs.

Choose US West

Both machine plans are available in all six locations. Availability is reported in real time by the console. Machines run continuously, 365 days a year; assess local network outages and SSH disconnections separately from machine status.

Once connected, tighten access and protect signing assets

Keep a verified connection open before changing access settings. Make one change at a time, confirm the new connection works, then close the old session. This helps prevent locking yourself out.

  1. 01

    Verify key access, then disable password login

    Open a second terminal and confirm you can log in with the dedicated key. Then disable password authentication using the system's SSH configuration. Check the syntax and confirm you have a way back in before changing anything. If you're unsure about system settings, submit a support ticket to check first.

  2. 02

    Keep only the ports you need

    Limit remote login and service access to what you actually use. Route VNC through an SSH tunnel whenever possible. Don't expose debugging services, build control interfaces, or temporary file servers directly to the public internet; check both the listening address and access controls.

  3. 03

    Use separate keys for each person and purpose

    Use different keys for human logins and CI. Revoke old access immediately when someone leaves or a credential may have been compromised. When rotating keys, add and verify the new public key first, then remove the old one and update your runners and team handoff notes.

  4. 04

    Keep signing assets out of routine logs

    Unlock Keychain only when a build needs it, then restrict access again. Inject API keys, certificate passphrases, and match decryption credentials through a secrets system. Check that scripts don't echo sensitive variables, and never store private key files in the repository.

  5. 05

    Retrieve artifacts and configuration before your term ends

    Sync any source, IPA files, archives, and pipeline configuration you need to keep to storage controlled by your team, then verify the files are readable. At the end of the rental term, the machine is reclaimed, including disk erasure and system reinstallation. Don't treat its local directories as your only copy.

When troubleshooting, a concise handoff is enough.Include the order number, location, error time and time zone, and the last 50 lines of redacted logs in your support ticket. Never send private keys, certificate passphrases, or account passwords. For connection issues, contact us through a console support ticket or at support@osxbuild.com .

Set up your connection, then plan your next archive

Already have a machine? Check the delivery details in the console. Still choosing a configuration? Start with one of two dedicated Cloud Mac plans, choose a machine based on your build workload, then select a location that works for your team.