AnsiblePilot — Master Ansible Automation

AnsiblePilot is the leading resource for learning Ansible automation, DevOps, and infrastructure as code. Browse over 1,400 tutorials covering Ansible modules, playbooks, roles, collections, and real-world examples. Whether you are a beginner or an experienced engineer, our step-by-step guides help you automate Linux, Windows, cloud, containers, and network infrastructure.

Popular Topics

About Luca Berton

Luca Berton is an Ansible automation expert, author of 8 Ansible books published by Apress and Leanpub including "Ansible for VMware by Examples" and "Ansible for Kubernetes by Example", and creator of the Ansible Pilot YouTube channel. He shares practical automation knowledge through tutorials, books, and video courses to help IT professionals and DevOps engineers master infrastructure automation.

Ansible chmod: Change File Permissions with file Module (Guide)

By Luca Berton · Published 2024-01-01 · Category: windows-automation

How to change file permissions (chmod) in Ansible with the file module. Set mode, owner, group, recursive permissions on files and directories.

Ansible chmod: Change File Permissions with file Module (Guide)

How to change file or directory permission with Ansible?

See also: Ansible Set File Permissions 755: chmod with file Module Guide

Ansible change file/directory permission

Today we're talking about the Ansible module file. The full name is ansible.builtin.file, which means that is part of the collection of modules "builtin" with ansible and shipped with it. It's a module pretty stable and out for years. It works in a different variety of operating systems. It manages files and file properties. For Windows targets, use the ansible.windows.win_file module instead.

Main Parameters

  • path _string_ (dest, name) - file path
  • owner _string_ - user
  • group _string_ - group
  • mode _raw_ - Ex: '0644' or 'u=rw,g=r,o=r'
  • state _string_ - file/absent/directory/hard/link/touch
  • setype/seuser/selevel - SELinux
This module has some parameters to perform any tasks. The only required is "path", where you specify the filesystem path of the file you're going to edit. The parameter "owner" sets the user that should own the file/directory. The parameter "group" sets the group that should own the file/directory. The parameter "mode" sets the permissions in the UNIX way of the file/directory. The state defines the type of object we are modifying, the default is "file" but we could handle also directories, hardlink, symlink, or only update the access time with the "touch" option. Let me also highlight that we could also specify the SELinux properties.

## Playbook Let's jump in a real-life playbook to change file permission with Ansible.

code

  • file.yml
---
- name: file module demo
  hosts: all
  vars:
    myfile: "/home/devops/test.txt"
  become: false
  tasks:
    - name: check permission
      ansible.builtin.file:
        path: "{{ myfile }}"
        owner: "devops"
        group: "users"
        mode: '0777'

code with ❤️ in GitHub

See also: Ansible Create User Account: user Module Complete Guide

Conclusion

Now you know how to change file or directory permission with Ansible.

Permission Format Options

Ansible accepts permissions in two formats:

- name: Set file to 644
  ansible.builtin.file:
    path: /etc/myapp/config.yml
    mode: '0644'  # Always quote and include leading 0
  become: true

Symbolic notation

- name: Set file permissions symbolically
  ansible.builtin.file:
    path: /etc/myapp/config.yml
    mode: 'u=rw,g=r,o=r'  # Same as 0644
  become: true

See also: Ansible Remove User Account: Delete Users with user Module

Common Permission Patterns

OctalSymbolicMeaningUse Case
0644u=rw,g=r,o=rOwner read/write, others readConfig files
0755u=rwx,g=rx,o=rxOwner full, others read/executeScripts, directories
0600u=rw,g=,o=Owner onlySecrets, SSH keys
0700u=rwx,g=,o=Owner only (executable)Private scripts
0444u=r,g=r,o=rRead-only for everyoneReference files
0775u=rwx,g=rwx,o=rxOwner+group fullShared directories

Advanced Examples

Change ownership and permissions together

- name: Set ownership and permissions
  ansible.builtin.file:
    path: /var/www/html
    owner: www-data
    group: www-data
    mode: '0755'
    recurse: true  # Apply to all files/dirs inside
  become: true

Set different permissions for files vs directories

- name: Find all files
  ansible.builtin.find:
    paths: /var/www/html
    file_type: file
    recurse: true
  register: website_files

- name: Set file permissions to 644
  ansible.builtin.file:
    path: "{{ item.path }}"
    mode: '0644'
  loop: "{{ website_files.files }}"
  become: true

- name: Find all directories
  ansible.builtin.find:
    paths: /var/www/html
    file_type: directory
    recurse: true
  register: website_dirs

- name: Set directory permissions to 755
  ansible.builtin.file:
    path: "{{ item.path }}"
    mode: '0755'
  loop: "{{ website_dirs.files }}"
  become: true

Make a script executable

- name: Deploy and make executable
  ansible.builtin.copy:
    src: scripts/deploy.sh
    dest: /usr/local/bin/deploy.sh
    owner: root
    group: root
    mode: '0755'  # rwxr-xr-x
  become: true

Set SELinux context

- name: Set SELinux context for web content
  ansible.builtin.file:
    path: /var/www/custom
    setype: httpd_sys_content_t
    recurse: true
  become: true

Set sticky bit, setuid, setgid

# Sticky bit on shared directory (only owner can delete their files)
- name: Set sticky bit on /tmp-style directory
  ansible.builtin.file:
    path: /shared/uploads
    mode: '1777'  # Leading 1 = sticky bit
  become: true

# Setgid on group directory (new files inherit group)
- name: Set setgid on project directory
  ansible.builtin.file:
    path: /projects/teamwork
    mode: '2775'  # Leading 2 = setgid
    group: developers
  become: true

FAQ

Why must I quote the mode value?

Without quotes, YAML interprets 0644 as the integer 644 (octal 01204), which gives wrong permissions. Always use mode: '0644' with quotes.

How do I check current permissions?

- name: Get current permissions
  ansible.builtin.stat:
    path: /etc/myapp/config.yml
  register: file_info

- name: Show permissions
  ansible.builtin.debug:
    msg: "Mode: {{ file_info.stat.mode }}, Owner: {{ file_info.stat.pw_name }}"

What does recurse: true do?

Applies the same owner/group/mode to all files AND directories inside the path. Be careful — files and directories often need different permissions (644 vs 755).

How do I change permissions on Windows?

Use ansible.windows.win_acl for Windows ACL permissions:

- name: Set Windows permissions
  ansible.windows.win_acl:
    path: C:\inetpub\wwwroot
    user: IIS_IUSRS
    rights: ReadAndExecute
    type: allow

Basic Permission Change

- ansible.builtin.file:
    path: /opt/myapp/start.sh
    mode: '0755'
  become: true

Change Owner and Group

- file:
    path: /var/www/html
    owner: www-data
    group: www-data
    recurse: true
  become: true

Common Permission Patterns

# Executable script
- file:
    path: /opt/scripts/deploy.sh
    mode: '0755'
    owner: deploy

# Private key
- file:
    path: /home/deploy/.ssh/id_rsa
    mode: '0600'
    owner: deploy
    group: deploy

# Config file (read-only)
- file:
    path: /etc/myapp/config.yml
    mode: '0644'
    owner: root
    group: root

# Shared directory
- file:
    path: /opt/shared
    state: directory
    mode: '0775'
    owner: root
    group: developers

# Sensitive config
- file:
    path: /etc/myapp/secrets.yml
    mode: '0600'
    owner: root
    group: root

Symbolic Mode

# Add execute for owner
- file:
    path: /opt/script.sh
    mode: u+x

# Add read/write for group
- file:
    path: /opt/shared/data
    mode: g+rw
    recurse: true

# Remove world read
- file:
    path: /etc/myapp/secrets
    mode: o-rwx

Recursive Permissions

# All files and directories
- file:
    path: /var/www/mysite
    owner: www-data
    group: www-data
    recurse: true
  become: true

# Different permissions for files vs directories
- shell: |
    find /var/www/mysite -type d -exec chmod 755 {} \;
    find /var/www/mysite -type f -exec chmod 644 {} \;
  become: true

SUID, SGID, Sticky Bit

# SGID on directory (new files inherit group)
- file:
    path: /opt/shared
    state: directory
    mode: '2775'
    group: developers
  become: true

# Sticky bit (only owner can delete)
- file:
    path: /tmp/shared
    state: directory
    mode: '1777'
  become: true

ACLs (Extended Permissions)

- ansible.posix.acl:
    path: /opt/myapp
    entity: deploy
    etype: user
    permissions: rwx
    state: present
  become: true

# Default ACL for new files
- ansible.posix.acl:
    path: /opt/myapp
    entity: developers
    etype: group
    permissions: rx
    default: true
    state: present
  become: true

Batch Permission Changes

- file:
    path: "{{ item.path }}"
    mode: "{{ item.mode }}"
    owner: "{{ item.owner | default('root') }}"
  loop:
    - { path: /opt/myapp/bin/start.sh, mode: '0755' }
    - { path: /opt/myapp/etc/config.yml, mode: '0644' }
    - { path: /opt/myapp/etc/secrets.yml, mode: '0600' }
    - { path: /opt/myapp/log, mode: '0755' }
  become: true

Verify Permissions

- stat:
    path: /etc/myapp/config.yml
  register: file_info

- debug:
    msg: "Mode: {{ file_info.stat.mode }}, Owner: {{ file_info.stat.pw_name }}"

- assert:
    that:
      - file_info.stat.mode == '0644'
      - file_info.stat.pw_name == 'root'

Permission Reference

ModeMeaning
0755rwxr-xr-x (executables, directories)
0644rw-r--r-- (config files)
0600rw------- (secrets, private keys)
0700rwx------ (private directories)
0775rwxrwxr-x (shared directories)
0666rw-rw-rw- (shared files, rarely used)
2775rwxrwsr-x (SGID directory)
1777rwxrwxrwt (sticky bit, like /tmp)

FAQ

Octal string vs integer?

Always quote mode as a string: mode: '0755'. Without quotes, YAML may interpret it as an integer (493), which causes unexpected permissions.

How do I change permissions without changing content?

The file module only changes metadata (permissions, owner, timestamps). It never modifies file content.

recurse doesn't set different perms for files vs dirs?

Correct — recurse applies the same mode to everything. Use find + shell for different file vs directory permissions.

Category: windows-automation

Watch the video: Ansible chmod: Change File Permissions with file Module (Guide) — Video Tutorial

Browse all Ansible tutorials · AnsiblePilot Home