Skip to main content
This guide covers deploying MacStadium VDI on infrastructure you manage. Most steps are the same whether you’re deploying on-premises or on AWS. Where the steps diverge, tabs or callout blocks mark the difference.
Before you start, confirm you have your Orka Engine license key and installer URL from your MacStadium account representative.

Prerequisites

Hardware requirements

Each Mac host must meet the following minimum specifications:
  • Apple silicon processor (any M-series chip)
  • 8 GB RAM
  • 256 GB storage
  • 1 GB Ethernet
  • macOS 13 (Ventura) or later
Recommended per host for production deployments:
  • M2 Pro, M4 Pro, or higher
  • 32 GB RAM
  • 1 TB+ storage
  • 10 GB Ethernet
  • macOS 14 (Sonoma), 15 (Sequoia), or 26 (Tahoe)
Apple’s EULA limits macOS virtual machines to 2 per host, regardless of available resources.

Controller requirements

The Ansible controller is a separate machine (macOS or Linux) that runs orchestration playbooks and the management UI.
  • Minimum: 2 vCPU, 4 GB RAM, 20 GB storage
  • Recommended: 4 vCPU, 8 GB RAM, 50 GB storage

Network requirements

  • Management VLAN with connectivity between the controller and all Mac hosts
  • Static IPs or DHCP reservations for each host
  • Outbound TCP 443 from VMs to Citrix Cloud endpoints (if deploying with Citrix DaaS):
    • [customer_ID].xendesktop.net
    • *.*.nssvc.net
    • *.citrixworkspacesapi.net
  • Inbound TCP/UDP 1494 and 2598 to VMs for HDX sessions

Step 1: Prepare your Mac hosts

Run all steps in this section on each physical Mac host. Repeat for every host in your fleet.
Don’t enable FileVault on Mac hosts without a remote recovery plan. If a host with FileVault enabled powers down, you’ll need physical access to decrypt the disk before the host can be managed remotely. If FileVault is required by your security policy, use macOS Tahoe (26). Tahoe supports pre-boot SSH for remote disk decryption. See Security and Encryption for details.

1.1 Assign a static IP

Assign a static IP to each host before installing Orka Engine. Either configure it manually or use a DHCP reservation. Manual configuration:
  1. Open System Settings → Network → select your interface (Ethernet or Wi-Fi).
  2. Set IP address, subnet mask, router, and DNS servers from your management VLAN.
  3. Apply and verify connectivity.
DHCP reservation:
  1. Note the MAC address of each host from System Settings → Network → Details → Hardware.
  2. Configure your DHCP server to assign a fixed IP to each MAC address.
  3. Verify the host receives the reserved IP.
Document the following for each host (you’ll need it for the Ansible inventory file):
FieldExample
Hostnamemac-node-1
IP address10.0.100.10
MAC addressa1:b2:c3:d4:e5:f6
Hardware modelMac mini M4
Network interfaceen0

1.2 Set the hostname

Replace example-host0 with the appropriate hostname for each machine. Use a short name without dots for HostName.
sudo scutil --set ComputerName "example-host0"
sudo scutil --set LocalHostName "example-host0"
sudo scutil --set HostName "host0"
dscacheutil -flushcache

1.3 Install Homebrew

/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"
brew doctor

1.4 Verify Python

Python 3 is required for Ansible to manage the host. It ships with macOS but confirm it’s present:
python3 --version

Step 2: Set up your controller

Run all steps in this section on the controller machine.

2.1 Set the hostname

sudo scutil --set ComputerName "example-controller"
sudo scutil --set LocalHostName "example-controller"
sudo scutil --set HostName "example-controller"
dscacheutil -flushcache

2.2 Install Homebrew

/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"
brew doctor

2.3 Install Ansible

Modern versions of macOS prevent installing Python packages system-wide. Install Ansible through pipx to keep it isolated from the system Python environment.
brew install pipx
pipx install ansible-core==2.18.4
pipx install ansible==11.4.0

Step 3: Configure SSH access to your hosts

Ansible uses SSH key authentication to connect to each Mac host. Run these steps on the controller.

3.1 Generate an SSH key

If you don’t already have one:
ssh-keygen -t ed25519
Accept the default file path or specify your own.

3.2 Copy the key to each host

Run once per host, substituting the correct IP:
ssh-copy-id administrator@10.0.100.10
Verify the connection before continuing:
ssh administrator@10.0.100.10
Repeat for every host.

Step 4: Configure the orchestration library

Run all steps in this section on the controller.

4.1 Clone the repository

mkdir -p ~/orka-automation
cd ~/orka-automation
git clone https://github.com/macstadium/orka-engine-orchestration.git
cd orka-engine-orchestration

4.2 Create the inventory file

mkdir -p dev/group_vars/all
touch dev/group_vars/all/main.yml
vim inventory
Add the IP address of each host:
[hosts]
10.0.100.10
10.0.100.11
10.0.100.12

4.3 Configure group variables

vim dev/group_vars/all/main.yml
File contents:
max_vms_per_host: 2
engine_binary: /usr/local/bin/orka-engine

ansible_user: administrator
vm_image: ghcr.io/macstadium/orka-images/sequoia:latest
VariableDescription
max_vms_per_hostMaximum VMs per host. Apple’s EULA caps macOS VMs at 2 per host.
engine_binaryPath to the Orka Engine binary
ansible_userSSH username on each host
vm_imageDefault base image for VM deployments
network_interface(Optional) Network interface for bridged networking, e.g. en0

Step 5: Install Orka Engine

This playbook installs Orka Engine on every host in your inventory, applies your license key, and starts the service.
cd ~/orka-automation/orka-engine-orchestration

ansible-playbook install_engine.yml -i inventory -e "orka_license_key=YOUR-LICENSE-KEY" -e "engine_url=YOUR-INSTALLER-URL"
Replace YOUR-LICENSE-KEY and YOUR-INSTALLER-URL with the values from your MacStadium account representative.

Verify the installation

ansible hosts -i inventory -m shell -a "orka-engine --version"
ansible hosts -i inventory -m shell -a "/usr/local/bin/orka-engine info"

Force reinstall or upgrade

To reinstall or upgrade to a newer version, add the install_engine_force flag:
ansible-playbook install_engine.yml -i inventory -e "orka_license_key=YOUR-LICENSE-KEY" -e "engine_url=YOUR-INSTALLER-URL" -e "install_engine_force=true"

Step 6: Set up the management UI

The management UI (built on Semaphore) is the primary interface for IT administrators. It provides a browser-based dashboard for running orchestration playbooks without touching the CLI.

6.1 Install prerequisites

brew install docker docker-compose
brew install uv
Docker Desktop is an alternative if you prefer a GUI installer.

6.2 Configure the environment

cd ~/orka-automation/orka-engine-orchestration
cp semaphore/.env.example semaphore/.env
Generate a 32-byte encryption key:
head -c32 /dev/urandom | base64
Open semaphore/.env and paste the key:
vim semaphore/.env
SEMAPHORE_ACCESS_KEY_ENCRYPTION=your-generated-key-here
Also set your admin username and password in the same file.

6.3 Start the management UI

cd ~/orka-automation/orka-engine-orchestration
docker compose up -d
The management UI is available at http://localhost:3000. Log in with the admin credentials you set in .env.

6.4 Configure SSH credentials

Option A: Setup script (recommended)
SEMAPHORE_ADMIN=$YOUR_ADMIN SEMAPHORE_ADMIN_PASSWORD=$YOUR_ADMIN_PASSWORD uv run ./semaphore/configure_semaphore.py --ssh-key-file $YOUR_KEY
Run uv run ./semaphore/configure_semaphore.py --help to see all options, including VM credentials and OCI registry settings. Option B: Manual (UI) After logging in, navigate to Key Store and edit the Mac Hosts SSH key. Replace the placeholder with the SSH username and private key for your Mac hosts.

Step 7: Deploy your first VM

With your hosts configured and the management UI running, you’re ready to deploy a macOS VM. From the management UI, open the Orka Engine Orchestration project and run the VM: Deploy VM template. Enter a unique vm_name and the vm_image to use. Or run the playbook directly:
ansible-playbook deploy.yml -i inventory -e "vm_name=vdi-test-01" -e "vm_image=ghcr.io/macstadium/orka-images/sequoia:latest" -e "network_interface=en0"
Use network_interface=en0 (bridged networking) for VDI workloads. VMs get direct IP addresses on your network, which Citrix Cloud and end users need to reach them without port forwarding. Orka 3.5.0 or later is required for bridged networking.
Use your management VLAN interface, typically en0 for Ethernet. Confirm the interface name on each host with networksetup -listallhardwareports.
Verify the VM deployed:
ansible-playbook list.yml -i inventory -e "vm_name=vdi-test-01"
To preview a deployment without making changes, add --tags plan:
ansible-playbook deploy.yml -i inventory -e "vm_name=vdi-test-01" -e "vm_image=ghcr.io/macstadium/orka-images/sequoia:latest" --tags plan

Next steps

Your infrastructure is ready. Continue with:

Citrix DaaS Configuration

Register your VMs with Citrix Cloud and configure delivery groups.

Image Management

Build a golden image with Citrix VDA and your organization’s applications pre-installed.