Docs

Register your runner in 10 minutes

Your MacRun box is a standard self-hosted GitHub Actions runner. Keep your pipeline and change two lines of YAML.

01

Connect to your machine

Your machine sits on a private Tailscale network rather than the public internet, so there is no open SSH port to find and nothing to harden. Getting in takes two things, once.

Install Tailscale from tailscale.com/download and sign in. It is free for personal use and for the account sizes most teams need here, and it runs on macOS, Linux and Windows. Then accept the share invite we send when your machine is ready, which gives you access to that one machine and nothing else on our network.

Your portal shows the exact command, with your machine's address filled in:

ssh runner@100.x.x.x

There is no password or key to manage: Tailscale handles authentication. If your Tailscale account uses a different email than your billing address, request a share for it in your portal.

Your CI jobs do not need Tailscale. GitHub Actions reaches the runner through GitHub's own outbound connection, so this is only for the times you want a shell on the box.

02

Open the screen, when you need it

SSH covers CI. For the times a log is not enough, the same machine is reachable by screen sharing over the same private network, so Instruments, the Simulator and Xcode's UI work as they would locally. Your portal shows the address, the user runner, and a password unique to your lease.

On a Mac, open Finder, then Go → Connect to Server (⌘K):

vnc://100.x.x.x

On Windows, install RealVNC Viewer or TightVNC and connect to 100.x.x.x:5900. On Linux, Remmina and TigerVNC both work, same address. If your client asks only for a password, leave the username blank.

This is the part most CI services cannot do. A hosted runner gives you logs and nothing else, so a crash that only reproduces under Instruments is a crash you cannot investigate.

03

Get a registration token from GitHub

In your repo (or org) go to Settings → Actions → Runners → New runner. GitHub shows a one-time token. You'll paste it into the command below. Org-level runners are shared across all repos in the org.

04

Register the runner on your box

SSH in as above, then run the configure command from your portal (it pre-fills your unit's label):

cd ~/actions-runner
./config.sh --url https://github.com/YOUR-ORG/YOUR-REPO \
  --token <RUNNER_TOKEN> \
  --labels self-hosted,macOS,macrun-unit-01 \
  --unattended

# start it as a service (survives reboots)
./svc.sh install && ./svc.sh start

The runner-agent daemon keeps this service alive automatically. If it crashes, it's restarted within 30 seconds.

05

Change two lines of YAML

Point your workflow at the runner. That's the whole diff:

 jobs:
   build:
-    runs-on: macos-latest
+    runs-on: [self-hosted, macOS, macrun-unit-01]

Everything else in your pipeline stays exactly the same.

06

Xcode versions

Recent Xcode releases are preinstalled and pinned via xcodes. Select one in your job, or request a new version from your portal (usually same-day):

- run: sudo xcodes select 26.6
- run: xcodebuild -version
07

Caches are already warm

Because the machine is yours, caches persist between runs on local disk, so there is no re-download tax. Common paths:

~/Library/Developer/Xcode/DerivedData   # build cache
~/Library/Caches/CocoaPods              # pods
~/.gradle  ~/.npm  ~/.gem               # toolchain caches
~/Library/Caches/org.swift.swiftpm      # SwiftPM

You can still use actions/cache if you want deterministic restore keys, but for most iOS builds the warm local disk is the win.

08

Manage your machine

Reboot, request Xcode versions, and manage billing from your portal. Need something else? Reply to any MacRun email and a human answers.