ℹ️ À 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
| Connexion | Côté nœud de contrôle | Quand la choisir |
|---|---|---|
| WinRM (HTTPS 5986) | pip install pywinrm[kerberos] + client Kerberos | Le standard en domaine ; ansible_winrm_transport: kerberos |
| PSRP | pip install pypsrp[kerberos] | Même port que WinRM, souvent plus rapide pour les gros transferts |
| SSH (OpenSSH Windows) | Rien de plus qu'SSH | Windows 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
| Module | Usage |
|---|---|
ansible.windows.win_feature | Rôles et fonctionnalités (RDS, .NET…) |
ansible.windows.win_package | Installer un MSI / EXE silencieux, idempotent via product_id ou creates_path |
ansible.windows.win_command / win_shell | Lancer un exécutable ou du PowerShell brut (creates / removes pour l'idempotence) |
ansible.windows.win_powershell | Script PowerShell avec contrôle de l'état : $Ansible.Changed, $Ansible.Failed |
ansible.windows.win_regedit | Clés et valeurs de registre |
ansible.windows.win_service | Démarrage, arrêt, type de démarrage |
ansible.windows.win_updates | Mises à jour Windows, avec redémarrages intégrés (reboot: true) |
ansible.windows.win_reboot | Redémarrer et attendre le retour de la machine |
microsoft.ad.membership | Joindre ou retirer une machine du domaine |
community.windows.win_scheduled_task | Tâches planifiées |
Construire une image VDA

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.

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.ps1en modeExecuteavec le modèle correspondant à ton OS, lancé viawin_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.shen mode silencieux, piloté par des variables d'environnementCTX_XDL_*(liste des DDC, intégration AD, démarrage des services…). - Image MCS : on renseigne
/etc/xdl/mcs/mcs.conf(template Jinja2) puis on lancedeploymcs.sh; pas de jonction AD de l'image, c'est MCS qui joint les clones.
Pièges classiques
| Symptôme | Cause | Parade |
|---|---|---|
| « Access denied » sur un partage pendant l'installation | Double saut | Sources copiées en local, délégation Kerberos ou become |
| Le playbook perd la machine pendant l'installation | Redémarrage déclenché par l'installeur lui-même | Toujours /noreboot, puis win_reboot piloté par Ansible |
| win_updates interminable | Beaucoup de mises à jour cumulées | Partir d'une image récente, reboot: true, timeout généreux |
| Installeur bloqué sans erreur | Il attend une interaction en session système | Vérifier les options silencieuses, tester avec PsExec -s |
| « changed » à chaque passage | win_command / win_shell sans garde-fou | creates / 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.Changedpour 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.