ℹ️ À savoir · En bref

Ansible gère Windows sans agent, en WinRM (historique) ou en SSH (support officiel depuis ansible-core 2.18, OpenSSH ≥ 7.9 donc Windows Server 2022 et plus). Les modules Windows sont écrits en PowerShell et vivent dans les collections ansible.windows, community.windows et microsoft.ad.

Côté Citrix, l'usage phare est la construction reproductible des images maîtres (VDA Windows et Linux) avant de les livrer à MCS, puis la configuration homogène de StoreFront.

Objectifs de la fiche

  • Connecter Ansible à des serveurs Windows du domaine (Kerberos) et éviter le piège du double saut.
  • Connaître les modules Windows indispensables.
  • Construire une image VDA de bout en bout, redémarrages compris.
  • Automatiser StoreFront et les VDA Linux avec la même logique.

Se connecter aux cibles Windows

ConnexionCôté nœud de contrôleQuand la choisir
WinRM (HTTPS 5986)pip install pywinrm[kerberos] + client KerberosLe standard en domaine ; ansible_winrm_transport: kerberos
PSRPpip install pypsrp[kerberos]Même port que WinRM, souvent plus rapide pour les gros transferts
SSH (OpenSSH Windows)Rien de plus qu'SSHWindows Server 2022+, clé SSH ; attention au double saut

inventaire Windows

# group_vars/windows.yml
ansible_connection: winrm
ansible_port: 5986
ansible_winrm_transport: kerberos
ansible_winrm_server_cert_validation: validate   # certificat de l'AD CS
ansible_user: svc-ansible@CORP.LOCAL             # royaume Kerberos en MAJUSCULES
ansible_password: "{{ vault_svc_ansible_password }}"

⚠️ Piège

Double saut : depuis la session distante, le compte ne peut pas accéder à un partage réseau (\\srv\sources) avec Kerberos simple ou une clé SSH. Solutions : copier les sources en local (win_copy, win_get_url), activer la délégation Kerberos (ansible_winrm_kerberos_delegation: true), ou become sur la tâche concernée.

Kerberos échoue si l'horloge du nœud de contrôle dérive de plus de 5 minutes, ou si on cible une adresse IP au lieu du FQDN.

Les modules Windows indispensables

ModuleUsage
ansible.windows.win_featureRôles et fonctionnalités (RDS, .NET…)
ansible.windows.win_packageInstaller un MSI / EXE silencieux, idempotent via product_id ou creates_path
ansible.windows.win_command / win_shellLancer un exécutable ou du PowerShell brut (creates / removes pour l'idempotence)
ansible.windows.win_powershellScript PowerShell avec contrôle de l'état : $Ansible.Changed, $Ansible.Failed
ansible.windows.win_regeditClés et valeurs de registre
ansible.windows.win_serviceDémarrage, arrêt, type de démarrage
ansible.windows.win_updatesMises à jour Windows, avec redémarrages intégrés (reboot: true)
ansible.windows.win_rebootRedémarrer et attendre le retour de la machine
microsoft.ad.membershipJoindre ou retirer une machine du domaine
community.windows.win_scheduled_taskTâches planifiées

Construire une image VDA

Terraform crée la VM, Ansible la prépare, MCS diffuse le snapshot
Terraform crée la VM, Ansible la prépare, MCS diffuse le snapshot

playbooks/vda_image.yml

- name: Préparer l'image maître VDA
  hosts: vda_master
  roles:
    - role: windows_base        # fonctionnalités, langue, registre
    - role: windows_updates     # ansible.windows.win_updates + reboot
    - role: apps                # win_package pour chaque application
    - role: citrix_vda          # voir ci-dessous
    - role: seal                # optimisation, nettoyage, arrêt

Installer le VDA, redémarrages compris

L'installeur VDA peut demander un redémarrage au milieu de l'installation. Il faut alors redémarrer puis le relancer sans paramètre depuis %ProgramData%\Citrix\XenDesktopSetup, jusqu'à ce que le fichier d'état disparaisse.

Codes retour : 0 ou 8 = terminé (redémarrage requis), 3 = redémarrer puis relancer
Codes retour : 0 ou 8 = terminé (redémarrage requis), 3 = redémarrer puis relancer

roles/citrix_vda/tasks/main.yml

- name: Copier l'installeur en local (évite le double saut)
  ansible.windows.win_copy:
    src: files/VDAServerSetup.exe
    dest: C:\Install\VDAServerSetup.exe

- name: Installer le VDA (premier passage)
  ansible.windows.win_command: >-
    C:\Install\VDAServerSetup.exe /quiet /noreboot /components VDA
    /controllers "{{ vda_controllers | join(' ') }}"
    /enable_hdx_ports /enable_hdx_udp_ports /enable_real_time_transport /masterimage
  args:
    creates: C:\Program Files\Citrix\Virtual Desktop Agent\BrokerAgent.exe   # VDA déjà présent
  register: vda
  failed_when: vda.rc is defined and vda.rc not in [0, 3, 8]

- name: Redémarrer
  ansible.windows.win_reboot:
  when: vda.rc is defined and vda.rc in [0, 3, 8]

- name: Reprendre l'installation tant que le fichier d'état existe
  ansible.windows.win_command: C:\ProgramData\Citrix\XenDesktopSetup\XenDesktopVdaSetup.exe
  args:
    removes: C:\ProgramData\Citrix\XenDesktopSetup\CitrixVirtualDesktopAgent.xml
  register: vda_resume
  failed_when: vda_resume.rc is defined and vda_resume.rc not in [0, 3, 8]
# puis win_reboot, et rejouer cette tâche tant que le code vaut 3

💡 Astuce

/controllers reçoit tes Cloud Connectors (DaaS) ou tes DDC (on-prem). Pour une image MCS, on peut aussi laisser MCS gérer l'enregistrement et omettre la liste.

Garde la version du VDA dans une variable (vda_version) et l'installeur dans un dépôt d'artefacts : changer de version devient une modification de variable, comme le snapshot dans TF-04.

Optimiser et sceller l’image

  • Citrix Optimizer : CtxOptimizerEngine.ps1 en mode Execute avec le modèle correspondant à ton OS, lancé via win_powershell.
  • Désactiver les mises à jour automatiques, vider les journaux et fichiers temporaires, arrêter les services inutiles.
  • Antivirus : déposer le script d'intégration VDI de Defender for Endpoint sans intégrer l'image elle-même (voir M365-DEF-01).
  • Dernière tâche : arrêt propre de la VM (win_shell: shutdown /s /t 5), puis snapshot côté hyperviseur.

StoreFront en PowerShell

StoreFront se configure avec ses modules PowerShell Citrix.StoreFront*. Le module win_powershell permet de rester idempotent : on lit l'état, on ne modifie que si besoin, et on le signale avec $Ansible.Changed.

roles/storefront/tasks/main.yml

- name: Sauvegarder la configuration StoreFront
  ansible.windows.win_powershell:
    script: |
      Get-Module -ListAvailable Citrix.StoreFront* | Import-Module
      Export-STFConfiguration -TargetFolder 'D:\Backup\StoreFront' `
        -ZipFileName "sf-{{ ansible_date_time.date }}" -NoEncryption
      $Ansible.Changed = $true

- name: Exemple de motif idempotent
  ansible.windows.win_powershell:
    script: |
      $actuel = (Get-ItemProperty 'HKLM:\SOFTWARE\Exemple' -Name Valeur -ErrorAction SilentlyContinue).Valeur
      if ($actuel -ne 1) {
        New-Item 'HKLM:\SOFTWARE\Exemple' -Force | Out-Null
        Set-ItemProperty 'HKLM:\SOFTWARE\Exemple' -Name Valeur -Value 1
        $Ansible.Changed = $true
      } else { $Ansible.Changed = $false }

ℹ️ À savoir

Pour un groupe de serveurs StoreFront, la configuration se fait sur le serveur principal puis se propage au groupe ; l'export / import (Export-STFConfiguration / Import-STFConfiguration) sert à sauvegarder ou cloner un environnement de recette.

Et les VDA Linux ?

  • Même logique, modules ansible.builtin : paquets, jonction AD (sssd / realmd, voir ANS-01), installation du paquet VDA.
  • VDA autonome : ctxsetup.sh en mode silencieux, piloté par des variables d'environnement CTX_XDL_* (liste des DDC, intégration AD, démarrage des services…).
  • Image MCS : on renseigne /etc/xdl/mcs/mcs.conf (template Jinja2) puis on lance deploymcs.sh ; pas de jonction AD de l'image, c'est MCS qui joint les clones.

Pièges classiques

SymptômeCauseParade
« Access denied » sur un partage pendant l'installationDouble sautSources copiées en local, délégation Kerberos ou become
Le playbook perd la machine pendant l'installationRedémarrage déclenché par l'installeur lui-mêmeToujours /noreboot, puis win_reboot piloté par Ansible
win_updates interminableBeaucoup de mises à jour cumuléesPartir d'une image récente, reboot: true, timeout généreux
Installeur bloqué sans erreurIl attend une interaction en session systèmeVérifier les options silencieuses, tester avec PsExec -s
« changed » à chaque passagewin_command / win_shell sans garde-foucreates / removes, product_id, ou $Ansible.Changed

🔷 En contexte Citrix

Chaîne complète : TF-01 (VM maître) → ANS-03 (préparation de l'image) → snapshot → TF-04 (catalogue MCS). Le tout peut tourner dans un pipeline CI/CD (ANS-04, TF-03).

Commence par automatiser un rôle à la fois sur ton image actuelle (par exemple l'installation du VDA), puis remplace progressivement les étapes manuelles.

À retenir

  • WinRM + Kerberos en domaine ; SSH supporté officiellement depuis ansible-core 2.18 (Windows Server 2022+).
  • Double saut : sources en local, délégation Kerberos ou become.
  • Installeur VDA : /noreboot, codes 0 / 8 terminé, 3 = redémarrer puis relancer sans paramètre.
  • win_powershell + $Ansible.Changed pour garder l'idempotence en PowerShell.
  • Linux VDA MCS : mcs.conf + deploymcs.sh, pas de jonction AD de l'image.

Auto-évaluation

Q1. Pourquoi une tâche qui lit \\srv\sources\setup.exe échoue-t-elle alors que le compte a les droits ?

→ C'est le double saut : la session distante n'a pas d'identifiants réutilisables pour un second serveur. Copier en local, déléguer Kerberos ou utiliser become.

Q2. L'installeur VDA renvoie 3. Que fait le playbook ?

→ Il redémarre la machine puis relance XenDesktopVdaSetup.exe sans paramètre depuis %ProgramData%\Citrix\XenDesktopSetup, jusqu'à obtenir 0 ou 8 et la disparition du fichier d'état.

Q3. Comment rendre idempotente une tâche win_powershell ?

→ Lire l'état actuel, ne modifier que s'il diffère, et positionner $Ansible.Changed en conséquence.

Q4. Pour une image Linux VDA destinée à MCS, quel fichier configures-tu ?

→ /etc/xdl/mcs/mcs.conf, puis deploymcs.sh ; MCS joint ensuite les clones au domaine.

Pour aller plus loin