Ansible Error Guide: 'Failed to set permissions on the temporary files' — Fix Unprivileged become
Fix Ansible's 'Failed to set permissions on the temporary files Ansible needs to create when becoming an unprivileged user' by installing ACL support or adjusting become and the temp dir.
- #ansible
- #automation
- #troubleshooting
- #errors
Fixing errors like this? Get 500 free DevOps AI prompts
500 copy-paste AI prompts for the stack you actually run — one PDF, free.
Overview
This failure appears the moment a task uses become: true with a become_user that is not root and not the connecting user. Ansible writes its module payload to a temporary directory as the login user, then hands off to the unprivileged become_user, and that second user cannot read the files:
fatal: [web01]: FAILED! => {"changed": false, "msg": "Failed to set permissions on the temporary files Ansible needs to create when becoming an unprivileged user (rc: 1, err: chmod: invalid mode: 'A+user:deploy:rx:allow'\nTry 'chmod --help' for more information.\n}). For information on working around this, see https://docs.ansible.com/ansible-core/devel/playbook_guide/playbooks_privilege_escalation.html#risks-of-becoming-an-unprivileged-user"}
The root of the message is always the same: Ansible tried to grant the target become_user access to its temp files, the preferred mechanism (POSIX ACLs via setfacl) was unavailable, and the fallback failed. The user-facing symptom is that any become_user: someappuser task dies before the actual module ever runs.
Symptoms
- Tasks with
become: trueand a non-rootbecome_userfail; the same tasks run fine withbecome_user: root(the default). - The error names “becoming an unprivileged user” and often references
setfacl,chmod, orchownin theerrfield. remote_tmp(default~/.ansible/tmp) is on a filesystem mountednoacl, or theaclpackage is not installed.- Connecting as an unprivileged login user and then
become-ing to a different unprivileged user (the classic unprivileged-to-unprivileged hop). - Works on one host, fails on another whose
/tmpor home filesystem lacks ACL support.
Common Root Causes
- ACL tools missing: the
aclpackage (providingsetfacl/getfacl) is not installed on the target, so Ansible cannot grant thebecome_userread/execute on its temp dir. - Filesystem mounted without ACL support: the partition holding
remote_tmpis mountednoacl, or is a filesystem type that doesn’t support POSIX ACLs, sosetfaclfails even when installed. - Unprivileged-to-unprivileged become: you connect as
deployandbecome_user: appuser. Neither is root, so Ansible must widen permissions on the temp files — exactly the case that needs ACLs. allow_world_readable_tmpfilesmisunderstanding: teams flip this expecting a fix, but it only helps when the content isn’t sensitive and world-readable temp files are acceptable.remote_tmppointing at a restrictive path: a customremote_tmpunder a directory thebecome_usercan’t traverse.
Diagnostic Workflow
First confirm it is specifically the unprivileged-become path by re-running the single task with maximum verbosity:
ansible-playbook site.yml --limit web01 --tags deploy -vvv
Look in the -vvv output for the temp dir path (ANSIBLE_REMOTE_TEMP / ~/.ansible/tmp/ansible-tmp-...) and the exact err — it tells you whether setfacl was missing or the mount rejected it.
Check whether ACL tooling exists on the target and whether the temp filesystem supports it:
ansible web01 -m raw -a 'which setfacl; rpm -q acl 2>/dev/null || dpkg -l acl 2>/dev/null | tail -1'
ansible web01 -m raw -a 'df -P ~/.ansible/tmp | tail -1; mount | grep -E "$(df -P ~/.ansible/tmp | tail -1 | awk "{print \$1}")"'
Reproduce the minimal failing case to isolate it from the rest of the play:
- name: Reproduce unprivileged become
hosts: web01
become: true
become_user: appuser
tasks:
- name: Trivial command as unprivileged user
ansible.builtin.command: id
Verify the fix candidate — installing acl — resolves it:
- name: Ensure ACL support then test become
hosts: web01
tasks:
- name: Install acl package
become: true
ansible.builtin.package:
name: acl
state: present
- name: Now try the unprivileged become
become: true
become_user: appuser
ansible.builtin.command: id
Example Root Cause Analysis
A deploy playbook connected as deploy and used become: true with become_user: appuser to run application steps as the service account. It passed on older hosts and failed on a freshly provisioned minimal image with the ACL error citing setfacl: command not found.
The -vvv output showed Ansible trying to setfacl -m u:appuser:r-x on ~/.ansible/tmp/ansible-tmp-... and getting “command not found”. The minimal image shipped without the acl package, and the older hosts happened to have it pulled in as a dependency of another tool. Because both the login user (deploy) and the target (appuser) were unprivileged, Ansible could not simply chown the temp files as root — it needed ACLs, which weren’t there.
The fix was a pre_tasks block that installs acl with become: true (escalating to root, where no ACL is needed) before any unprivileged-become task runs. After that, the become_user: appuser tasks succeeded on every host. The team added acl to their base image build so new hosts never hit it again.
Prevention Best Practices
- Bake
aclinto your base image or install it in an earlybecome: true(to root) task, before anybecome_usertargets a non-root account. - Prefer becoming root when the task doesn’t strictly need to run as a specific service user — root-to-anything doesn’t need ACLs.
- Keep
remote_tmpon an ACL-capable filesystem; avoid pointing it at partitions mountednoaclor at exotic filesystem types. - Set
remote_tmpunder the become_user’s own home when appropriate, so the target user already owns the path. - Only use
allow_world_readable_tmpfiles = trueas a deliberate, documented choice when the transferred content is not sensitive — it makes temp files world-readable. - Test the unprivileged-become path in CI/Molecule on a minimal image so a missing
aclpackage is caught before production.
Quick Command Reference
# Re-run the failing task with full verbosity to see the real err
ansible-playbook site.yml --limit web01 -vvv
# Check for setfacl and the acl package on the target
ansible web01 -m raw -a 'which setfacl; dpkg -l acl 2>/dev/null | tail -1 || rpm -q acl'
# Install acl fleet-wide (escalates to root, which needs no ACL)
ansible all -b -m package -a 'name=acl state=present'
# Inspect the temp filesystem's mount options for noacl
ansible web01 -m raw -a 'mount | grep -Ei "acl|/tmp|home"'
# Confirm the fix with a trivial unprivileged-become command
ansible web01 -b --become-user appuser -m command -a id
Conclusion
“Failed to set permissions on the temporary files Ansible needs to create when becoming an unprivileged user” is almost always the unprivileged-to-unprivileged become path meeting a host without POSIX ACL support. Read the err field in -vvv to confirm whether setfacl is missing or the mount rejects ACLs, install the acl package (ideally in your base image), and prefer becoming root when a specific service user isn’t required. Once ACL support is present on the temp filesystem, become_user to a non-root account works cleanly.
More Ansible prompts & error guides
Every Ansible AI prompt and troubleshooting guide, in one place.
Get 500 Battle-Tested DevOps AI Prompts — Free
500 battle-tested, copy-paste AI prompts engineered by a senior systems engineer — every one with fill-in placeholders and safety/back-out notes. Drop your email and it's yours.
- 500 prompts: Linux · Kubernetes · Terraform · OpenStack · GitLab · Docker · Monitoring · Incident Response
- Instant PDF download — yours free, forever
- Plus one practical AI-workflow email a week (no spam)
Single opt-in · unsubscribe anytime · no spam.