Ansible fails to write in the /tmp directory when security policies, such as noexec mounts or restrictive permissions, block temporary file creation. This occurs because Ansible requires a writable location to stage modules before execution. Resolving this involves adjusting the
remote_tmp configuration to point to a permitted directory like
/var/lib/ansible/tmp.
Understanding the Root Cause
When you run an Ansible playbook, the controller node transfers module files to the managed host. By default, Ansible attempts to create these files in the user's home directory or the system's
/tmp directory. Modern Linux distributions often mount
/tmp with the
noexec flag for security reasons. This flag prevents any executable files from running in that directory. If Ansible tries to copy a Python script there and execute it, the operation will fail with permission denied errors. Additionally, some environments use sticky bits or ACLs that restrict write access to specific users, further complicating the process.
The error message typically resembles "Failed to set permissions on the temporary directory" or "Could not find a usable python." These messages indicate that the underlying issue is not with your playbook logic but with the environment's ability to store and execute transient data. It is crucial to distinguish between a network connectivity issue and a local filesystem restriction. If you can SSH into the host manually and create files, the connection is fine. The problem lies specifically in where those files are placed.
For more context on how security settings impact system operations, you might find
Understanding Strange Processes Running as User and Root: A Potential Sign of Server Compromise helpful, as malicious actors often exploit similar permission vulnerabilities. However, in this case, the restrictions are intentional administrative controls rather than signs of compromise.
Configuring Remote Temporary Paths
The most robust solution is to configure Ansible to use a different temporary directory on the remote host. You can achieve this by setting the
remote_tmp parameter. This parameter tells Ansible where to stage its modules instead of relying on the default behavior. You can set this globally in your
ansible.cfg file or locally within your inventory or playbook.
To modify the global configuration, locate your
ansible.cfg file, which is usually found in
/etc/ansible/ansible.cfg or your home directory. Add or update the following section:
[defaults]
remote_tmp = /var/lib/ansible/tmp
After saving the file, ensure that the specified directory exists on all managed nodes. If it does not exist, Ansible may still fail. You can create this directory using a simple shell command or include it in your initial provisioning scripts. For example, you might add a task to create the directory if it is missing. This approach ensures that every subsequent play uses the new path without requiring individual adjustments.
Alternatively, you can override this setting per-host in your inventory file. Add the variable
ansible_remote_tmp=/var/lib/ansible/tmp to the host definition. This method is useful when only specific servers have restricted
/tmp directories while others do not. It provides granular control over the execution environment.
If you prefer not to change global settings, you can also specify the temporary directory via the command line using the
--tmpdir flag. This is less common for persistent setups but useful for one-off debugging sessions. Keep in mind that command-line flags often take precedence over configuration file settings, so be aware of the hierarchy of overrides.
Another related consideration is the
local_tmp setting, which controls where the controller stores temporary files during transfer. While less critical for the remote execution failure, ensuring both paths are valid helps maintain overall stability. If you encounter issues with large files, consider increasing the timeout values as well, though this is rarely the primary cause of write failures.
For deeper insights into troubleshooting Ansible execution issues on older systems, refer to
Troubleshooting Linux RHEL 7 - Ansible - Execute command in shell, which covers similar diagnostic steps for legacy environments.
Verifying Permissions and Ownership
Even after changing the path, you must ensure that the Ansible user has sufficient privileges to write to the new directory. The directory should be owned by the user running the Ansible tasks or have world-writable permissions with the appropriate sticky bit. Typically, creating the directory as root and then chowning it to the ansible user is the safest approach.
Check the permissions using
ls -ld /var/lib/ansible/tmp. The output should show write permissions for the user or group executing the playbook. If you are using sudo to elevate privileges, ensure that the target user can write to the directory after elevation. Sometimes, SELinux contexts can block writes even if standard Unix permissions seem correct. In such cases, you may need to adjust the SELinux context using
chcon or
restorecon.
It is also important to verify that the disk space is adequate. Although rare, a full partition can prevent temporary file creation. Use
df -h to check available space on the volume containing your new temp directory. If space is low, clean up unnecessary files or expand the partition.
Finally, test the configuration by running a simple ad-hoc command like
ansible all -m ping. If this succeeds, your configuration is likely correct. If it fails, review the verbose output (
-vvv) to see exactly where the permission denial occurs. This level of detail often reveals subtle misconfigurations in ownership or context labels.
Frequently Asked Questions
Can I disable the noexec flag on /tmp?
Disabling the noexec flag is generally discouraged because it weakens the security posture of the system. Attackers could potentially exploit this by uploading and executing malicious scripts directly in /tmp. Instead, configuring a separate writable directory for Ansible is the recommended and safer practice.
Does this issue affect Windows hosts?
No, this specific issue is limited to Linux and Unix-like systems. Windows hosts use different mechanisms for temporary files and do not rely on the same
/tmp structure. Ansible handles Windows remoting through WinRM, which manages its own temporary staging areas automatically.
What happens if I use /home/user/.ansible/tmp?
Using a subdirectory in the user's home folder is a valid alternative if
/tmp is blocked. However, ensure that the user has enough quota and that the directory is created automatically if it does not exist. Some configurations may require explicit creation tasks to avoid race conditions during initial runs.
How do I check if SELinux is blocking Ansible?
You can check the audit log for denials using
ausearch -m avc -ts recent. If you see entries related to
python or
ansible being denied access to the temporary directory, SELinux is likely the culprit. Adjusting the context with
semanage fcontext and applying it with
restorecon will resolve the issue.
Is there a performance impact from using a different tmp dir?
There is negligible performance impact unless the new directory resides on a significantly slower storage medium than
/tmp. Since
/tmp is often mounted on RAM-based filesystems like tmpfs, moving to a disk-backed directory might introduce slight latency. However, for most automation tasks, this difference is unnoticeable compared to the time taken for actual module execution.