
Un projet Ansible bien structuré est lisible, versionnable et passe à l’échelle d’une équipe. À l’inverse, un projet en vrac avec un seul gros playbook.yml à la racine devient ingérable dès qu’on dépasse 10 hôtes ou 3 contributeurs. Cette page pose le layout standard retenu dans la communauté en 2026, explique où vit chaque type de fichier (variables, secrets, modules custom, collections, rôles), et donne les conventions de nommage qui rendent un projet lisible.
Le layout que vous lisez ici est compatible RHCE EX294 et avec l’outil moderne ansible-navigator + Execution Environments. Il s’aligne aussi sur ce qu’attendent les outils tiers : ansible-lint, molecule, ansible-galaxy.
Ce que vous allez apprendre
Section intitulée « Ce que vous allez apprendre »- Le layout standard d’un projet Ansible et le rôle de chaque dossier ;
- Où placer les variables :
group_vars/,host_vars/,vars/,defaults/,vars_files:; - Comment versionner les dépendances :
requirements.yml(collections + rôles) etrequirements.txt(Python) ; - Quand sortir un rôle d’un playbook et où le placer (
roles/, Galaxy, Automation Hub) ; - Les conventions de nommage qui évitent les conflits sur une équipe.
Le layout standard
Section intitulée « Le layout standard »Voici le layout que vous trouverez sur la majorité des projets Ansible matures :
Répertoiremon-projet/
- ansible.cfg Config Ansible (forks, become, callback…)
- requirements.yml Collections + rôles externes
- requirements.txt Dépendances Python
- .ansible-lint Règles ansible-lint custom
Répertoireinventory/
- hosts.yml Inventaire principal (YAML)
- production.yml Inventaire prod (optionnel)
- staging.yml Inventaire staging (optionnel)
Répertoiregroup_vars/
- all.yml Variables pour tous les hôtes
- webservers.yml Variables pour le groupe webservers
- dbservers.yml Variables pour le groupe dbservers
Répertoirehost_vars/
- web1.lab.yml Variables spécifiques à web1.lab
- db1.lab.yml Variables spécifiques à db1.lab
Répertoireroles/
Répertoirecommon/ Rôle interne au projet
- …
Répertoirenginx/ Rôle interne nginx
- …
Répertoirecollections/ Collections téléchargées via ansible-galaxy
- …
Répertoireplaybooks/
- site.yml Playbook racine
- webservers.yml Playbook spécifique webservers
- dbservers.yml Playbook spécifique dbservers
Répertoirefiles/ Fichiers statiques (clés, config, scripts)
- …
Répertoiretemplates/ Templates Jinja2 partagés
- …
Répertoirelibrary/ Modules custom (Python)
- …
Répertoirefilter_plugins/ Plugins de filtres Jinja2 custom
- …
Répertoirelookup_plugins/ Plugins de lookup custom
- …
Ce layout n’est pas obligatoire — c’est une convention qui maximise l’interopérabilité avec les outils. Vous pouvez avoir un projet plus minimal (juste ansible.cfg, inventory/hosts.yml, playbooks/site.yml) ou plus structuré (sous-dossiers d’environnements, namespaces internes).
Le rôle de chaque fichier/dossier
Section intitulée « Le rôle de chaque fichier/dossier »ansible.cfg
Section intitulée « ansible.cfg »La config locale au projet d’Ansible. Toujours préférée à ~/.ansible.cfg ou /etc/ansible/ansible.cfg pour qu’un git clone suffise à reproduire l’environnement :
[defaults]inventory = ./inventory/hosts.ymlprivate_key_file = ./ssh/id_ed25519forks = 10host_key_checking = Falsestdout_callback = yamlgathering = smartfact_caching = jsonfilefact_caching_connection = ./.ansible_facts
[privilege_escalation]become = Truebecome_method = sudo
[ssh_connection]ssh_args = -o ControlMaster=auto -o ControlPersist=60spipelining = Truerequirements.yml et requirements.txt
Section intitulée « requirements.yml et requirements.txt »Deux fichiers, deux univers :
| Fichier | Gère | Installation |
|---|---|---|
requirements.yml | Collections + rôles Ansible Galaxy | ansible-galaxy install -r requirements.yml |
requirements.txt | Dépendances Python (pour les modules) | pip install -r requirements.txt |
Exemple requirements.yml :
---collections: - name: ansible.posix version: "2.1.0" - name: community.general version: "11.4.7" - name: community.libvirt version: "2.2.0"
roles: - name: geerlingguy.nginx version: "3.2.0"Versions épinglées (version:) pour la reproductibilité — pas ~> 1.0 qui prendrait n’importe quelle 1.x.
inventory/
Section intitulée « inventory/ »L’inventaire centralisé. Format YAML privilégié pour les variables structurées. Plusieurs fichiers possibles : production.yml, staging.yml, dev.yml. Activé via --inventory inventory/production.yml ou la variable inventory = d’ansible.cfg.
group_vars/ et host_vars/
Section intitulée « group_vars/ et host_vars/ »L’emplacement officiel des variables Ansible — bien plus propre que de mettre des vars: à l’intérieur d’un playbook ou d’un inventaire :
group_vars/├── all.yml # Variables partagées par TOUS les hôtes├── webservers.yml # Variables pour le groupe `webservers`└── dbservers.yml # Variables pour le groupe `dbservers`
host_vars/├── web1.lab.yml # Variables spécifiques à web1.lab└── db1.lab.yml # Variables spécifiques à db1.labAnsible charge automatiquement ces fichiers en fonction du nom — pas besoin de vars_files:. Si un hôte appartient à plusieurs groupes, les group_vars/<groupe>.yml sont fusionnés dans l’ordre alphabétique (puis écrasés par host_vars/).
Les rôles internes au projet. Chaque rôle a sa propre arborescence (tasks/, handlers/, templates/, defaults/, vars/, meta/, files/). Cf. la section Rôles (à venir).
Pour les rôles externes (Ansible Galaxy), la convention est de les déclarer dans requirements.yml et de les laisser dans ~/.ansible/roles/ ou collections/ansible_collections/.
collections/
Section intitulée « collections/ »Le dossier de téléchargement des collections Galaxy installées avec --collections-path. En général, vous laissez Ansible utiliser le path par défaut (~/.ansible/collections/) et vous ne versionnez pas ce dossier dans Git (gitignored).
playbooks/ ou racine
Section intitulée « playbooks/ ou racine »Deux écoles :
- Playbooks à la racine :
site.yml,webservers.ymldirectement à la racine du projet. Simple, court à taper. Convient aux petits projets. - Playbooks dans
playbooks/: sépare clairement le code de l’inventaire et des variables. La convention recommandée dès qu’un projet dépasse 5 playbooks.
library/ et *_plugins/
Section intitulée « library/ et *_plugins/ »library/: modules Python custom propres au projet. Ansible les charge automatiquement avant les modules standards.filter_plugins/: filtres Jinja2 custom.lookup_plugins/: plugins de lookup custom.callback_plugins/: plugins de callback (sortie custom).
À utiliser avec parcimonie — pour la plupart des cas, une collection externe existe déjà.
Où placer les variables ?
Section intitulée « Où placer les variables ? »C’est la question la plus fréquente en débutant. Voici la décision rapide :
| Type de variable | Emplacement |
|---|---|
| Variable globale (port standard, nom organisation) | group_vars/all.yml |
| Variable propre à un groupe | group_vars/<groupe>.yml |
| Variable propre à un hôte | host_vars/<hôte>.yml |
| Variable propre à un rôle (par défaut) | roles/<role>/defaults/main.yml |
| Variable forcée par un rôle (non override) | roles/<role>/vars/main.yml |
| Variable temporaire dans un play | vars: du play |
| Variable extérieure injectée | --extra-vars (CLI) |
| Secret | ansible-vault (cf. section Sécurité) |
La précédence complète (22 niveaux) est l’objet d’une page dédiée — c’est l’un des objectifs explicites de la RHCE EX294.
Conventions de nommage
Section intitulée « Conventions de nommage »Sur une équipe, ces conventions évitent les conflits et rendent le code lisible :
- Hostnames :
<rôle><n>.<env>.<domain>—web1.prod.example.com,db2.staging.example.com. - Groupes : pluriel, en kebab-case —
webservers,dbservers,load-balancers. - Variables : préfixées par le rôle ou le composant —
nginx_port,nginx_workers,pg_version. Évite les collisions entre rôles. - Playbooks : verbe d’action ou nom de groupe —
deploy-webservers.yml,harden-baseline.yml,site.yml. - Tags : descriptifs et orthogonaux —
nginx,firewall,monitoring. Évite lestag1,step2. - Rôles internes : en
snake_caseoukebab-case—nginx_labounginx-lab(cohérence sur tout le projet).
Pièges fréquents
Section intitulée « Pièges fréquents »| Symptôme | Cause | Fix |
|---|---|---|
Variables group_vars/all.yml ignorées | Le fichier est mal placé (ex: dans inventory/group_vars/) | Le placer à côté du playbook ou de l’inventaire chargé |
requirements.yml non installé sur les machines de l’équipe | Personne ne lance ansible-galaxy install -r requirements.yml | Intégrer dans le make bootstrap ou la CI |
ansible.cfg du projet ignoré | Lancement depuis un sous-dossier qui contient son propre ansible.cfg | Toujours lancer depuis la racine du projet (make aide) |
| Conflit de variables entre deux rôles | Rôles utilisent des variables avec le même nom (port, user) | Préfixer les variables par le rôle (nginx_port, pg_user) |
Secrets en clair dans host_vars/ | Variables sensibles non chiffrées | Chiffrer avec ansible-vault ou utiliser un manager externe (HashiCorp Vault, AWS Secrets Manager) |
À retenir
Section intitulée « À retenir »- Le layout standard inclut
ansible.cfg,inventory/,group_vars/,host_vars/,roles/,collections/,requirements.ymletrequirements.txt. group_vars/ethost_vars/sont l’emplacement officiel des variables — bien plus propre que lesvars:inline.requirements.ymlversionne les collections et rôles Galaxy ;requirements.txtversionne les dépendances Python.- Préfixez les variables par le nom du rôle/composant pour éviter les collisions sur une équipe.
- Les secrets ne vont jamais en clair —
ansible-vaultou un manager externe. - Le
ansible.cfglocal au projet est préféré à la version utilisateur — ungit clonedoit suffire à reproduire l’environnement.