Ansible Copy Module Examples for Remote Servers
The Ansible copy module copies a file or directory from the local machine (or the control node) to a remote server. You provide the source path, the destination path, and optionally set permissions, ownership, and backup behavior. This article shows practical examples, explains how the module works, and covers common pitfalls.
Basic Syntax and Parameters
The simplest playbook task using copy looks like this:
- name: Copy a file
ansible.builtin.copy:
src: /local/path/file.txt
dest: /remote/path/file.txt
Key parameters you will use often:
src– source file or directory on the control node. If it is a directory, the entire directory is copied recursively.dest– absolute path on the remote host. Ifsrcis a directory,destis the parent directory where the source directory will be placed.ownerandgroup– set the file ownership on the remote host.mode– set file permissions, e.g.,0644or'u=rw,g=r,o=r'.backup– ifyes, create a timestamped backup of the remote file if it differs from the source.force– ifno, the file is only copied if the destination does not exist.content– instead ofsrc, you can provide the file content directly as a string.
Copying a Single File
The most common use is copying a configuration file. For example, to deploy an NGINX configuration:
- name: Deploy nginx config
ansible.builtin.copy:
src: files/nginx.conf
dest: /etc/nginx/nginx.conf
owner: root
group: root
mode: '0644'
Note the quotes around 0644 – without them, YAML would interpret it as a number and the leading zero would be lost, resulting in wrong permissions.
Copying a Directory
To copy an entire directory, point src to the directory. The behavior depends on a trailing slash:
src: mydir– copies the directory itself todest, creatingdest/mydir.src: mydir/– copies the contents ofmydirdirectly intodest.
Example:
- name: Copy website files
ansible.builtin.copy:
src: public/
dest: /var/www/html/
owner: www-data
group: www-data
mode: '0755'
Using content Instead of a File
When the file content is short or generated dynamically, use content:
- name: Create a simple file
ansible.builtin.copy:
dest: /etc/motd
content: |
Welcome to this server.
Managed by Ansible.
owner: root
group: root
mode: '0644'
This is useful for templates that do not need variables; for variable substitution, use the template module instead.
Setting Permissions and Ownership
You can set permissions using octal notation (e.g., 0644) or symbolic (e.g., u=rw,g=r,o=r). Ownership is set with owner and group – the remote user must have privileges to change ownership, so run the task with become: yes if needed.
Example with symbolic mode:
- name: Copy script with specific permissions
ansible.builtin.copy:
src: script.sh
dest: /usr/local/bin/script.sh
mode: 'u=rwx,g=rx,o=rx'
Backup and Force Options
If the destination file already exists and differs from the source, Ansible will overwrite it by default. To keep a backup, set backup: yes – the old file is saved with a timestamp suffix. To avoid overwriting an existing file, set force: no – the task will skip if the destination exists.
- name: Copy with backup
ansible.builtin.copy:
src: config.yml
dest: /etc/app/config.yml
backup: yes
Common Mistakes and Troubleshooting
- Missing quotes on mode – as mentioned, always quote the mode.
- Trailing slash confusion – forgetting the trailing slash on a directory source can create an unexpected nested directory.
- Permission denied – when writing to protected paths like
/etc, usebecome: yes. - File always shows as changed – if the source file changes every run (e.g., timestamps), the copy module will report changed. Use
checksumto verify, or consider thetemplatemodule if content is dynamic. - Copying between remote hosts – the
copymodule only copies from the control node to the remote. To copy between two remote hosts, use thefetchmodule to download first, then copy, or usesynchronizewithdelegate_to.
Frequently Asked Questions
Can I copy a file from one remote server to another?
No, the copy module only works from the control node to a remote host. To transfer between remotes, use fetch to pull the file to the control node, then copy to push it to the second host, or use synchronize with the delegate_to parameter.
What is the difference between copy and template?copy copies a static file as-is. template processes a Jinja2 template file, allowing you to substitute variables and use loops/conditionals. Use template when the file content depends on host variables.
How do I copy a file only if it doesn’t exist?
Set force: no. The task will skip if the destination already exists, regardless of content.
Why does my copy task always report ‘changed’?
This usually happens when the source file changes on every run (e.g., it contains a timestamp or a build ID). Ansible compares checksums; if they differ, it copies. If you want to avoid unnecessary copies, ensure the source file is stable, or use template with a fixed output.
Can I copy a file with special characters in the path?
Yes, but you must quote the path properly in YAML. Use single quotes for paths with spaces or special characters, e.g., src: '/path/with space/file.txt'.
Does copy module preserve file attributes like SELinux context?
By default, it does not preserve SELinux context. You can set setype, seuser, serole parameters, or use synchronize with rsync_opts to preserve attributes.
Related
Method: the standard formula for this calculation, rounded as each result states. See how the calculators work or report an error.