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 Permission Denied (Errno 13): Fix File Access Errors

By Luca Berton · Published 2024-01-01 · Category: installation

Fix Ansible Permission denied [Errno 13] errors. Resolve file permission, become/sudo, SELinux, and directory access issues with troubleshooting steps.

Ansible Permission Denied (Errno 13): Fix File Access Errors

Introduction

Welcome to another episode of Ansible Pilot! I'm Luca Berton, and today we're delving into Ansible troubleshooting, focusing on the pesky "Permission Denied Errno 13" error. Join me as we explore the intricacies of this issue, reproduce it in a live Playbook, and learn how to effectively resolve it using privilege escalation in Ansible Playbooks.

See also: Ansible 'fatal: template error while templating string' Fix (Guide)

The Demo

Let's jump right into a live Playbook to understand how to troubleshoot the Ansible fatal error [Errno 13] Permission denied and fix it in an Ansible Playbook.

Error Code

# permissiondenied_error.yml
---
- name: set environment Playbook
  hosts: all
  gather_facts: false
  vars:
    os_environment:
      - key: EDITOR
        value: vi
  tasks:
    - name: customize /etc/environment
      ansible.builtin.lineinline:
        dest: "/etc/environment"
        state: present
        regexp: "^{{ item.key }}="
        line: "{{ item.key }}={{ item.value }}"
      with_items: "{{ os_environment }}"

Error Execution

ansible-pilot $ ansible-playbook -i virtualmachines/demo/inventory troubleshooting/permissiondenied_error.yml
PLAY [set environment Playbook] ***********************************************************************
TASK [customize /etc/environment] *****************************************************************
An exception occurred during task execution. To see the full traceback, use -vvv. The error was: PermissionError: [Errno 13] Permission denied: b'/home/devops/.ansible/tmp/ansible-tmp-1645543127.772594-89712-144540003805636/tmpvhoh4q83' -> b'/etc/environment'
failed: [demo.example.com] (item={'key': 'EDITOR', 'value': 'vi'}) => {"ansible_facts": {"discovered_interpreter_python": "/usr/libexec/platform-python"}, "ansible_loop_var": "item", "changed": false, "item": {"key": "EDITOR", "value": "vi"}, "msg": "The destination directory (/etc) is not writable by the current user. Error was: [Errno 13] Permission denied: b'/etc/.ansible_tmp_hwdwg3denvironment'"}
PLAY RECAP ****************************************************************************************
demo.example.com           : ok=0    changed=0    unreachable=0    failed=1    skipped=0    rescued=0    ignored=0
ansible-pilot $

Fix Code

# permissiondenied_fix.yml
---
- name: set environment Playbook
  hosts: all
  gather_facts: false
  become: true
  vars:
    os_environment:
      - key: EDITOR
        value: vi
  tasks:
    - name: customize /etc/environment
      ansible.builtin.lineinline:
        dest: "/etc/environment"
        state: present
        regexp: "^{{ item.key }}="
        line: "{{ item.key }}={{ item.value }}"
      with_items: "{{ os_environment }}"

Fix Execution

ansible-pilot $ ansible-playbook -i virtualmachines/demo/inventory troubleshooting/permissiondenied_fix.yml
PLAY [set environment Playbook] ***********************************************************************
TASK [customize /etc/environment] *****************************************************************
changed: [demo.example.com] => (item={'key': 'EDITOR', 'value': 'vi'})
PLAY RECAP ****************************************************************************************
demo.example.com           : ok=1    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0
ansible-pilot $

Conclusion

In this tutorial, we've successfully troubleshooted the Ansible [Errno 13] Permission Denied error and implemented a fix in an Ansible Playbook. By leveraging privilege escalation, we overcame the Permission Denied hurdle and ensured seamless execution.

I hope this guide proves valuable in unraveling similar challenges during your Ansible automation endeavors. If you found this information helpful, consider subscribing for more Ansible insights.

See also: Ansible 'Failure Downloading' Error: Fix get_url & uri Module Issues

Common Causes and Fixes

Missing become (sudo)

# WRONG - no privilege escalation
- ansible.builtin.copy:
    src: config.yml
    dest: /etc/myapp/config.yml

# CORRECT - ansible.builtin.copy: src: config.yml dest: /etc/myapp/config.yml become: true

Directory doesn't exist

- name: Create directory first
  ansible.builtin.file:
    path: /opt/myapp/config
    state: directory
    owner: appuser
    mode: '0755'
  become: true

- name: Then copy file ansible.builtin.copy: src: config.yml dest: /opt/myapp/config/config.yml owner: appuser become: true

Wrong file ownership

- name: Fix ownership
  ansible.builtin.file:
    path: /opt/myapp
    state: directory
    owner: appuser
    group: appgroup
    recurse: true
  become: true

SELinux blocking access

# Check SELinux status
- command: getenforce
  register: selinux_status

# Restore SELinux context - ansible.builtin.command: restorecon -Rv /opt/myapp become: true

# Or set correct context - community.general.sefcontext: target: '/opt/myapp(/.*)?' setype: httpd_sys_content_t state: present become: true

Debugging Steps

# Check current permissions
- ansible.builtin.stat:
    path: /etc/myapp/
  register: dir_info

- debug: msg: | Mode: {{ dir_info.stat.mode }} Owner: {{ dir_info.stat.pw_name }} Group: {{ dir_info.stat.gr_name }}

# Check who you're running as - command: whoami register: current_user - command: id register: current_id

See also: Ansible 'Missing Required Arguments' Error: Fix Missing Module Parameters

Common Permission Patterns

| Path | Typical Owner | Mode | Needs become | |------|--------------|------|-------------| | /etc/ | root | 644/755 | Yes | | /opt/app/ | appuser | 755 | Usually | | /var/log/ | syslog/root | 640 | Yes | | /tmp/ | any | 1777 | No | | ~/ | user | 755 | No |

Temporary Directory Issues

# Ansible uses /tmp for module execution
# If /tmp is mounted noexec, override:
# ansible.cfg
[defaults]
remote_tmp = /var/tmp/.ansible/tmp

FAQ

Errno 13 on "copy" module but file exists?

Check the parent directory permissions. You need write permission on the directory to create/modify files in it.

Works with SSH but fails with Ansible?

Ansible may run as a different user or without a login shell. Check ansible_user and become settings.

"Permission denied" during package install?

- apt:
    name: nginx
  become: true  # Package management requires root

How do I debug permission issues?

ansible-playbook site.yml -vvvv
# Shows exact command and user context

The Error

fatal: [web1]: FAILED! => {"msg": "[Errno 13] Permission denied: '/etc/myapp/config.conf'"}

Quick Fixes

Add become (sudo)

# WRONG — running as unprivileged user
- copy:
    src: config.conf
    dest: /etc/myapp/config.conf

# CORRECT — use become for privileged paths - ansible.builtin.copy: src: config.conf dest: /etc/myapp/config.conf become: true

Fix File Permissions

- ansible.builtin.file:
    path: /opt/myapp/data
    state: directory
    mode: '0755'
    owner: deploy
    recurse: true
  become: true

Fix Parent Directory Permissions

# Often the DIRECTORY permissions matter, not the file
- file:
    path: /opt/myapp
    state: directory
    mode: '0755'
  become: true

- copy: src: app.conf dest: /opt/myapp/app.conf become: true

Common Causes

1. Missing become

# Writing to system paths requires sudo
- hosts: all
  become: true  # Apply to all tasks in play
  tasks:
    - copy:
        src: nginx.conf
        dest: /etc/nginx/nginx.conf

2. Wrong become_user

# Run as specific user
- copy:
    src: app.conf
    dest: /home/deploy/app.conf
  become: true
  become_user: deploy

3. Ansible tmp Directory

# Remote user can't write to /tmp/.ansible/tmp
# Fix in ansible.cfg:
[defaults]
remote_tmp = /tmp/.ansible-${USER}/tmp

4. SELinux Blocking

# Check SELinux denials
ausearch -m AVC -ts recent

# Fix context restorecon -rv /opt/myapp/

# Or set context with Ansible
- community.general.sefcontext:
    target: '/opt/myapp(/.*)?'
    setype: httpd_sys_content_t
  become: true

5. NFS/Mounted Filesystem

# NFS with root_squash prevents root access
# In ansible.cfg, use become_user matching NFS export:
[privilege_escalation]
become_user = nfsuser

Debugging

# Check current user and permissions
- command: whoami
  register: current_user

- command: ls -la /etc/myapp/ register: dir_perms become: true

- debug: msg: | Running as: {{ current_user.stdout }} Directory: {{ dir_perms.stdout }}

# Verbose mode shows permission details
ansible-playbook site.yml -vvv

Common Permission Patterns

# System config files
- template:
    src: app.conf.j2
    dest: /etc/myapp/app.conf
    mode: '0644'
    owner: root
    group: root
  become: true

# Application files - copy: src: app.jar dest: /opt/myapp/app.jar mode: '0755' owner: appuser group: appuser become: true

# SSH keys - copy: content: "{{ vault_ssh_key }}" dest: /home/deploy/.ssh/id_rsa mode: '0600' owner: deploy become: true no_log: true

# Log directories - file: path: /var/log/myapp state: directory mode: '0755' owner: appuser become: true

FAQ

"Permission denied" but I'm using become?

Check if become_method is correct (default is sudo). Verify the remote user has sudo privileges: sudo -l.

Permission denied on the Ansible controller?

# Local file permissions — use delegate_to or local_action
- copy:
    src: /restricted/file
    dest: /tmp/file
  delegate_to: localhost
  become: true  # Needs sudo on controller

How to debug SELinux issues?

# Check for denials
sudo audit2why < /var/log/audit/audit.log
# Generate policy
sudo audit2allow -a -M mypolicy

Related Articles

how Ansible become works under the hoodhow Ansible inventory worksloop_control in Ansible

Category: installation

Watch the video: Ansible Permission Denied (Errno 13): Fix File Access Errors — Video Tutorial

Browse all Ansible tutorials · AnsiblePilot Home