
La meilleure structure pour un projet Ansible mature : pour chaque groupe d’inventaire, deux fichiers côte à côte — main.yml qui contient les variables publiques (port, version, environnement) et vault.yml qui contient uniquement les secrets (chiffré complet). Ansible les fusionne automatiquement, et la convention vault_* rend la sensibilité visible dans le code.
À la fin, vous saurez structurer un group_vars/ industriel, garder des diffs Git lisibles sur les variables publiques, et limiter le périmètre du mot de passe vault aux modifications réellement sensibles.
Ce que vous allez apprendre
Section intitulée « Ce que vous allez apprendre »- Pattern
group_vars/<groupe>/main.yml + vault.yml: structure et règles de fusion. - Convention de nommage
vault_*pour distinguer visuellement une variable sensible. - Fusion automatique par Ansible : les deux fichiers forment un seul namespace.
- Diff Git : pourquoi cette structure produit des diffs lisibles.
- Lecture sans déchiffrer : qui peut lire
main.ymlsans avoir le mot de passe vault. - Rotation localisée : ne rote que les
vault.ymldu groupe concerné.
Prérequis
Section intitulée « Prérequis »- Avoir lu Introduction Ansible Vault et encrypt_string.
- Comprendre
group_vars/(voir Inventaires).
Le pattern en une image
Section intitulée « Le pattern en une image »inventory/├── hosts.yml└── group_vars/ ├── all/ │ ├── main.yml ← variables publiques partagées (clair) │ └── vault.yml ← secrets partagés (CHIFFRÉ COMPLET) ├── webservers/ │ ├── main.yml ← config publique webservers (clair) │ └── vault.yml ← secrets webservers (CHIFFRÉ COMPLET) └── dbservers/ ├── main.yml └── vault.ymlRègle d’or : pour un groupe donné, Ansible fusionne automatiquement tous les fichiers YAML présents dans group_vars/<groupe>/. Un host de webservers voit donc :
- les variables de
all/main.yml+all/vault.yml(héritage) - les variables de
webservers/main.yml+webservers/vault.yml(spécifique)
Convention : préfixer les variables vault par vault_* (ex: vault_admin_token, vault_db_password, vault_web_secret). Permet un coup d’œil rapide pour repérer les valeurs sensibles dans tout le code.
Pourquoi pas un seul fichier complètement chiffré
Section intitulée « Pourquoi pas un seul fichier complètement chiffré »Trois inconvénients du fichier unique chiffré :
- Diffs Git illisibles : modifier
http_port: 80→8080produit un blob hex aléatoire de 200 lignes. Impossible à reviewer. - Périmètre vault élargi : ajouter une variable publique demande le mot de passe.
- Lecture en revue : impossible de comprendre la config sans déchiffrer.
Le pattern mixte résout les trois en mettant la frontière claire/chiffré au niveau du fichier, pas au niveau de la variable.
Étape 1 — Préparer la structure
Section intitulée « Étape 1 — Préparer la structure »cd labs/vault/playbooks-mixtes/
mkdir -p inventory/group_vars/allmkdir -p inventory/group_vars/webservers
# all/main.yml — variables PUBLIQUES partagéescat > inventory/group_vars/all/main.yml <<'EOF'deployment_environment: lab80EOF
# webservers/main.yml — config publiquecat > inventory/group_vars/webservers/main.yml <<'EOF'http_port: 80worker_count: 4EOFCes fichiers restent en clair. On peut les cat, les diff, les commiter sans souci.
Étape 2 — Créer les fichiers de secrets
Section intitulée « Étape 2 — Créer les fichiers de secrets »# all/vault.yml — secrets PARTAGÉScat > inventory/group_vars/all/vault.yml <<'EOF'vault_admin_token: "lab80-admin-token-2026"EOF
# webservers/vault.yml — secrets WEBSERVERScat > inventory/group_vars/webservers/vault.yml <<'EOF'vault_web_secret: "web_secret_lab80_xyz"vault_web_db_password: "WebDbPassLab80!"EOFPour l’instant non chiffrés. On va les chiffrer dans l’étape suivante.
Convention vault_* : toutes les variables sensibles sont préfixées. Un grep rapide (grep -r "vault_" .) liste tous les secrets utilisés dans le projet.
Étape 3 — Chiffrer chaque vault.yml
Section intitulée « Étape 3 — Chiffrer chaque vault.yml »ansible-vault encrypt \ inventory/group_vars/all/vault.yml \ inventory/group_vars/webservers/vault.yml \ --vault-password-file=.vault_passwordVérifier :
head -1 inventory/group_vars/all/vault.yml# → $ANSIBLE_VAULT;1.1;AES256
head -1 inventory/group_vars/webservers/main.yml# → http_port: 80 (clair, intact)Étape 4 — Lancer le playbook
Section intitulée « Étape 4 — Lancer le playbook »Le playbook ne fait aucune distinction entre variables claires et chiffrées. Ansible s’occupe de tout.
- name: Lab 80 — Playbook mixte hosts: webservers become: true gather_facts: false
tasks: - name: Pose un fichier qui combine variables claires et chiffrées ansible.builtin.copy: dest: /tmp/lab80-mixte.txt mode: "0600" content: | === Lab 80 — playbook mixte ===
Variables PUBLIQUES (group_vars/<group>/main.yml) : deployment_environment: {{ deployment_environment }} http_port: {{ http_port }} worker_count: {{ worker_count }}
Secrets CHIFFRÉS (group_vars/<group>/vault.yml) : vault_admin_token starts: {{ vault_admin_token[:5] }} vault_web_secret starts: {{ vault_web_secret[:5] }} vault_web_db_password length: {{ vault_web_db_password | length }}ansible-playbook -i inventory/hosts.yml \ --vault-password-file=.vault_password \ playbook.ymlVérifier côté cible :
ssh ansible@web1.lab "sudo cat /tmp/lab80-mixte.txt"Sortie : 6 variables accessibles transparentement depuis un seul namespace, dont 3 chiffrées et 3 claires. La {{ var }} est strictement la même syntaxe pour les deux.
Bénéfice n°1 — diffs Git lisibles
Section intitulée « Bénéfice n°1 — diffs Git lisibles »Modifier le port HTTP :
sed -i 's/http_port: 80/http_port: 8080/' inventory/group_vars/webservers/main.ymlgit diffSortie :
http_port: 80http_port: 8080Une ligne diffable, immédiatement compréhensible en revue de code. Avec un fichier unique chiffré, le diff aurait montré un blob hex de 100+ lignes.
Bénéfice n°2 — lecture sans déchiffrer
Section intitulée « Bénéfice n°2 — lecture sans déchiffrer »Un développeur qui n’a pas le mot de passe vault peut quand même lire :
cat inventory/group_vars/webservers/main.yml# → http_port: 8080# → worker_count: 4Il comprend la config, peut proposer des changements sur les variables publiques (worker_count: 8 par exemple), sans accès aux secrets. Le périmètre du mot de passe vault est limité aux personnes qui doivent réellement modifier les secrets.
Bénéfice n°3 — rotation localisée
Section intitulée « Bénéfice n°3 — rotation localisée »Compromission suspectée des secrets webservers uniquement ?
# Modifier seul vault.yml de webservers, ignorer all/ansible-vault edit inventory/group_vars/webservers/vault.yml \ --vault-password-file=.vault_password# (changer les valeurs, sauver)Aucun toucher à all/vault.yml ni dbservers/vault.yml. La rotation est chirurgicale.
Convention vault_* — pourquoi ce préfixe précis
Section intitulée « Convention vault_* — pourquoi ce préfixe précis »Trois alternatives ont été essayées par la communauté Ansible :
| Préfixe | Avantages | Inconvénients |
|---|---|---|
vault_* | Court, parle à tout Ansible-iste | Aucun |
_secret_* | Souligne la sensibilité | Underscore initial = convention “privé” en Python, prête à confusion |
secure_* | Lisible | Trop générique, déjà utilisé en sysadmin |
vault_* est devenu la convention de facto dans la doc officielle Red Hat et la majorité des rôles Galaxy. Le respecter facilite la lecture par d’autres développeurs et la portabilité des rôles.
Que se passe-t-il si la même variable est définie dans main et vault ?
Section intitulée « Que se passe-t-il si la même variable est définie dans main et vault ? »Ansible suit la précédence standard : le fichier traité en dernier par ordre alphabétique gagne. Avec main.yml et vault.yml, vault.yml gagne car v > m alphabétiquement.
C’est généralement le comportement souhaité : si on définit db_password dans main (placeholder pour debug local) et dans vault (vraie valeur prod), la valeur vault l’emporte.
À tester en cas de doute :
ansible -i inventory/hosts.yml all -m debug -a "var=ma_variable" \ --vault-password-file=.vault_passwordLab pratique
Section intitulée « Lab pratique »Le lab vault/playbooks-mixtes du repo ansible-training reproduit ce parcours avec 4 tests pytest qui valident :
- Les fichiers
main.ymlsont en clair,vault.ymlchiffrés. - Les variables claires et chiffrées sont toutes accessibles dans le playbook.
- La convention
vault_*est respectée. - Le diff Git sur une variable publique reste lisible.
Suivre : labs/vault/playbooks-mixtes/README.md.
Pièges courants
Section intitulée « Pièges courants »- Mauvais emplacement de
group_vars/: doit être au même niveau que l’inventaire (inventory/group_vars/), pas à la racine du projet. Sinon Ansible ne charge pas les variables. - Oubli de
vault_*: un secret nommédb_password(sans préfixe) reste accessible mais on perd la lecture rapide de qui est sensible. - Variables dupliquées entre main et vault : techniquement OK (vault gagne), mais source de confusion. Garder une seule définition.
group_vars/all/vault.ymlnon chiffré : oubli classique. Vérifierhead -1 inventory/group_vars/*/vault.ymlaprès chaque modification.
À retenir
Section intitulée « À retenir »- Pattern
<groupe>/main.yml + vault.yml: variables publiques d’un côté, secrets de l’autre. - Convention
vault_*rend la sensibilité visible dans tout le code (recherchegrep). - Ansible fusionne automatiquement les deux fichiers — un seul namespace côté playbook.
- Diffs Git lisibles sur les variables publiques (changements quotidiens).
- Périmètre vault minimal : seules les personnes qui modifient des secrets ont besoin du mot de passe.
- Rotation localisée : changer un mot de passe d’un seul groupe sans toucher aux autres.