Ansible Create File with Content: copy Module content Parameter
By Luca Berton · Published 2024-01-01 · Category: linux-administration
How to create files with content in Ansible using the copy module content parameter. Write text, YAML, JSON to files without templates.

I'm going to show you a live Playbook with some simple Ansible code. I'm Luca Berton and welcome to today's episode of Ansible Pilot.
Ansible create a text file
Today we're talking about Ansible modulecopy.
The full name is ansible.builtin.copy which means is part of the collection of modules "builtin" with ansible and shipped with it.
This module is pretty stable and out for years.
The purpose is to copy files to remote locations but it's also capable to create some simple text files.
If you need a more complex configuration it's better to rely on the template module.
See also: Ansible Create Empty File: Touch Files with file Module (Guide)
Parameters
• dest path - destination file • content string - text • mode/owner/group - permission • setype/seuser/selevel - SELinuxThe parameter list is pretty wide but I'll summarize the most useful for the use case.
The only required parameter is "dest" which specifies the remote absolute path destination.
The content parameter sets the contents of a file directly to the specified value. It works only when dest is a file/
Please note that if you use a variable in the content parameter will result in unpredictable output.
For advanced formatting or if the content contains a variable, use the ansible.builtin.template module.
Let me also highlight that we could also specify the permissions and SELinux properties.
## Playbook Let's jump into a real-life playbook on how to create an empty file with Ansible.
code
• copy.yml---
- name: copy module Playbook
hosts: all
vars:
myfile: "{{ ~/example.txt }}"
tasks:
- name: create a text file
ansible.builtin.copy:
dest: "{{ myfile }}"
content: |
line 1
line 2
Conclusion
Now you know better how to create a text file with Ansible.
See also: Ansible Rename File: Move & Rename Files with copy + file Modules
Advanced copy Module Examples
Write multi-line content
- name: Create config file with multiple lines
ansible.builtin.copy:
content: |
[database]
host = db.example.com
port = 5432
name = myapp
user = {{ db_user }}
password = {{ db_password }}
dest: /etc/myapp/database.conf
owner: appuser
group: appuser
mode: '0600'
become: true
Write variable content to file
- name: Gather system info
ansible.builtin.setup:
gather_subset: network
- name: Save IP address to file
ansible.builtin.copy:
content: "{{ ansible_default_ipv4.address }}"
dest: /etc/myapp/server_ip.txt
mode: '0644'
Copy file from controller to remote
- name: Copy local file to remote host
ansible.builtin.copy:
src: files/nginx.conf
dest: /etc/nginx/nginx.conf
owner: root
group: root
mode: '0644'
backup: true # Create backup of existing file
become: true
notify: restart nginx
Create file only if it doesn't exist
- name: Create default config (don't overwrite)
ansible.builtin.copy:
content: |
# Default configuration
debug: false
log_level: info
dest: /etc/myapp/config.yml
force: false # Don't overwrite if file exists
mode: '0644'
become: true
Save command output to file
- name: Run diagnostic command
ansible.builtin.command: df -h
register: disk_info
changed_when: false
- name: Save output to file
ansible.builtin.copy:
content: "{{ disk_info.stdout }}"
dest: /tmp/disk_report.txt
mode: '0644'
copy vs template vs lineinfile
| Module | Best For |
|--------|----------|
| copy (content=) | Static text, simple variable substitution |
| copy (src=) | Copying files from controller |
| template | Complex Jinja2 templates with loops/conditions |
| lineinfile | Modifying a single line in existing files |
| blockinfile | Adding/replacing a block in existing files |
See also: Ansible Create Symlink: file Module with state=link (Guide)
Key Parameters
| Parameter | Type | Description |
|-----------|------|-------------|
| content | string | Text content to write |
| src | string | Local file to copy |
| dest | string | Remote destination path |
| mode | string | File permissions (e.g., '0644') |
| owner | string | File owner |
| group | string | File group |
| force | bool | Overwrite if exists (default: true) |
| backup | bool | Create backup before overwriting |
| validate | string | Command to validate before replacing |
FAQ
How do I write JSON content to a file?
- name: Write JSON config
ansible.builtin.copy:
content: "{{ my_dict | to_nice_json }}"
dest: /etc/myapp/config.json
mode: '0644'
How do I append to a file instead of overwriting?
copy always overwrites. Use lineinfile or blockinfile to add content, or use shell:
- name: Append line to file
ansible.builtin.lineinfile:
path: /etc/myapp/app.log
line: "Deployed at {{ ansible_date_time.iso8601 }}"
create: true
What's the maximum content size for copy?
There's no hard limit, but for large files (>1MB), use src instead of content for better performance. For templates with complex logic, use the template module.
Create File with Content
- name: Create config file
ansible.builtin.copy:
content: |
# Application Config
DB_HOST=db.internal
DB_PORT=5432
LOG_LEVEL=info
dest: /etc/myapp/.env
owner: deploy
group: deploy
mode: '0600'
become: true
Copy from Controller
- copy:
src: files/nginx.conf
dest: /etc/nginx/nginx.conf
owner: root
mode: '0644'
backup: true # Keep backup of original
become: true
notify: restart nginx
Copy with Variables
- copy:
content: |
APP_NAME={{ app_name }}
APP_PORT={{ app_port }}
APP_ENV={{ env }}
DB_HOST={{ db_host }}
dest: /opt/myapp/.env
mode: '0600'
become: true
Copy Multiple Files
- copy:
src: "{{ item.src }}"
dest: "{{ item.dest }}"
mode: "{{ item.mode | default('0644') }}"
loop:
- { src: app.conf, dest: /etc/myapp/app.conf }
- { src: logging.conf, dest: /etc/myapp/logging.conf }
- { src: deploy.sh, dest: /opt/scripts/deploy.sh, mode: '0755' }
become: true
Create JSON File
- copy:
content: "{{ config_data | to_nice_json }}"
dest: /etc/myapp/config.json
mode: '0644'
become: true
Create YAML File
- copy:
content: "{{ config_data | to_nice_yaml }}"
dest: /etc/myapp/config.yml
mode: '0644'
become: true
Backup Before Overwrite
- copy:
src: new-config.conf
dest: /etc/myapp/config.conf
backup: true # Creates timestamped backup
become: true
Remote to Remote Copy
- copy:
src: /opt/myapp/config.yml
dest: /opt/myapp/config.yml.bak
remote_src: true
become: true
copy vs template
| Feature | copy | template |
|---------|------|----------|
| Static files | ✅ | ✅ |
| Jinja2 processing | ❌ | ✅ |
| Inline content | ✅ (content:) | ❌ |
| Variable substitution | Limited | Full |
| Loops/conditionals | ❌ | ✅ |
Key Parameters
| Parameter | Description |
|-----------|-------------|
| src | Source file on controller |
| dest | Destination path on remote |
| content | Inline file content |
| owner | File owner |
| group | File group |
| mode | File permissions |
| backup | Create backup before overwrite |
| remote_src | Source is on remote host |
| force | Overwrite if different (default: true) |
| validate | Command to validate before placing |
FAQ
copy vs template for config files?
Use copy for static files or inline content: with simple variable substitution. Use template when you need Jinja2 logic (loops, conditionals).
How do I avoid overwriting a file?
- copy:
content: "initial content"
dest: /etc/myapp/config
force: false # Don't overwrite if exists
Can I copy a directory?
Yes — if src is a directory (with trailing /), copy transfers all contents. Without trailing /, it copies the directory itself.
Related Articles
• Jinja2 templating in Ansible • role-based playbook organization in AnsibleCategory: linux-administration
Watch the video: Ansible Create File with Content: copy Module content Parameter — Video Tutorial