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 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 Set allow_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: TroubleshootingAnsible shell vs command vs rawAnsible Undefined Variable Error: FixesAnsible Check Mode / Dry Run Guide

Category: installation

Browse all Ansible tutorials · AnsiblePilot Home