
If your daily driver is a Linux terminal and you need to add an iOS target, you need a macOS machine for the Xcode step. Renting one keeps your existing editor, shell, and scripts in place: you SSH to the Mac, run xcodebuild, and pipe the output back. This guide gives you the SSH config, the aliases, and the session-keeping script to make that feel native.
Linux has no substitute for Apple's SDKs. A Mac host is required for:
The useful shape for a Linux developer is: keep your project on Linux, reach the Mac only when the iOS lane runs, and treat it as an appliance for build, test, and sign.
| Scenario | Plan | Price |
|---|---|---|
| Command-line Intel Xcode builds, Simulator for supported iOS versions | Virtual Intel macOS | $29/mo |
| Apple silicon toolchain, ARM execution, visionOS, Xcode 27 | M-series Mac (request) | From $95/mo |
| One M-series with CI setup, backups, monitoring, 30 min support | Managed Build Mac | $249/mo |
| Two M-series, two runners, team setup, backups, monitoring, 1 h support | Managed Mac Team | $999/mo |
The $29 tier is a virtual Intel macOS environment (2 vCPU, 8 GiB RAM, 80 GiB disk) and runs compatible Intel Xcode toolchains. Apple's porting guide is explicit: Intel Macs must use Xcode 26 or an earlier release; Xcode 27 and ARM execution need an M-series host. Confirm the exact Xcode/macOS pair you want in the Xcode release notes.
Access to the $29 VM is through the browser-console desktop terminal; outbound CI agents on the VM can reach your GitHub/GitLab/Buildkite service. Inbound public SSH to the $29 VM is not currently exposed, so the interactive SSH workflow below targets an M-series Mac with SSH confirmed in your configuration quote. The $95 M-series entry price does not pin a chip, RAM, or disk; those are set in the quote. The i3 Mac at $49 and physical M-series plans collect requests until supply is confirmed.
Request a configuration at figment.io/mac-hosting.
Each fresh xcodebuild over SSH pays a TCP handshake and a key exchange. ControlMaster opens a master socket once; later connections reuse it, so repeated commands feel local. Add this to ~/.ssh/config on Linux:
Host figment-mac
HostName <mac-ip-or-hostname>
User macuser
IdentityFile ~/.ssh/id_ed25519
ControlMaster auto
ControlPath ~/.ssh/cm-%r@%h:%p
ControlPersist 600
ServerAliveInterval 60
ServerAliveCountMax 5
ControlPersist 600 keeps the master alive for ten minutes after the last session closes. Verify:
# First call opens the master socket
ssh figment-mac 'echo master socket open'
# Second call reuses the socket; should return almost immediately
ssh figment-mac 'xcodebuild -version'
To open the master explicitly before a long script and let later ssh figment-mac calls share it, use the same ControlPath as the config:
ssh -fN -M figment-mac
# Close when done:
ssh -O exit figment-mac
Define four per-project variables once, then use aliases that read like make and cargo:
# Project configuration
export FIGMENT_HOST="figment-mac"
export FIGMENT_PROJECT_DIR="~/MyApp"
export FIGMENT_SCHEME="MyApp" # replace with your scheme
export FIGMENT_SIM="platform=iOS Simulator,name=iPhone 16"
# Build
alias ios-build='ssh "$FIGMENT_HOST" \
"set -euo pipefail; cd $FIGMENT_PROJECT_DIR && \
xcodebuild -scheme \"$FIGMENT_SCHEME\" \
-destination \"$FIGMENT_SIM\" \
-configuration Debug build 2>&1"'
# Test
alias ios-test='ssh "$FIGMENT_HOST" \
"set -euo pipefail; cd $FIGMENT_PROJECT_DIR && \
xcodebuild -scheme \"$FIGMENT_SCHEME\" \
-destination \"$FIGMENT_SIM\" \
test 2>&1"'
# Clean
alias ios-clean='ssh "$FIGMENT_HOST" \
"set -e; cd $FIGMENT_PROJECT_DIR && xcodebuild clean"'
# Live simulator log, filtered locally
alias ios-log='ssh "$FIGMENT_HOST" \
"xcrun simctl spawn booted log stream --level debug" 2>&1 | \
rg --line-buffered "$FIGMENT_SCHEME"'
set -euo pipefail makes the remote shell exit non-zero on any failure, and SSH propagates that exit code back to your terminal so a wrapping CI job sees a real pass/fail. These are unexecuted examples for your own project; substitute your scheme and simulator.
Because each alias writes to local stdout, you can pipe through anything already on your Linux box:
# Errors and warnings only
ios-build | rg "error:|warning:"
# Full log and a tail at the same time
ios-build | tee ~/build.log | tail -40
# Count failed test cases
ios-test | rg "Test Case.*failed" | wc -l
To edit sources in your local Neovim or VS Code, mount the project with SSHFS; it reuses the active ControlMaster socket, so file operations do not pay a new handshake:
# Debian/Ubuntu: apt install sshfs
mkdir -p ~/mnt/figment-mac
sshfs macuser@figment-mac:/Users/macuser/MyApp ~/mnt/figment-mac
nvim ~/mnt/figment-mac/Sources/ContentView.swift
fusermount -u ~/mnt/figment-mac
Long builds and interactive lldb sessions should outlive your network. Start a named tmux session on the Mac and reconnect to it:
# Create if missing; harmless to run repeatedly
ssh figment-mac 'tmux new-session -d -s ios-build || true'
# Attach interactively
ssh -t figment-mac 'tmux attach-session -t ios-build'
An auto-reconnect wrapper for your Linux profile:
mac_shell() {
while true; do
ssh -t figment-mac \
'tmux attach-session -t ios-build 2>/dev/null || tmux new-session -s ios-build'
local code=$?
[[ $code -eq 0 ]] && break
echo "Connection lost (exit $code). Retrying in 5s..." >&2
sleep 5
done
}
Clean detach (Ctrl-b d) returns zero and exits; a dropped link returns non-zero and the loop reconnects.
The $29 virtual Intel macOS tier is the cheapest Figment entry for adding an iOS lane that is driven by a CI agent on the VM reporting outbound to GitHub, GitLab, or Buildkite. That path does not depend on inbound SSH. The interactive flow in this guide — ControlMaster, aliases, SSHFS, tmux — needs inbound SSH, so pair it with an M-series Mac from $95/mo and ask for SSH to be enabled in the quote. For teams who want the CI, backups, and monitoring handled, the Managed Build Mac at $249/mo covers one M-series host with 30 minutes of monthly support; the Managed Mac Team at $999/mo doubles the hardware and runners and includes one hour of monthly support.
Start a request at figment.io/mac-hosting/start.
Related guides: