You are currently viewing Ansible Copy : guide complet du module en pratique

Ansible Copy : guide complet du module en pratique

  • Auteur/autrice de la publication :
  • Post category:DevOps

Dans cet article

  • Le module ansible copy transfère des fichiers du contrôleur vers les machines distantes en une seule tâche
  • Le paramètre content permet d’écrire du texte directement dans un fichier sans source locale
  • Les permissions se règlent avec mode, owner et group pour garantir la sécurité des fichiers déployés
  • La copie récursive d’un répertoire complet s’active avec directory_mode et un slash final sur src
  • Le paramètre backup: yes crée automatiquement une sauvegarde horodatée avant tout écrasement
  • Pour les fichiers contenant des variables Jinja2, préférez le module template plutôt que copy

Comprendre le module copy d’Ansible

Quand je forme mes étudiants en BTS SIO à l’automatisation d’infrastructure, le module ansible copy fait partie des premiers que je leur présente. C’est la brique fondamentale pour transférer des fichiers depuis le contrôleur Ansible vers une ou plusieurs machines distantes. Sans ce module, impossible de déployer proprement un fichier de configuration, un script ou un certificat sur vos serveurs.

Le principe est simple : vous indiquez un fichier source sur votre machine locale (celle qui exécute Ansible) et une destination sur la machine cible. Ansible se charge du transfert via SSH, vérifie l’idempotence (le fichier n’est copié que s’il diffère de la version distante) et applique les permissions que vous avez définies. Ce comportement idempotent est fondamental : relancer le playbook dix fois ne modifie rien si le fichier est déjà en place.

Le module copy ansible appartient à la collection ansible.builtin, ce qui signifie qu’il est disponible nativement sans installation supplémentaire. Selon la documentation officielle du module copy, il supporte le transfert de fichiers individuels, de répertoires entiers et même la création de contenu à la volée. Si vous travaillez déjà avec Ansible Tower pour orchestrer vos déploiements, ce module sera omniprésent dans vos playbooks.

Les paramètres essentiels du module copy

Avant de plonger dans les exemples, je vous recommande de bien maîtriser les paramètres disponibles. Voici ceux que j’utilise le plus souvent en production et que je détaille systématiquement à mes étudiants.

Paramètre Obligatoire Description Valeur par défaut
src Non* Chemin du fichier source sur le contrôleur
dest Oui Chemin de destination sur la machine distante
content Non* Texte à écrire directement dans le fichier distant
mode Non Permissions du fichier (ex : 0644, u+rw) Permissions système
owner Non Propriétaire du fichier distant Utilisateur distant
group Non Groupe du fichier distant Groupe par défaut
backup Non Créer une sauvegarde avant écrasement no
force Non Écraser même si le fichier existe déjà yes
remote_src Non La source est déjà sur la machine distante no
validate Non Commande de validation avant application
directory_mode Non Permissions pour les répertoires créés lors d’une copie récursive

* src et content sont mutuellement exclusifs : vous utilisez l’un ou l’autre, jamais les deux en même temps. Le paramètre dest reste toujours obligatoire.

Copier des fichiers simples vers un serveur distant

Commençons par le cas le plus courant : copier un fichier de configuration depuis votre poste de travail vers un serveur. C’est typiquement ce que vous faites quand vous déployez un fichier nginx.conf, un certificat SSL ou un script de maintenance.

---
- name: Déployer la configuration Nginx
  hosts: webservers
  become: yes
  tasks:
    - name: Copier le fichier de configuration Nginx
      ansible.builtin.copy:
        src: files/nginx.conf
        dest: /etc/nginx/nginx.conf
        owner: root
        group: root
        mode: '0644'
      notify: Redémarrer Nginx

  handlers:
    - name: Redémarrer Nginx
      ansible.builtin.service:
        name: nginx
        state: restarted

Plusieurs points importants dans cet exemple. D’abord, le chemin src est relatif au répertoire files/ de votre rôle ou de votre playbook. Ansible cherche automatiquement dans ce dossier. Ensuite, j’ai associé un handler qui redémarre Nginx uniquement si le fichier a été modifié. C’est l’idempotence en action : pas de redémarrage inutile.

La syntaxe YAML du module copy reste simple même pour les débutants en automatisation
La syntaxe YAML du module copy reste simple même pour les débutants en automatisation

Pour copier un fichier sur une machine distante (ansible copy file on remote), il suffit d’activer remote_src: yes. Dans ce cas, Ansible copie un fichier qui existe déjà sur le serveur cible vers un autre emplacement du même serveur :

- name: Copier un fichier déjà présent sur le serveur
  ansible.builtin.copy:
    src: /tmp/app-config.yml
    dest: /opt/myapp/config.yml
    remote_src: yes
    mode: '0640'

Le paramètre backup est une sécurité que je recommande systématiquement en production. Avec backup: yes, Ansible crée une copie horodatée du fichier existant avant de le remplacer. Vous pouvez ainsi revenir en arrière manuellement si nécessaire.

Créer du contenu inline avec le paramètre content

Le paramètre content est une alternative au paramètre src. Au lieu de copier un fichier existant, vous écrivez directement le contenu dans le playbook. C’est particulièrement utile pour les fichiers courts comme un flag de maintenance, un fichier .env ou un marqueur de déploiement.

- name: Créer un fichier de maintenance
  ansible.builtin.copy:
    content: |
      MAINTENANCE=true
      DEPLOY_DATE={{ ansible_date_time.iso8601 }}
      VERSION=2.4.1
    dest: /opt/myapp/.maintenance
    owner: deploy
    group: deploy
    mode: '0644'

Attention : même si vous pouvez intégrer des variables Jinja2 dans content, cette fonctionnalité reste limitée. Pour des fichiers de configuration complexes avec de la logique conditionnelle, des boucles ou des filtres avancés, je vous oriente vers le module ansible template qui est conçu pour cela.

Un autre usage fréquent du paramètre content consiste à générer des fichiers de configuration à partir de variables d’inventaire :

- name: Générer le fichier hosts personnalisé
  ansible.builtin.copy:
    content: |
      # Fichier généré par Ansible - ne pas modifier
      127.0.0.1 localhost
      {{ ansible_default_ipv4.address }} {{ inventory_hostname }}
    dest: /etc/hosts.ansible
    mode: '0644'
    backup: yes

Copier des répertoires et fichiers multiples

La question revient constamment dans mes formations : comment copier plusieurs fichiers ou un répertoire entier avec ansible copy ? Le module gère nativement la copie récursive de répertoires. Il suffit d’ajouter un slash à la fin du chemin source pour copier le contenu du répertoire.

- name: Copier tout le répertoire de configuration
  ansible.builtin.copy:
    src: files/app-config/
    dest: /opt/myapp/config/
    owner: deploy
    group: deploy
    directory_mode: '0755'
    mode: '0644'

Le slash final sur src est capital. Avec src: files/app-config/, Ansible copie le contenu du répertoire. Sans le slash (src: files/app-config), il copie le répertoire lui-même, créant ainsi un sous-dossier /opt/myapp/config/app-config/. C’est une source d’erreur classique que je vois régulièrement.

Pour copier plusieurs fichiers individuels (ansible copy multiple files), vous avez deux approches. La première utilise une boucle loop :

- name: Copier plusieurs fichiers de configuration
  ansible.builtin.copy:
    src: "files/{{ item }}"
    dest: "/etc/myapp/{{ item }}"
    owner: root
    group: root
    mode: '0644'
  loop:
    - database.yml
    - redis.yml
    - smtp.yml
    - logging.yml
Ansible copy transfère les fichiers vers des serveurs distants via une connexion SSH sécurisée
Ansible copy transfère les fichiers vers des serveurs distants via une connexion SSH sécurisée

La seconde approche, que je privilégie quand les fichiers ont des permissions différentes, utilise une liste de dictionnaires :

- name: Copier des fichiers avec des permissions distinctes
  ansible.builtin.copy:
    src: "{{ item.src }}"
    dest: "{{ item.dest }}"
    owner: "{{ item.owner }}"
    mode: "{{ item.mode }}"
  loop:
    - { src: 'files/app.conf', dest: '/etc/myapp/app.conf', owner: 'root', mode: '0644' }
    - { src: 'files/secrets.conf', dest: '/etc/myapp/secrets.conf', owner: 'root', mode: '0600' }
    - { src: 'files/start.sh', dest: '/usr/local/bin/start.sh', owner: 'deploy', mode: '0755' }

Si vous devez copier tous les fichiers d’un répertoire (ansible copy all files in directory) tout en filtrant certains types, combinez copy avec le module find ou utilisez with_fileglob :

- name: Copier uniquement les fichiers .conf
  ansible.builtin.copy:
    src: "{{ item }}"
    dest: /etc/myapp/conf.d/
    mode: '0644'
  with_fileglob:
    - files/conf.d/*.conf

Gestion des permissions et de la sécurité

La gestion des permissions est un aspect critique que je détaille toujours longuement avec mes étudiants. Un fichier de configuration mal sécurisé peut exposer des mots de passe ou des clés API. Le module copy ansible offre un contrôle granulaire sur les permissions UNIX.

Le paramètre mode accepte deux formats. Le format octal ('0644') que je recommande pour sa clarté, et le format symbolique ('u=rw,g=r,o=r'). Attention : en YAML, les valeurs octales doivent être entourées de guillemets pour éviter une interprétation incorrecte.

- name: Copier une clé privée avec permissions strictes
  ansible.builtin.copy:
    src: files/ssl/private.key
    dest: /etc/ssl/private/myapp.key
    owner: root
    group: ssl-cert
    mode: '0640'
  no_log: true

Le paramètre no_log: true empêche Ansible d’afficher le contenu du fichier dans les logs. C’est indispensable pour les fichiers sensibles comme les clés privées ou les fichiers contenant des mots de passe. Pour sécuriser davantage vos données sensibles, je vous recommande d’utiliser Ansible Vault afin de chiffrer les fichiers avant de les stocker dans votre dépôt Git.

Le paramètre validate est une sécurité supplémentaire que j’apprécie particulièrement. Il exécute une commande de validation sur le fichier temporaire avant de le placer à sa destination finale. Si la validation échoue, le fichier existant reste intact :

- name: Copier la configuration Apache avec validation
  ansible.builtin.copy:
    src: files/apache2.conf
    dest: /etc/apache2/apache2.conf
    owner: root
    group: root
    mode: '0644'
    validate: '/usr/sbin/apache2ctl -t -f %s'
    backup: yes

La variable %s est remplacée par le chemin du fichier temporaire. Si apache2ctl -t détecte une erreur de syntaxe, la copie est annulée. C’est un filet de sécurité essentiel pour éviter de casser un service en production.

Bonnes pratiques et pièges à éviter

Après plusieurs années à déployer des infrastructures avec Ansible et à former des étudiants en BTS SIO SISR, j’ai identifié des erreurs récurrentes et des pratiques qui font la différence en production. Voici mes recommandations.

Structurez vos fichiers sources correctement. Placez vos fichiers dans le répertoire files/ de votre rôle. Ansible résout automatiquement les chemins relatifs en cherchant dans cet ordre : files/ du rôle, files/ du playbook, puis le répertoire courant. Respecter cette convention facilite la maintenance et la collaboration.

mon-role/
├── files/
│   ├── nginx.conf
│   ├── ssl/
│   │   ├── cert.pem
│   │   └── key.pem
│   └── scripts/
│       └── deploy.sh
├── tasks/
│   └── main.yml
└── handlers/
    └── main.yml

Évitez de copier des fichiers volumineux. Le module copy transfère les fichiers via SSH en les encodant en base64, ce qui augmente la taille du transfert d’environ 33 %. Pour des fichiers de plusieurs centaines de mégaoctets, préférez le module synchronize (basé sur rsync) ou get_url pour télécharger depuis un serveur de fichiers.

Utilisez force: no pour les fichiers initiaux. Si vous voulez copier un fichier uniquement s’il n’existe pas encore sur la cible (sans écraser une version personnalisée manuellement), activez force: no :

- name: Copier la config par défaut sans écraser
  ansible.builtin.copy:
    src: files/default-config.yml
    dest: /opt/myapp/config.yml
    force: no
    mode: '0644'

Attention au checksum. Ansible utilise un hash MD5 (ou SHA1 selon la configuration) pour déterminer si le fichier distant diffère du fichier source. Si vous utilisez content avec des variables qui changent à chaque exécution (comme une date), le fichier sera réécrit à chaque lancement du playbook, brisant l’idempotence.

Les bonnes pratiques Ansible copy s'acquièrent par la pratique et le travail en équipe
Les bonnes pratiques Ansible copy s’acquièrent par la pratique et le travail en équipe

Si vous êtes en phase d’apprentissage de l’automatisation d’infrastructure, le métier de DevOps Engineer repose précisément sur la maîtrise de ces outils. La copie de fichiers est un fondement, mais c’est la combinaison de modules qui crée des déploiements robustes.

Copy vs template vs fetch : quel module choisir

Une question que mes étudiants me posent fréquemment : quand utiliser copy, quand passer à template, et à quoi sert fetch ? Voici un tableau comparatif pour y voir clair.

Critère copy template fetch
Direction Contrôleur → distant Contrôleur → distant Distant → contrôleur
Variables Jinja2 Non (sauf content) Oui, plein support Non applicable
Boucles et conditions Non Oui Non applicable
Fichiers binaires Oui Non recommandé Oui
Cas d’usage type Fichiers statiques, scripts, certificats Fichiers de config dynamiques Récupérer logs, sauvegardes
Performance gros fichiers Moyenne (base64) Moyenne (base64) Moyenne
Idempotence Oui (checksum) Oui (checksum) Oui

Ma règle simple : si votre fichier contient des variables Jinja2 ou de la logique conditionnelle, utilisez ansible template. Si c’est un fichier statique (un binaire, un certificat, un script sans variable), copy suffit. Pour récupérer un fichier depuis un serveur distant vers votre contrôleur, c’est fetch qu’il faut utiliser.

Le transfert de fichiers depuis un hôte vers une machine distante (ansible copy from host to remote) reste le cas d’usage principal du module copy. Si vous avez besoin du chemin inverse, pensez à fetch plutôt qu’à tenter des contournements avec remote_src et delegate_to.

Cas d’usage avancés en production

Pour terminer ce guide, je partage quelques patterns que j’utilise régulièrement en production et que j’enseigne à mes étudiants les plus avancés. Ces exemples illustrent la puissance du module ansible-copy quand il est combiné avec d’autres fonctionnalités d’Ansible.

Déploiement conditionnel avec register

Vous pouvez capturer le résultat de la copie pour déclencher des actions conditionnelles :

- name: Copier la configuration applicative
  ansible.builtin.copy:
    src: files/app.conf
    dest: /etc/myapp/app.conf
    mode: '0644'
  register: config_result

- name: Afficher un message si le fichier a changé
  ansible.builtin.debug:
    msg: "Configuration mise à jour, redémarrage nécessaire"
  when: config_result.changed

- name: Redémarrer l'application
  ansible.builtin.systemd:
    name: myapp
    state: restarted
  when: config_result.changed

Copie depuis un serveur bastion

Dans les architectures sécurisées, vous devez parfois copier un fichier via un jump host. Ansible gère cela via la configuration SSH dans votre inventaire, sans modifier la tâche copy elle-même. Selon les recommandations de la ANSSI sur l’usage sécurisé d’OpenSSH, utilisez ProxyJump plutôt que ProxyCommand pour les connexions via bastion.

Copie avec vérification d’intégrité

Pour les déploiements critiques, combinez copy avec le module stat pour vérifier le checksum après transfert :

- name: Copier le binaire applicatif
  ansible.builtin.copy:
    src: files/myapp-v2.4.1
    dest: /opt/myapp/bin/myapp
    mode: '0755'
    checksum: 'sha256:e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855'

- name: Vérifier l'intégrité du binaire
  ansible.builtin.stat:
    path: /opt/myapp/bin/myapp
    checksum_algorithm: sha256
  register: binary_stat

- name: Confirmer le checksum
  ansible.builtin.assert:
    that:
      - binary_stat.stat.checksum == 'e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855'
    fail_msg: "Erreur d'intégrité sur le binaire déployé"

Déploiement multi-environnement

En utilisant les variables de groupe, vous pouvez déployer des fichiers différents selon l’environnement. C’est un pattern que j’utilise systématiquement pour gérer les configurations de staging et de production :

- name: Copier la configuration spécifique à l'environnement
  ansible.builtin.copy:
    src: "files/{{ env }}/application.properties"
    dest: /opt/myapp/application.properties
    mode: '0640'
    owner: deploy
    backup: yes

La variable env est définie dans les group_vars : staging pour le groupe de serveurs de préproduction, production pour la prod. C’est propre, maintenable et sans surprise. Ce type d’architecture est exactement ce que l’on attend d’un professionnel en alternance développement informatique ou d’un ingénieur en poste.

Pour les environnements conteneurisés, sachez que le module copy fonctionne aussi avec les connexions Docker et Kubernetes. Si vous travaillez avec des conteneurs, consultez notre guide sur Symfony et Docker pour comprendre comment structurer vos déploiements. L’utilisation d’images Docker bien construites réduit d’ailleurs le besoin de copier des fichiers manuellement dans les conteneurs.

Le module ansible copy reste un outil incontournable dans la boîte à outils de tout administrateur système ou DevOps Engineer. Sa simplicité d’utilisation cache une puissance réelle quand il est combiné avec les autres modules de la collection builtin. Si vous maîtrisez les concepts présentés dans ce guide, vous avez les bases solides pour automatiser la gestion de fichiers sur n’importe quelle infrastructure.

À retenir

  • Utilisez src pour les fichiers existants et content pour le texte inline, jamais les deux ensemble
  • Ajoutez backup: yes systématiquement en production pour créer une sauvegarde avant écrasement
  • Mettez les permissions en mode octal entre guillemets (‘0644’) pour éviter les erreurs YAML
  • Passez à template dès que votre fichier contient de la logique Jinja2 complexe
  • Activez validate pour les fichiers de configuration critiques (Apache, Nginx, sudoers)

Questions fréquentes


Comment copier un fichier avec Ansible copy ?

Utilisez le module ansible.builtin.copy avec les paramètres src (chemin local du fichier) et dest (chemin distant). Exemple : ansible.builtin.copy: src=files/config.yml dest=/etc/myapp/config.yml mode='0644'. Ansible transfère le fichier via SSH et vérifie l’idempotence grâce au checksum.

Quelle est la différence entre copy et template dans Ansible ?

Le module copy transfère un fichier tel quel, sans interprétation. Le module template traite les variables Jinja2, les boucles et les conditions avant de transférer le résultat. Utilisez copy pour les fichiers statiques (scripts, binaires, certificats) et template pour les fichiers de configuration dynamiques contenant des variables.

Comment copier plusieurs fichiers en une seule tâche Ansible ?

Utilisez une boucle loop avec le module copy. Listez vos fichiers dans la directive loop et référencez chaque élément avec {{ item }} dans les paramètres src et dest. Pour des fichiers avec des permissions différentes, utilisez une liste de dictionnaires contenant src, dest, owner et mode pour chaque fichier.

Comment copier un répertoire entier avec ses sous-dossiers ?

Ajoutez un slash à la fin du chemin src pour copier le contenu du répertoire : src: files/monrepertoire/. Sans le slash, Ansible copie le répertoire lui-même comme sous-dossier de la destination. Utilisez directory_mode pour définir les permissions des répertoires créés automatiquement.

Le module copy est-il idempotent ?

Oui, le module copy est entièrement idempotent. Ansible compare le checksum du fichier source avec celui du fichier distant. Si les deux sont identiques, aucune copie n’est effectuée et la tâche affiche le statut « ok » au lieu de « changed ». Cela permet de relancer un playbook sans effet de bord.

Comment sécuriser la copie de fichiers sensibles avec Ansible ?

Combinez plusieurs mesures : utilisez mode ‘0600’ pour restreindre les permissions, ajoutez no_log: true pour masquer le contenu dans les logs, et chiffrez les fichiers sensibles avec Ansible Vault avant de les stocker dans votre dépôt. Pour les clés privées, attribuez owner et group à l’utilisateur du service uniquement.


Lucie Moreau
Lucie Moreau

Formatrice IT indépendante depuis 2016, ancienne étudiante BTS SIO SLAM. 6 ans d'expérience en entreprise.

Lucie Moreau

Formatrice IT indépendante depuis 2016, ancienne étudiante BTS SIO SLAM. 6 ans d'expérience en entreprise.