Fixing Ansible's 'sudo: sorry, you must have a tty to run sudo' Error

intermediate🔧 Ansible2026-05-24| Ansible running against RHEL 5/6, CentOS 5/6, or legacy Fedora distributions. Also occurs on hardened Debian or Ubuntu systems.

Error Message

sudo: sorry, you must have a tty to run sudo
#ansible#sudo#become#tty#sudoers#privilege-escalation

The Problem

You’ve double-checked your SSH keys and sudo rights, yet your Ansible playbook crashes immediately. The error message is blunt: sudo: sorry, you must have a tty to run sudo. This isn't a bug in your code. It’s a security gatekeeper on the remote host blocking non-interactive automation.

This usually happens when managing legacy Red Hat environments (RHEL 6 or CentOS 6). It also pops up in highly secured clusters where the policy forbids running sudo without a real interactive terminal session.

TL;DR: The Quick Fix

The most reliable solution is disabling the requiretty setting on the target server. Log into the remote machine, run visudo, and comment out this line:

# Defaults    requiretty

If you cannot modify the server's security policy, try enabling SSH Pipelining in your local ansible.cfg to change how commands are streamed:

[ssh_connection]
pipelining = True

Detailed Root Cause

Linux kernels use pseudo-terminals (PTYs) for interactive sessions. Historically, distributions like RHEL 5 and 6 shipped with Defaults requiretty enabled in the /etc/sudoers file. This setting ensures that sudo only works if a user is physically or virtually 'typed' at a terminal.

Ansible prioritizes speed. By default, it executes modules by streaming them over SSH without allocating a PTY. This makes the automation faster but triggers the security check. When Ansible attempts to become: yes, the remote system sees a non-interactive stream instead of a TTY and kills the process instantly.

Modern security standards generally view requiretty as having low security value. Consequently, most modern distros like Ubuntu, Debian, and RHEL 7+ have removed this restriction entirely.

Fix Approach 1: Modifying the Sudoers File (Recommended)

Addressing the problem at the source is the cleanest route. You have two ways to apply this change safely using the visudo tool.

1. Disable it globally

Run sudo visudo on the target machine. Locate the requiretty line and prefix it with a # character.

# Find this line:
Defaults    requiretty

# Change it to:
# Defaults    requiretty

2. Disable it for the Ansible user

You might prefer keeping the policy for other users while exempting your automation account (e.g., ansible_user). Add this specific rule to the end of the file:

Defaults:ansible_user !requiretty

Fix Approach 2: Enabling SSH Pipelining

If you are managing 500+ legacy servers, manual edits aren't feasible. Enabling pipelining reduces the number of SSH operations required to run a module. This often bypasses the TTY requirement by changing how the command payload is delivered to the remote shell.

Edit your ansible.cfg file in your project root:

[ssh_connection]
pipelining = True

Note: Pipelining can speed up execution by 30% or more. However, if your sudo setup requires a password (rather than NOPASSWD), pipelining might cause the task to hang. Always test this in staging first.

Fix Approach 3: Forcing a TTY (The Last Resort)

You can trick the remote host by forcing Ansible to allocate a pseudo-terminal. This mimics a real user session. Use the -tt flag within your SSH arguments.

In your ansible.cfg:

[ssh_connection]
ssh_args = -C -o ControlMaster=auto -o ControlPersist=60s -tt

Why this is a last resort: Forcing a TTY often breaks modules that expect clean data streams. TTYs can inject hidden control characters or wrap long lines of output, leading to unpredictable parsing errors in Ansible.

Verification: Confirming the Fix

Once you've applied a fix, run a quick ad-hoc command. This verifies that privilege escalation now works across your inventory:

ansible all -m shell -a "whoami" --become

If the command returns root for your hosts instead of the TTY error, the hurdle is cleared.

Summary

  • The cause: A legacy requiretty setting in /etc/sudoers blocks non-interactive sudo calls.
  • Best fix: Comment out Defaults requiretty using visudo.
  • Scale fix: Enable pipelining = True in your Ansible configuration to streamline connections.

Related Error Notes