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.

Introduction
Welcome to another episode of Ansible Pilot! I'm Luca Berton, and today we're delving into Ansible troubleshooting, focusing on the pesky PermissionError: [Errno 13] Permission denied 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: trueDirectory 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: trueWrong file ownership
- name: Fix ownership
ansible.builtin.file:
path: /opt/myapp
state: directory
owner: appuser
group: appgroup
recurse: true
become: trueSELinux 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: trueDebugging 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_idSee 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/tmpFAQ
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 rootHow do I debug permission issues?
ansible-playbook site.yml -vvvv
# Shows exact command and user contextThe 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: trueFix File Permissions
- ansible.builtin.file:
path: /opt/myapp/data
state: directory
mode: '0755'
owner: deploy
recurse: true
become: trueFix 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: trueCommon 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.conf2. Wrong become_user
# Run as specific user
- copy:
src: app.conf
dest: /home/deploy/app.conf
become: true
become_user: deploy3. Ansible tmp Directory
# Remote user can't write to /tmp/.ansible/tmp
# Fix in ansible.cfg:
[defaults]
remote_tmp = /tmp/.ansible-${USER}/tmp4. 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: true5. NFS/Mounted Filesystem
# NFS with root_squash prevents root access
# In ansible.cfg, use become_user matching NFS export:
[privilege_escalation]
become_user = nfsuserDebugging
# 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 -vvvCommon 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: trueFAQ
"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 controllerHow to debug SELinux issues?
# Check for denials
sudo audit2why < /var/log/audit/audit.log
# Generate policy
sudo audit2allow -a -M mypolicyRelated Articles
Category: installation
Watch the video: Ansible Permission Denied (Errno 13): Fix File Access Errors — Video Tutorial