MacStadium VDI environment
How to use this guide
This is a quick reference for troubleshooting common issues. Each section is organized by symptom (what users report or what you observe), followed by its likely causes and diagnostic steps. During an incident:- Find the symptom that matches your situation
- Follow the diagnostic commands in order
- Apply the recommended solution
- Document what worked for your post-incident review
- Primary method: Always use Ansible playbooks for VM operations (deploy, delete, start, stop, image management)
-
Advanced diagnostics: You can SSH to hosts and use
orka-engineCLI commands for lower-level troubleshooting -
Examples:
orka-engine vm list,orka-engine vm run <VM_NAME> --image <IMAGE_NAME> --net-interface en0 - Note: All production operations should go through Ansible playbooks to maintain consistency
VM provisioning issues
Symptom: VM deployment fails completely
What you see:deploy.yml playbook fails with error messages
Quick diagnostic:
Most common fix: Image name/tag typo or a registry authentication failure.
Symptom: VMs deploy but won’t start
What you see: Deployment succeeds but VMs show “Stopped” or error status Quick diagnostic:Likely causes and solutions:
Most common fix: Corrupted image during pull. Re-pull the image to the host and redeploy.
Symptom: Wrong number of VMs deployed
What you see: Requested 10 VMs but only 7 deployed, or deployment stopped partway through Quick diagnostic:
Most common fix: You may have hit the max_vms_per_host limit. Add more hosts to distribute VM load.
Symptom: Can’t delete VMs
What you see:delete.yml or vm.yml with desired_state=absent fails
Quick diagnostic:
vm.yml with desired_state=stopped runs orka-engine vm stop, which already force-stops the VM without waiting for macOS to shut down, so there’s no harder stop to try. If vm stop itself fails, contact MacStadium support and include the Orka Engine log.
Likely causes and solutions:
Most common fix: VM is stuck in a hung state. Stop the VM with
vm.yml, then delete it.
Symptom: VM deploys but never boots or services don’t start
What you see: Ansible playbook completes but VM never becomes usable. VM created but stuck in an unresponsive state. Quick diagnostic:
Most common fix: Apple’s EULA limits macOS VMs to 2 per host. Run
deploy.yml with --tags plan to check capacity before deploying.
Citrix VDA registration failures
Symptom: New VMs won’t register with Citrix
What you see: VMs show as “Unregistered” in Citrix Cloud Console → Monitor → Machines Quick diagnostic: Confirm the VDA was installed and registered.deploy.yml only deploys the VM: unless the golden image includes the VDA, run install_citrix_vda.yml, and then run register_citrix_vda.yml for every new VM.
443, 1494, and 2598 are open.
Symptom: VMs were registered, now show as unregistered
What you see: VMs that were working now show “Unregistered” status Quick diagnostic:-
Verify the VM is running:
ansible-playbook -i dev/inventory list.yml -e "vm_name=<VM_NAME>" -
VNC into the VM and check VDA status. From your Mac, open a Screen Sharing (VNC) connection to the VM:
open vnc://<VM_IP>. Screen Sharing is on in the MacStadium base images, so golden images built from them have it unless your build turns it off. Whether your Mac can reach the VM’s IP depends on your network’s routing to the VM VLAN. - Navigate to: System Preferences → Citrix VDA. Should show: “Registered” with Cloud Connector details.
- Test network connectivity from the VM:
- Check VDA service logs. On the VM: Console.app → Search for “Citrix”
Most common fix: Cloud Connector lost network connectivity or service crashed. Restart the Cloud Connector.
Symptom: VDA shows “Registration in Progress” indefinitely
What you see: VDA status remains stuck on “Registering…” and never completes Quick diagnostic:- Check if Cloud Connector is up by navigating to Citrix Cloud Console → Monitor → Cloud Connectors, and look for: Status “Up” or “Down”.
- Check if multiple VMs are affected: Monitor → Machines → Filter by Delivery Group. Check if all VMs show as unregistered, or just some.
-
Test connectivity from VM to Cloud Connector by running
ssh administrator@<HOST_IP>, VNC to the VM, then run:ping <CLOUD_CONNECTOR_IP> - Check the VDA service on the VM: System Preferences → Citrix VDA.
Most common fix: Verify that the VM can resolve the Cloud Connector hostname or configure it with a correct/updated IP address.
Symptom: VMs register but users can’t connect
What you see: Citrix Console shows VMs are “Registered” but users get connection errors Quick diagnostic:- Verify the user is in the correct Delivery Group by navigating to Citrix Cloud Console → Manage → Delivery Groups → Search for the user
- Check that the VM is actually in an “Available” state by navigating to Monitor → Machines → and checking the “Status” column. This should show “Available” not “In Use” or “Maintenance”.
- Test the connection yourself with a test account by launching a desktop from Citrix Workspace.
- Check for Citrix policy issues. Policies → Review policies applied to the impacted Delivery Group.
Most common fix: User was not added to the Delivery Group. Add the user via Citrix Cloud Console.
Symptom: Session fails to launch or times out
What you see: Desktop appears in Citrix Workspace but won’t launch. Connection progress bar stalls. “Unable to connect” error. Quick diagnostic:*.xendesktop.net and outbound TCP/UDP 443 to *.*.nssvc.net.
Likely causes and solutions:
Most common fix: Firewall blocking HDX ports. Ensure TCP/UDP 1494 and 2598 are open from client to VM.
Symptom: Clipboard or file transfer not working
What you see: Can’t copy/paste between client and VM. File drag-and-drop fails. Quick diagnostic:- Check HDX policies: Citrix Cloud Console → Policies → HDX Settings
- “Client clipboard redirection” should be Allowed
- “Client drive redirection” should be Allowed
- Log out and back in; policies don’t always apply to existing sessions.
- Test with plain text first, then formatted text, then files.
Most common fix: HDX clipboard or drive redirection policy is set to Prohibited. Update the policy in Citrix Cloud Console → Policies.
Network and connectivity problems
Symptom: VMs can’t reach internet
What you see: Users report “No internet connection” / Can’t browse web or download updates Quick diagnostic:-
Test basic connectivity from the VM by VNCing into the VM:
ping 8.8.8.8
ping google.com
curl https://google.com - Check the VM network configuration
-
Check DNS configuration
cat /etc/resolv.conf -
Test connecting from the host to rule out any host issues
ssh administrator@<HOST_IP>
ping 8.8.8.8
Most common fix: DNS is not configured in the golden image. Add DNS servers (e.g., 8.8.8.8, 8.8.4.4) to network config in the image template.
Symptom: VMs can’t reach internal corporate services
What you see: “Can’t access file shares” / “Internal apps unreachable” / “Need VPN” Quick diagnostic:- Test connecting from the VM to internal services
-
Check routing:
traceroute <internal-server-ip> - Test from host (confirm the host has access)
ssh administrator@<HOST_IP> ping <internal-server-ip>
- Check if the VM subnet is allowed through company firewalls. Contact your network IT team with the following information:
Destination: Internal service IP
Ports needed Likely causes and solutions:
Most common fix: Your firewall rules don’t include the VM subnet. Work with your network team to add the appropriate
allow rules.
Symptom: Bridged mode VMs getting wrong IPs (192.168.64.x)
What you see: VMs should get corporate IPs but are getting 192.168.64.x private range instead Important prerequisite: Bridged networking requires a DHCP server on your network that can assign IP addresses to VMs, and you must setnetwork_interface to the host’s network interface, for example en0, when you deploy the VM. Without it, the VM uses NAT, with a 192.168.64.x address, and Citrix Cloud and end users can’t reach it. You can’t change the network mode after the VM is deployed.
Quick diagnostic:
-
Check the VM’s IP address:
ansible-playbook -i dev/inventory list.yml -e "vm_name=<VM_NAME>". A 192.168.64.x address means the VM was deployed withoutnetwork_interface. -
Verify that the interface exists on the host:
ssh administrator@<HOST_IP> ifconfig | grep <INTERFACE_NAME> -
Check DHCP traffic on the interface:
ssh administrator@<HOST_IP> sudo tcpdump -i <INTERFACE_NAME> port 67 and port 68 - Deploy a test VM and watch for DHCP requests/replies
Solution steps:
- Delete the VMs that have 192.168.64.x addresses. List them first, then preview and run the deletion:
- Deploy a test VM with
network_interfaceset:
- Verify that the VM received a corporate IP address:
ansible-playbook -i dev/inventory list.yml -e "vm_name=test-01"
network_interface, or with the wrong interface name. Verify the interface name, then delete the VM and redeploy it with network_interface set.
Symptom: Intermittent network connectivity
What you see: Network works sometimes, drops randomly, packet loss Quick diagnostic:-
Run a continuous ping test from the VM by VNCing into the VM and running:
ping -c 100 8.8.8.8. Look for the packet loss percentage. - Check for interface errors on the host, and look for errors/drops in output:
ssh administrator@<HOST_IP> netstat -i
- Check host network utilization:
ssh administrator@<HOST_IP> nload (or: iftop)
- Check if the connectivity issue is specific to one host, or impacts all hosts. Test VMs on different hosts to confirm.
Most common fix: Network congestion or host overloaded. Reduce VMs per host or work with network team on quality of service improvements.
Image cache and distribution issues
Symptom: Image pull extremely slow
What you see:pull_image.yml takes 30+ minutes for reasonably sized images
Quick diagnostic:
- Test registry connection and speed:
ssh administrator@<HOST_IP> time curl -o /dev/null https://<registry>/test-file
- Check image size by viewing this in your container registry UI
- Monitor network utilization during the image pull process
ssh administrator@<HOST_IP> nload
- Check if the repository is rate limiting. Look for throttling messages in the image pull output to confirm/deny this.
Most common fix: Registry is located in a geographically distant datacenter. Deploy the registry closer to Orka hosts or use registry replication.
Symptom: Image pull fails with authentication error
What you see: “unauthorized” / “authentication required” / “403 Forbidden” Quick diagnostic:-
Test registry authentication manually:
curl -u <username>:<password> https://<registry>/v2/_catalog -
Verify credentials in the Ansible playbook command, and check that the
registry_usernameandregistry_passwordare correct - Test pull with credentials:
- If available, check the registry access logs. Look for any authentication failures.
Most common fix: Credentials are outdated or incorrect. Verify and update your
registry_username and registry_password values.
Symptom: Image pull succeeds, but deploy fails
What you see:pull_image.yml succeeds but deploy.yml can’t find image
Quick diagnostic:
- Verify the image was pulled successfully:
ansible-playbook -i dev/inventory list_images.yml
- Try pulling the image again with verbose output:
- Check the image name and tags match exactly
- Try pulling the image to a specific host
deploy.yml builds its plan on the Ansible control node, so include localhost in --limit.
Likely causes and solutions:
Most common fix: Image name/tag mismatch between pull and deploy. Ensure an exact match, including image tags.
Symptom: Can’t push new image to registry
What you see:create_image.yml fails during push phase
Quick diagnostic:
- Run the
create_image.ymlAnsible playbook with verbose output:
-
Check registry authentication
curl -u <user>:<pass> https://<registry>/v2/_catalog - Check registry storage space
-
Verify sufficient host disk space:
ansible hosts -i dev/inventory -m shell -a "df -h /opt/orka"
Most common fix: Registry authentication or insufficient storage space. Verify credentials and check registry capacity.
Symptom: Inconsistent images across hosts
What you see: The same image name on different hosts, but with different behavior/versions Quick diagnostic:- List VMs on all hosts to check deployment times
ansible-playbook -i dev/inventory list.yml
-
Check when VMs were last deployed using
list.ymlto show the VM status - Test pulling an image to verify registry performance
- Check the registry for image versions
Solution steps:
- Pull a fresh image to all hosts
- Verify all hosts completed pull successfully, check playbook output for any errors
- Redeploy VMs from the freshly pulled image
deploy.yml doesn’t deploy a new one, so delete the old VM first with vm.yml and desired_state=absent. Deletes match VM names by prefix, so run list.yml with the same vm_name first.
Most common fix: Images were pulled at different times, with registry updates between. Re-pull images to all hosts for consistency.
Performance and latency problems
Symptom: Desktop Feels Sluggish for Users What you see: Users report slow response, lag, choppy mouse movement, etc. Quick diagnostic:-
Check host resource utilization
ansible hosts -i dev/inventory -m shell -a "top -l 1 | head -20" -
Count VMs per host: run
ansible-playbook -i dev/inventory list.ymland count the running VMs per host in theHostcolumn. A host running two VMs is at capacity. -
Check specific VM resources by VNCing into the VM:
open vnc://<vm-ip>:5900
Open Activity Monitor → Check CPU, Memory, Disk, Network - Test the user’s network latency (if remote). Ask the user to ping the VM IP, or use the Citrix HDX Tester tool
Most common fix: Host is overloaded. Redistribute VMs across hosts or add capacity.
Symptom: Poor video quality or choppy playback
What you see: Pixelated screen, blurry text, stuttering video Quick diagnostic:- Check the user’s network bandwidth
- Ask the user to run: Speedtest by Ookla - The Global Broadband Speed Test
- Check the user’s HDX Visual Quality policy by navigating to: Citrix Cloud Console → Policies.
- Test bandwidth/performance with Citrix HDX Monitor (if available), as this shows real-time HDX metrics
- Check the user’s connection type (Are they connecting remotely/via VPN? On wifi? Wired?)
Most common fix: HDX Visual Quality policy too conservative. Increase quality for users with good connections.
Symptom: Slow login times (>2 minutes)
What you see: Long wait from launching desktop to usable desktop Quick diagnostic:- Measure login time components
- Check if VM had to boot
ansible-playbook -i dev/inventory list.yml -e "vm_name=<VM_NAME>"
- Check user profile size (if using roaming profiles)
- Monitor VM resources during login: Watch Activity Monitor during the login process
Most common fix: Large roaming profiles. Implement folder redirection and profile cleanup policies.
Symptom: Application launches are slow
What you see: Apps take 30+ seconds to launch after clicking Quick diagnostic:- Test from within the VM directly
- Check if the app is on network share vs. local storage
- Check VM disk I/O
- Check available memory
Most common fix: Applications installed on network shares. Pre-install in golden image for local execution.
Symptom: High CPU usage even when idle
What you see: VM consuming 50%+ CPU with no user activity Quick diagnostic:- Identify the process consuming CPU by VNCing into the VM, then navigate to Activity Monitor → Sort by %CPU
- Check for runaway processes
- Check for malware (unlikely but possible)
- Monitor over time: Is the CPU spike temporary or sustained?
Most common fix: Spotlight indexing or macOS maintenance tasks. Usually resolves itself within an hour.
Authentication and access control
Symptom: User can’t log into desktop (credentials rejected)
What you see: The user enters their credentials, but gets an “Invalid username or password” error Quick diagnostic:- Verify the user exists in your identity provider by checking Active Directory or Azure AD
- Test user login capabilities with a known-good account
- Check if the issue is specific to one VM or is impacting all VMs
- Check VDA domain binding (if using AD)
Most common fix: The user’s password is expired. Have the user reset their password through your normal corporate process.
Symptom: User can log in but has the wrong permissions
What you see: User is authenticated, but they can’t access files/apps they should have access to Quick diagnostic:- Check the user’s group memberships
- Verify user permissions on restricted resources
- Test with a known-good user from the same group
- Check GPO application (if using AD)
Most common fix: The user is not in the required AD group(s). Add them to the appropriate group(s), and then force a GPO refresh.
Symptom: Single Sign-On (SSO) not working
What you see: Users are prompted for their SSO credentials despite being logged into iCloud/corporate network Quick diagnostic:- Check Citrix Workspace SSO configuration
- Verify Citrix Gateway/SSO configuration is correct
- Test SSO login capability with manual credentials
- Check the user’s SSO/company domain login
Most common fix: SSO is not enabled in Citrix Workspace. Enable SSO in the user’s Workspace preferences.
Symptom: Can’t access Citrix Cloud Admin Console
What you see: Admins can’t log into Citrix Cloud Console to manage environment(s) Quick diagnostic:-
Try using a different browser
- Some browsers cache authentication differently
- Clear browser cookies and cache, then try logging in again
- Verify your admin account is not locked, check with Citrix support or another admin
- Check Citrix Cloud status: https://status.cloud.com
Most common fix: Browser cache issue. Clear your cookies and cache, or try using incognito/private mode.
Ansible playbook errors
Symptom: Playbook fails with “Host unreachable”
What you see: Playbook errors: “Failed to connect to the host via ssh” / “Host is unreachable” Quick diagnostic:-
Test basic connectivity
ping <host-ip> -
Test SSH manually
ssh administrator@<HOST_IP> -
Check inventory file
cat dev/inventory
- Test Ansible ping module
ansible hosts -i dev/inventory -m ping
Most common fix: SSH key is not in
authorized_keys on host. Add the Ansible control node’s public key to the host.
Symptom: Playbook fails with “Permission denied”
What you see: Playbook errors with permission/sudo errors during execution Quick diagnostic:-
Test sudo access manually
ssh administrator@<HOST_IP>
sudo ls /opt/orka -
Run the playbook with verbose output
ansible-playbook -i dev/inventory <PLAYBOOK>.yml -vvv - Check if a specific task is failing, and/or look at which task in the playbook fails
Symptom: Playbook times out
What you see: Your Ansible playbook runs, but it times out on specific tasks without completing Quick diagnostic:-
Run with verbose output to see where the playbook hangs:
ansible-playbook -i dev/inventory <PLAYBOOK>.yml -vvv - Test the specific command manually by SSHing to the host and running the command that’s timing out
- Check if the task requires a long time to complete
- Monitor host resources during tasks by running:
ssh administrator@<HOST_IP>
top
Most common fix: Legitimate long-running task (such as an image pull). Increase the
async timeout or be patient.
Symptom: Playbook variables not being applied
What you see: Playbook runs but doesn’t use the variables you specified with-e
Quick diagnostic:
- Check command syntax
- Run with verbose output:
- Check playbook for variable names, and ensure they match exactly (variable names are case-sensitive)
- Check for hard-coded values in the playbook, these might override other variables
Most common fix: Variable name typo. Check playbook documentation for exact variable names (these are case-sensitive).
Symptom: Playbook fails partway through
What you see: The playbook starts successfully, but fails on a specific task Quick diagnostic:-
Run the playbook with verbose output to see the exact error:
ansible-playbook -i dev/inventory <PLAYBOOK>.yml -vvv - Check the specific task that failed, reviewing the error logs carefully
- Test the failing task’s command manually by SSHing into the host and running the command
- Check if the task is stuck in a partially successful state and needs cleanup, or needs to be re-run
Most common fix: Network or resource interruption. Verify connectivity and available resources, then re-run the playbook.
Symptom: Playbook says “Changed” but nothing actually changed
What you see: Playbook reports changes, but its state appears identical Quick diagnostic:- Check what the playbook claims to change, look at the task output while the playbook is running
-
Verify the actual state on the MacStadium VDI host
ssh administrator@<HOST_IP>and check if the claimed changes actually exist -
Preview the playbook’s changes. The orchestration modules that query Orka Engine don’t support Ansible check mode, so
--checkfails. Rundeploy.yml,delete.yml,deploy_avd.yml,delete_avd.yml, oravd.ymlwith--tags planinstead:ansible-playbook -i dev/inventory <PLAYBOOK>.yml -e "vm_name=<VM_NAME>" --tags plan - Check for idempotency issues, and run the playbook twice. The task status should display “ok,” the second time, and not “changed”.
Most common fix: The playbook is not properly checking the existing state before making changes (idempotency issue).
Escalation quick reference
When to escalate:Troubleshooting best practices
- Start simple: verify basic connectivity before diving into application-layer issues.
- Check one layer at a time: network → host → VM → VDA → Citrix.
- Use verbose playbook output for any failing task:
ansible-playbook -i dev/inventory <PLAYBOOK>.yml -vvv - Test on a single host before assuming an issue is widespread: add
--limit mac-node-1. Playbooks that build a plan or list results on the Ansible control node, such asdeploy.yml,delete.yml, andlist.yml, also needlocalhostin the limit:--limit mac-node-1,localhost. - Document what you tried and what worked. Add it to your internal runbook.
- Monitor logs proactively rather than reactively. See Monitoring & Observability for setup guidance.

