Aller au contenu
Infrastructure as Code medium

Module file Ansible : gérer état, permissions, symlinks

9 min de lecture

Logo Ansible

Le module ansible.builtin.file est le couteau suisse des métadonnées de fichiers. Contrairement à copy:, il ne transfère aucun contenu — il agit uniquement sur l’existence, le mode, le propriétaire, le type (fichier, directory, symlink, hardlink). C’est le module idéal pour préparer une arborescence, créer un lien symbolique vers la release courante, ou supprimer un fichier obsolète.

file: se distingue par son option state: qui prend 6 valeurs : file, directory, absent, link, hard, touch. Maîtriser ces 6 états couvre 95% des cas d’usage.

  • Les 6 états possibles : file, directory, absent, link, hard, touch.
  • Les options recurse: true, force: true et leurs cas d’usage.
  • Quand file: suffit et quand il faut enchaîner avec copy: ou template:.
  • Le piège des liens symboliques cassés (state: link sur cible inexistante).
  • Avoir lu Module copyfile: complète copy:, ne le remplace pas.

state: détermine ce que file: va faire. Chaque valeur a son cas d’usage et ses pièges.

state:ActionIdempotence
file (défaut)Vérifie que la cible est un fichier ; ajuste mode/owner si différentok si déjà fichier avec bonnes perms
directoryCrée le répertoire (et parents si besoin) avec mode/ownerok si déjà directory avec bonnes perms
absentSupprime le fichier ou le répertoire (récursif)ok si déjà absent
linkCrée un lien symbolique : destsrcok si lien existe et pointe au bon endroit
hardCrée un lien physique (hardlink) : dest et src partagent l’inodeok si déjà hardlink
touchCrée le fichier (vide) ou met à jour le mtimetoujours changed (timestamp à jour)

touch est le seul état non-idempotent : il modifie systématiquement le mtime. Utiliser uniquement quand on veut explicitement marquer un timestamp (init, healthcheck).

- name: Repertoire de logs applicatifs
ansible.builtin.file:
path: /var/log/myapp
state: directory
owner: nobody
group: nobody
mode: "0750"

Si /var/log/myapp n’existe pas, il est créé. S’il existe avec mode 0755 et owner root, il est ajusté à 0750 + nobody. S’il existe déjà comme prévu, la tâche est ok.

Création récursive : par défaut, file: state: directory crée les répertoires parents manquants (équivalent mkdir -p). Pas besoin de tâche préalable pour /var/log/.

Pattern classique pour le déploiement par releases : /opt/myapp/current est un symlink vers la release active.

- name: Pointer current vers la release courante
ansible.builtin.file:
src: /opt/myapp/releases/v1.2.0
dest: /opt/myapp/current
state: link
force: true

force: true est nécessaire si dest est déjà un fichier (non symlink) — sans force, la tâche échoue. Avec force, le fichier existant est remplacé par le symlink.

Piège lien cassé : si src n’existe pas au moment de la création, Ansible crée un symlink cassé sans erreur. Pour échouer si src est absent, ajouter une vérification préalable avec stat: + assert:.

- name: Nettoyer une ancienne config
ansible.builtin.file:
path: /etc/old-config.conf
state: absent

absent est récursif : si path est un répertoire, tout est supprimé (équivalent rm -rf). À utiliser avec précaution — pas de --check automatique en production.

Uniquement valable pour state: directory. Propage mode/owner/group à toute l’arborescence.

- name: Reparer les permissions sur /etc/myapp
ansible.builtin.file:
path: /etc/myapp
state: directory
owner: root
group: myapp
mode: "0750"
recurse: true

recurse: true est puissant mais lent sur de grosses arborescences (Ansible parcourt chaque inode). Pour un répertoire de 50K fichiers, préférer une commande shell unique avec chown -R.

- name: Marquer le timestamp d init
ansible.builtin.file:
path: /var/log/myapp-init.timestamp
state: touch
mode: "0644"

Le fichier est créé vide s’il n’existe pas, ou son mtime mis à jour s’il existe. Utile pour des flags d’initialisation ou des healthchecks basés sur la date du fichier.

SymptômeCauseFix
Symlink cassé sans erreursrc n’existe pas au moment de state: linkVérifier src avec stat: + assert: avant
mode: non appliqué récursivementOubli de recurse: trueAjouter recurse: true (state=directory uniquement)
state: absent supprime tout un dossier sans warningC’est le comportement par défaut (récursif)Toujours tester en --check avant
force: true ignoréMauvais state: (force ne sert que pour link/hard)force: true n’a d’effet que pour les liens
  • file: gère les métadonnées uniquement — pour le contenu, utiliser copy: ou template:.
  • state: = file / directory / absent / link / hard / touch — 6 cas couvrant 95% des besoins.
  • recurse: true propage mode/owner sur toute l’arborescence (lent sur gros volumes).
  • force: true n’a de sens que pour state: link ou hard — remplace un fichier existant.
  • state: touch est le seul état non-idempotent — toujours changed.

Cette page a un lab d’accompagnement : labs/modules-fichiers/file/ dans stephrobert/ansible-training.

Challenge — sur web1.lab :

  1. Créer /opt/myapp/releases/v1.0.0 avec mode 0755.
  2. Créer /opt/myapp/shared/logs avec mode 0750, owner nobody.
  3. Créer un symlink /opt/myapp/current/opt/myapp/releases/v1.0.0.
  4. Supprimer /etc/myapp-old.conf s’il existe.
  5. Touch /var/log/myapp-init.timestamp mode 0644.

Validation pytest+testinfra :

Fenêtre de terminal
ansible-playbook solution.yml
pytest -v labs/modules-fichiers/file/challenge/tests/

5 tests vérifient l’existence, le type (directory/symlink/file), le mode et l’owner.

Ce site vous est utile ?

Sachez que moins de 1% des lecteurs soutiennent ce site.

Je maintiens +700 guides gratuits, sans pub ni tracing. Aujourd'hui, ce site ne couvre même pas mes frais d'hébergement, d'électricité, de matériel, de logiciels, mais surtout de cafés.

Un soutien régulier, même symbolique, m'aide à garder ces ressources gratuites et à continuer de produire des guides de qualité. Merci pour votre appui.

Abonnez-vous et suivez mon actualité DevSecOps sur LinkedIn