Ansible Permission Denied on Remote Temp Path: Fix Every Cause
By Luca Berton · Published 2024-01-01 · Category: installation
Fix Ansible 'Permission denied on the temporary files Ansible needs to create' error. Covers remote_tmp path issues, become nopasswd, polyinstantiated /tmp.
"Failed to set permissions on the temporary files Ansible needs to create" is one of the most confusing Ansible errors because the root cause varies widely — from become configuration to filesystem mounts to SELinux policies.
The Error
fatal: [host]: FAILED! => {
"msg": "Failed to set permissions on the temporary files Ansible needs
to create when becoming an unprivileged user
(rc: 1, err: chmod: changing permissions of '/tmp/ansible-tmp-xxx/': Operation not permitted)."
}
Or the related:
"Could not make dir /home/user/.ansible/tmp: [Errno 13] Permission denied"
See also: Ansible become: Fix Missing sudo Password & Privilege Escalation (Guide)
Cause 1: become + Unprivileged User (Most Common)
When you use become: true with become_user: appuser, Ansible creates temp files as the SSH user, then tries to change ownership for the become user.
# ❌ This triggers the error
- name: Deploy as app user
ansible.builtin.copy:
src: config.conf
dest: /opt/app/config.conf
become: true
become_user: appuser
Fix: allow_world_readable_tmpfiles
# ansible.cfg
[defaults]
allow_world_readable_tmpfiles = true
⚠️ This makes temp files world-readable momentarily. Acceptable for most use cases, avoid for highly sensitive data.
Fix: Use pipelining (Better)
# ansible.cfg
[ssh_connection]
pipelining = true
Pipelining avoids temp files entirely by piping the module code through SSH. This is the best solution — faster and no temp file permission issues.
Requirement: The target host must have requiretty disabled in sudoers:
# On target host, ensure this is NOT present (or commented out):
# /etc/sudoers
# Defaults requiretty ← Comment this out or remove
Fix: Install acl Package
# The acl package allows Ansible to use POSIX ACLs for temp file permissions
- name: Install ACL support
ansible.builtin.apt:
name: acl
state: present
become: true
With acl installed, Ansible uses setfacl to grant the become user access without making files world-readable.
Cause 2: Custom remote_tmp Path Doesn't Exist
# ansible.cfg — custom temp path
[defaults]
remote_tmp = /opt/ansible/tmp
If /opt/ansible/tmp doesn't exist or the SSH user can't write to it:
Fix
# Create the directory first
- name: Ensure Ansible temp directory exists
ansible.builtin.file:
path: /opt/ansible/tmp
state: directory
mode: '0777'
owner: root
group: root
become: true
Or use the default (~/.ansible/tmp) which Ansible creates automatically.
See also: Ansible 'This command has to be run under the root user' Error: Fix with become
Cause 3: /tmp Mounted with noexec
Some security-hardened systems mount /tmp with noexec:
# Check mount options
mount | grep /tmp
# tmpfs on /tmp type tmpfs (rw,nosuid,nodev,noexec)
# ^^^^^^
Fix: Change remote_tmp
# ansible.cfg — use a path that allows execution
[defaults]
remote_tmp = /var/tmp/.ansible/tmp
# Or per-host in inventory
[hardened_servers]
host1 ansible_remote_tmp=/var/tmp/.ansible/tmp
Cause 4: Polyinstantiated /tmp (PAM)
RHEL/CentOS with pam_namespace gives each user their own /tmp:
# /etc/security/namespace.conf
/tmp /tmp-inst/ level root,adm
When the SSH user writes to /tmp, the become user sees a different /tmp.
Fix
# ansible.cfg
[defaults]
remote_tmp = /var/tmp/.ansible/tmp
# Or enable pipelining
[ssh_connection]
pipelining = true
See also: Ansible PowerShell & sudo Become Error: 'powershell is not compatible' Fix
Cause 5: SELinux Blocking Temp Files
# Check SELinux denials
ausearch -m AVC -ts recent | grep ansible
Fix
# Create a policy module for the denial
audit2allow -a -M ansible_tmp
semodule -i ansible_tmp.pp
# Or set correct context
chcon -t user_tmp_t /tmp/ansible-*
Cause 6: Home Directory Doesn't Exist
If the SSH user has no home directory, ~/.ansible/tmp can't be created:
# The user exists but has no home:
getent passwd deploy
# deploy:x:1001:1001::/home/deploy:/bin/bash
ls -la /home/deploy
# ls: cannot access '/home/deploy': No such file or directory
Fix
# Create the home directory
mkdir -p /home/deploy
chown deploy:deploy /home/deploy
Or set a custom temp path:
# ansible.cfg
[defaults]
remote_tmp = /tmp/.ansible-${USER}/tmp
Cause 7: Container/Chroot Targets
Containers often have restrictive filesystems:
# ❌ Connecting to a container with limited filesystem
- hosts: containers
connection: docker
tasks:
- ansible.builtin.copy: # Fails — no /tmp or no permissions
Fix
# Use a writable path
- hosts: containers
vars:
ansible_remote_tmp: /var/tmp/.ansible/tmp
tasks:
- ansible.builtin.copy:
src: config.conf
dest: /app/config.conf
Quick Diagnosis
# 1. Check what's happening
ansible host -m ping -vvvv 2>&1 | grep -i "tmp\|perm\|denied"
# 2. Check /tmp mount options
ansible host -m shell -a "mount | grep tmp"
# 3. Check ACL support
ansible host -m shell -a "which setfacl"
# 4. Check SELinux
ansible host -m shell -a "getenforce"
# 5. Check home directory
ansible host -m shell -a "ls -la ~"
The Fix Priority Order
Enable pipelining — best solution, avoids the problem entirely Install acl — second best, secure permission handling Setallow_world_readable_tmpfiles — quick fix, slight security trade-off
Change remote_tmp — for noexec/polyinstantiated /tmp
Fix the underlying issue — create home dirs, fix mounts, etc.
FAQ
Why does this only happen with become_user?
When you become: root, Ansible can change file permissions freely. When you become_user: appuser (non-root), the SSH user creates files that the become user can't access, and the become user can't chmod files they don't own. That's the fundamental permission mismatch.
Is allow_world_readable_tmpfiles a security risk?
It makes temp files readable by any user on the system for a brief moment during task execution. For most environments this is acceptable — the files are deleted after the task completes. Avoid it only on multi-tenant systems where users actively try to read each other's temp files.
Does pipelining work with all connection types?
Pipelining works with SSH connections. It doesn't apply to local, docker, or winrm connections. For SSH, it requires Defaults !requiretty in sudoers on the target.
Conclusion
The "permission denied on temp files" error has six different causes but two reliable fixes: enable pipelining (avoids temp files) or install the acl package (handles permissions properly). Start with pipelining — it's faster and eliminates the problem entirely.
Related Articles
• Failed to Connect via SSH: Troubleshooting • Ansible shell vs command vs raw • Ansible Undefined Variable Error: Fixes • Ansible Check Mode / Dry Run GuideCategory: installation