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
Sommaire
- Comprendre le module copy d’Ansible
- Les paramètres essentiels du module copy
- Copier des fichiers simples vers un serveur distant
- Créer du contenu inline avec le paramètre content
- Copier des répertoires et fichiers multiples
- Gestion des permissions et de la sécurité
- Bonnes pratiques et pièges à éviter
- Copy vs template vs fetch : quel module choisir
- Cas d’usage avancés en production
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.

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

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.

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.
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.Quelle est la différence entre copy et template dans Ansible ?
Utilisez une boucle loop avec le module copy. Listez vos fichiers dans la directive loop et référencez chaque élément avec Comment copier plusieurs fichiers en une seule tâche Ansible ?
{{ 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.
Ajoutez un slash à la fin du chemin src pour copier le contenu du répertoire : Comment copier un répertoire entier avec ses sous-dossiers ?
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.
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.Le module copy est-il idempotent ?
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.Comment sécuriser la copie de fichiers sensibles avec Ansible ?
Formatrice IT indépendante depuis 2016, ancienne étudiante BTS SIO SLAM. 6 ans d'expérience en entreprise.