Prerequisites

RequirementDetails
macOSmacOS 12 (Monterey) or later
XcodeXcode 12+ for iOS <17, Xcode 15+ for iOS 17.0–17.3, Xcode 15.3+ for iOS 17.4+
Apple Developer AccountPaid account ($99/year) — free accounts are too limited for ControlFloor
iOS DevicesiOS 14+, trusted/paired with the Mac, Developer Mode enabled (iOS 16+)
Device SettingsAuto-Lock set to "Never" (Settings → Display & Brightness → Auto-Lock)
KeyboardsFor keyboard automation: only two keyboards installed — one Western layout (e.g. English) and the Emoji keyboard
PythonPython 3.8+ for the Python API (optional, for scripting)

Step 1: Download and Install

Run the installer on each Mac that will host devices:

$ /bin/bash -c "$(curl -fsS https://controlfloor.com/dl/install.sh)"

This creates the ~/cf directory containing the server, provider, iOS apps, and utilities. If setup fails partway through, re-run:

$ cd ~/cf $ ./setup.sh

Step 2: Re-sign iOS Apps

ControlFloor includes three iOS apps that must be re-signed with your Apple Developer certificate before deploying to your devices. See the Signing Guide for full details.

Quick version:

# Unlock the keychain (you'll be prompted for your Mac password) $ security unlock # Set your signing identity and provisioning profile $ export CFA_SIGNING_IDENTITY="your-signing-identity-hash" $ export CFA_PROVISIONING_PROFILE="/path/to/your.mobileprovision" # Sign all iOS apps $ ./apps/Utils/sign_all.macos.sh ./apps/*.app

Step 3: Configure Server

Edit ~/cf/server/config.json:

{ "listen": ":8080", "https": true }

By default, the server generates a self-signed TLS certificate. For production use, you can provide your own certificates. See HTTPS Configuration below.

The admin password is set during the initial setup. You can change it later via the CLI (see User Management).

Step 4: Start Server

$ cd ~/cf/server $ ./cfserver run

The server starts and listens on the configured port. Access the web dashboard at https://localhost:8080 (or your server's hostname).

Step 5: Configure Provider

Edit ~/cf/provider/config.json:

{ "licenseKeys": ["your-license-key-here"], "controlfloor": { "host": "localhost:8080", "https": true, "selfSigned": true } }

If you're running the Provider on a different Mac than the Server, replace localhost with the Server's hostname or IP address. Set selfSigned to false if using a real TLS certificate.

Step 6: Register Provider

On the same machine as the server, the first provider auto-pairs as provider1 with a randomly generated password.

For additional providers or remote machines:

$ cd ~/cf/provider $ ./cfprovider register

You'll be prompted for admin credentials and a name for the new provider. The registration process assigns credentials that the provider uses to authenticate with the server.

Step 7: Run Provider

Single device mode:

# List connected devices to find UDIDs $ ./bin/go-ios list --details --pretty # Run provider for a specific device $ ./cfprovider run --udid YOUR_DEVICE_UDID

Runner mode (all devices):

$ ./cfprovider runner

Runner mode automatically detects all connected devices and manages them. It handles reconnections, launches agents, and keeps devices running unattended. This is the recommended mode for production deployments.

Step 8: Initialize Devices

Each device needs initial configuration for optimal automation. ControlFloor can do this automatically:

  1. Open the web dashboard and select a device
  2. Open the Menu and select Command Window
  3. Choose "Device Initialization" → "Initialize Device (All Settings)"
  4. Wait 5–10 minutes for the process to complete

This disables auto-correct, auto-capitalization, smart punctuation, and configures assistive controls needed for automation.

HTTPS Configuration

ControlFloor supports three HTTPS modes:

Self-signed (default)

The server generates a self-signed certificate on first run. Suitable for development and internal use. Clients will need to accept the self-signed certificate.

Custom certificates

Provide your own certificate and key in config.json:

{ "crt": "/path/to/fullchain.pem", "key": "/path/to/privkey.pem" }

Let's Encrypt

Point to your Let's Encrypt certificate files:

{ "crt": "/etc/letsencrypt/live/your-domain/fullchain.pem", "key": "/etc/letsencrypt/live/your-domain/privkey.pem" }

User Management

Manage users via the server CLI:

# Create a new user $ ./cfserver create-user -username new_user # Change a user's password $ ./cfserver modify-user -username admin -change-password # Delete a user $ ./cfserver delete-user -username old_user

iOS 17+ RSD Tunnel Configuration

iOS 17 introduced a new device communication model called Remote Service Discovery (RSD). Traditional usbmuxd-based communication no longer works for many operations. ControlFloor supports multiple QUIC-based tunnel methods:

1. Internal (Default)

ControlFloor's own tunnel implementation using remotedtool and utunuds helper binaries (set to suid root). This is the default and recommended method. Note: a short range of early iOS 17 firmware versions are not supported by this method — use PMD3 for those devices.

2. PMD3 (pymobiledevice3)

Uses pymobiledevice3 to create individual QUIC tunnels per device. Requires Python 3 and pymobiledevice3 installed. Good fallback for devices where the internal method is not available.

3. tunneld (pymobiledevice3 Daemon)

Runs pymobiledevice3's tunneld daemon as a separate process to manage all device tunnels centrally. Must be launched before the Provider.

See the Provider Configuration docs for detailed setup instructions for each tunnel method.