Introduction

The ansible.builtin.file module with state: touch creates an empty file if it doesn't exist, or updates its modification timestamp if it does — exactly like the Unix touch command. Use it to create marker files, initialize logs, or signal task completion.

Quick Reference

# Create empty file (or update timestamp)
- ansible.builtin.file:
    path: /tmp/marker.txt
    state: touch

# Create with specific permissions
- ansible.builtin.file:
    path: /var/log/myapp/app.log
    state: touch
    owner: app
    group: app
    mode: '0644'

# Set specific modification time
- ansible.builtin.file:
    path: /tmp/timestamp-file
    state: touch
    modification_time: "202606020000.00"

Parameters

ParameterDescription
pathFile path to touch (required)
statetouch (required for this operation)
ownerFile owner
groupFile group
modeFile permissions
modification_timeSet mtime (format: YYYYMMDDHHmm.ss or preserve)
access_timeSet atime (same format or preserve)

Common Patterns

Create Log File Before Service Start

- name: Ensure log file exists
  ansible.builtin.file:
    path: /var/log/myapp/app.log
    state: touch
    owner: app
    group: app
    mode: '0644'
  changed_when: false  # Don't report as change every run

- name: Start application
  ansible.builtin.service:
    name: myapp
    state: started

Deployment Marker File

- name: Create deployment marker
  ansible.builtin.file:
    path: /opt/app/.last-deployed
    state: touch
    mode: '0644'
  # File's mtime = when deployment happened

Lock File Pattern

- name: Create lock file
  ansible.builtin.file:
    path: /tmp/ansible-deploy.lock
    state: touch
    mode: '0644'

# ... do work ...

- name: Remove lock file
  ansible.builtin.file:
    path: /tmp/ansible-deploy.lock
    state: absent

Create Only If Missing (Don't Update Timestamp)

# Use copy with force=false instead of touch
- name: Create file only if it doesn't exist
  ansible.builtin.copy:
    content: ""
    dest: /etc/myapp/custom.conf
    force: false  # Won't overwrite/update existing
    owner: app
    mode: '0644'

Create Multiple Files

- name: Ensure all log files exist
  ansible.builtin.file:
    path: "{{ item }}"
    state: touch
    owner: app
    group: app
    mode: '0644'
  loop:
    - /var/log/myapp/app.log
    - /var/log/myapp/error.log
    - /var/log/myapp/access.log
  changed_when: false

Preserve Timestamps

# Touch without changing modification time
- name: Ensure file exists (preserve mtime)
  ansible.builtin.file:
    path: /etc/myapp/config.conf
    state: touch
    modification_time: preserve
    access_time: preserve

touch vs Other Create Methods

MethodCreates FileUpdates mtimeContent
file: touch✅ (empty)✅ (every run)No
copy: content=""✅ (empty)Only on createOptional
copy: force=false✅ (only if missing)NoOptional
template✅Only on changeYes

Troubleshooting

IssueFix
Always reports "changed"Add changed_when: false if timestamp update is expected
Parent directory doesn't existCreate dir first: file: state=directory
Permission deniedUse become: true
Want content in fileUse copy with content instead

Best Practices

  1. Use changed_when: false if touch is just ensuring existence
  2. Create parent directories first — touch doesn't create parents
  3. Use copy force=false if you only want to create, never update
  4. Set owner/group/mode explicitly — don't rely on umask
  5. Use as deployment markers — mtime becomes "last deployed" timestamp

Conclusion

Use file: state=touch to create empty files or update timestamps. Add changed_when: false when the touch is just a precondition. Use copy: force=false when you only want to create without updating existing files. Set permissions explicitly to avoid umask-dependent behavior.