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 --image <image> --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:
Most common fix: VM is stuck in a hung state. Force stop and delete the VM via SSH to the host.
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: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 | grep <vm-name> -
VNC into the VM and check VDA status:
ssh admin@<host-ip> open vnc://<vm-ip>:5900 - Navigate to: System Preferences → Citrix VDA. Should show: “Registered” with Cloud Connector details.
-
Test network connectivity from the VM:
ping <cloud-connector-ip> curl https://api.cloud.com - 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 admin@<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.
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
ifconfig route -n get default -
Check DNS configuration
cat /etc/resolv.conf -
Test connecting from the host to rule out any host issues
ssh admin@<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
ping <internal-server-ip> telnet <internal-server-ip> <port>
-
Check routing:
traceroute <internal-server-ip> - Test from host (confirm the host has access)
ssh admin@<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. If you don’t have DHCP configured, VMs will fall back to NAT mode with 192.168.64.x addresses. Quick diagnostic:-
Check cluster configuration on the MacStadium VDI management node:
cat /path/to/cluster.yml | grep vm_network_mode. This should show:vm_network_mode: bridge. -
Check host interface configuration:
cat /path/to/nodes.yml | grep osx_node_vm_network_interfaceor check thehostsfile:cat /path/to/hosts | grep osx_node_vm_network_interface -
Verify that the interface exists on the host:
ssh admin@<host-ip> ifconfig | grep <interface-name> -
Check DHCP traffic on the interface:
ssh admin@<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 all VMs (this is required before switching networking modes)
ansible-playbook -i dev/inventory delete.yml \ -e "vm_name=<vm-name>"Run this command once for each additional VM, using a unique
vm_name each time.
- Verify configuration files
cat cluster.yml should have: vm_network_mode: bridgecat nodes.yml should have: osx_node_vm_network_interface: <interface>
-
Reapply the host configuration:
ansible-playbook -i dev/inventory configure-hosts.yml - Deploy a test VM:
ansible-playbook -i dev/inventory deploy.yml \ -e "vm_name=test-01" \ -e "vm_image=<your-image>"
- Verify that the VM received a corporate IP address:
ansible-playbook -i dev/inventory list.yml -e "vm_name=test-01"
osx_node_vm_network_interface is not set or was set incorrectly. Verify the interface name, then reapply the configuration.
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 admin@<host-ip> netstat -i
- Check host network utilization:
ssh admin@<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 admin@<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 admin@<host-ip> nload
- Check if the repository is rate limiting. Look for throttling messages in the image pull output to confirm/deny this.
ansible-playbook -i dev/inventory pull_image.yml \ -e "remote_image_name=<image>" \ -vvv | grep -i "limit\|throttle"
Likely causes and solutions:
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:
ansible-playbook -i dev/inventory pull_image.yml \ -e "remote_image_name=<image>" \ -e "registry_username=<user>" \ -e "registry_password=<pass>" \ -vvv
- 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.yml
- Try pulling the image again with verbose output:
ansible-playbook -i dev/inventory pull_image.yml \ -e "remote_image_name=<image-name>" \ -vvv
- Check the image name and tags match exactly
- Try pulling the image to a specific host
ansible-playbook -i dev/inventory deploy.yml \ -e "vm_name=test-01" \ -e "vm_image=<exact-image-name>" \ --limit <specific-host>
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:
ansible-playbook -i dev/inventory create_image.yml \ -e "vm_image=<source>" \ -e "remote_image_name=<destination>" \ -e "registry_username=<user>" \ -e "registry_password=<pass>" \ -vvv
-
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 /var/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
ansible-playbook -i dev/inventory pull_image.yml \ -e "remote_image_name=<image-name>" \ --limit <single-host>
- Check the registry for image versions
Solution steps:
-
Pull a fresh image to all hosts
ansible-playbook -i dev/inventory pull_image.yml \
-e "remote_image_name=<image>" - Verify all hosts completed pull successfully, check playbook output for any errors
-
Redeploy VMs from the freshly pulled image
ansible-playbook -i dev/inventory deploy.yml \
-e "vm_name=<vm-name>" \
-e "vm_image=<image>"
Run this command once for each VM to deploy.
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
ansible-playbook -i dev/inventory list.yml | grep <host-name> | wc -l -
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 | grep <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 admin@<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 basic connectivity
ping <host-ip> -
Test SSH manually
ssh admin@<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 admin@<host-ip>
sudo ls /var/orka -
Check Ansible inventory settings:
cat dev/inventory | grep ansible_become -
Run the playbook with verbose output
ansible-playbook -i dev/inventory <playbook> -vvv - Check if a specific task is failing, and/or look at which task in the playbook fails
Most common fix:
ansible_become=yes not set in inventory. Add to [all:vars] section.
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> -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 admin@<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:
ansible-playbook -i dev/inventory <playbook> \-e "var1=value1" \-e "var2=value2" \-vv - 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: a
nsible-playbook -i dev/inventory <playbook> -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 admin@<host-ip>and check if the claimed changes actually exist -
Run the playbook in check mode:
ansible-playbook -i dev/inventory <playbook> --check - 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).

